Skybox and culling (because of model bound)

Ok, hello everybody.

For some time already, i “often” have a bug with the skybox: when i attach the skybox to node which is not the rootNode, i get some strange artifact that make my entire world disappear when i look in some directions.

This doesn’t happen on small projects, so it was impossible to find a test case.

After some research, i found that it’s because of the model bound : when the model bound of the node (the one that contains the sky spatial) doesn’t intersect with the camera’s fov, it’s just culled, and all of its children are also culled.

Ok, in a perfectly mathematical world, my node should have a bounding volume of at least the bounding volume of its children. As a skybox has a bounding volume of infinite in all directions, my node should have the same.

It happens that it’s not the case, for some reason i don’t know.

I still managed to do a test case, with that in mind.

[java]
package real.tests;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.util.SkyFactory;
import real.client.controllers.SkyBoxMover;

/**
*

  • @author Bubuche
    */
    public class SkyBoxBug extends SimpleApplication
    {
    public static void main(String args[])
    {
    SkyBoxBug app = new SkyBoxBug();

    app.start();
    }

@Override
public void simpleInitApp()
{
Node nodeWithSky = new Node(“i have a sky”);
flyCam.setMoveSpeed(15);

Box b = new Box(1, 1, 1);
Geometry geom = new Geometry("Box", b);
nodeWithSky.attachChild(geom);

Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
geom.setMaterial(mat);

nodeWithSky.attachChild(geom);


Spatial sky = SkyFactory.createSky(
        assetManager, "Textures/Sky/Bright/BrightSky.dds", false);
//sky.addControl(new SkyBoxMover());
nodeWithSky.attachChild(sky);

rootNode.attachChild(nodeWithSky);
nodeWithSky.updateModelBound();

cam.setLocation(new Vector3f(0, 0, 20));

}
}

[/java]

If you turn the camera more than pi/4 on the left (or the right) all the scene just disappear (you got a black screen).
i KNOW that this line

nodeWithSky.updateModelBound();

is a bit strange, but without it the test doesn’t work. For a reason i don’t know, i don’t have bounds for my node without it. Maybe it’s done after. I don’t know where this method is called in jme, so i can’t say why i have problems with my programs.

Ok, that said i tried to create a solution. I wanted something generic enough.
Here we go :

[java]
package real.client.controllers;

import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;

/**
*

  • @author Bubuche
    */
    public class SkyBoxMover extends AbstractControl implements Cloneable
    {
    public Vector3f position;
    public Vector3f out;

public SkyBoxMover()
{
position = new Vector3f();
out = new Vector3f();
}

@Override
protected void controlUpdate(float tpf)
{

}

@Override
protected void controlRender(RenderManager rm, ViewPort vp)
{
Camera camera;
camera = vp.getCamera();
position.set(camera.getLocation());

spatial.worldToLocal(position, out);
//spatial.updateModelBound();
spatial.setLocalTranslation(position);

}

@Override
public SkyBoxMover cloneForSpatial(Spatial spatial)
{
SkyBoxMover result = new SkyBoxMover();
spatial.addControl(result);
return result;
}
}
[/java]

To test it, just take the “test case” and remove the “//” in front of sky.addControl(new SkyBoxMover());

However, i don’t know what are the consequences of this fix. The way i do it, you can even have multiple camera to render your scene and it should still work, so i am not “delaying” the problem to bigger projects.

My solution is basically : move the skybox to the camera’s location every frame for each and every camera.

Fix the source of the bug is also a possibility ^^.

ok, the “edit” button just disappeared so :

i notice that in my controller i do that:

spatial.worldToLocal(position, out);
//spatial.updateModelBound();
spatial.setLocalTranslation(position);

which is stupid.

However, it doesn’t work with “out” instead of “position” in the last line. I don’t know why.
So, just remove spatial.worldToLocal(position, out);.

The other thing you can do is to set CullHint.Never on the parents of the sky box back up to root node (which I think is never culled anyway).

I already tried this. It doesn’t work.

You can test : remove my fix (otherwise you’ll not be able to test it :D)

then under the line nodeWithSky.attachChild(sky);

add the line

nodeWithSky.setCullHint(Spatial.CullHint.Never);

Then run, turn the camera. The world disappear.

@bubuche said: I already tried this. It doesn't work.

You can test : remove my fix (otherwise you’ll not be able to test it :D)

then under the line nodeWithSky.attachChild(sky);

add the line

nodeWithSky.setCullHint(Spatial.CullHint.Never);

Then run, turn the camera. The world disappear.

The “world” meaning both the sky and the blue box? Or just the blue box?

the sky and the blue box.

ok, actually, i don’t know for the blue box, cause you know … when i turn the camera to remove the world, i already don’t see the blue box any longer. I’ll add a new bow then give to you the answer (let me a minute).

EDITED :

well, i added a red box and … when i am between the 2 boxes, i don’t have the bug. I need to be outside of them to have the problem (and then i can’t see them).

However, when i have this problem in real projects, everything vanish (not just the sky). I’ll try to reproduce this bug.

I bet you will need to put cull hint never on the root node also. I think the reason this never comes up is because usually the root node has the world the player is viewing and so there is always some part of it visible.

Adding a second box will probably make everything work… since I suspect as long as one box is in view then you will see your sky.