Z order

Hello,

  I'm super new to jME and I'm working on a test program and ran across a problem.  I have been a Java3D dev so maybe I'm a bit confused of how the scene graph works in jME compared to Java3D. 



The code below shows two Shapes attached to their respective Nodes which are then attached to the root node.  Notice the z-axis values for each.  q1's z-axis value is -5 while quad's z-axis value is -25. 



In Java3D, quad would be rendered first and THEN q1 b/c of the z-value.



However, when I run this example in jME, it appears that q1 is rendered first AND THEN quad.



The problem: quad one covers up q1 (ie, q1 isn't shown on the screen).



Yes, it seems if I attached quad to the root node first and then q1, then it renders like I think it should; however, I think part of the reason one has a scene graph is that the programmer shouldn't have to worry about the order in which nodes are added to the scene.  Or maybe Java3D was just good like that.



Anyways, is there a way to get jME to order the scene properly or do I have to manually do this?



Thanks



    protected void initGame(){
        scene = new Node("Scene graph node");
        scene.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
    
        Quad q1 = new Quad("q1",5f,5f);
        q1.setDefaultColor(ColorRGBA.red);
        q1.setModelBound(new BoundingBox());
        q1.updateModelBound();
        Node q1Node = new Node("q1Node");
        q1Node.setLocalTranslation(new Vector3f(0,5,-5f));
        q1Node.attachChild(q1);
        scene.attachChild(q1Node);


        // build background
        Quad quad = new Quad("background",40f,40f);
        quad.setDefaultColor(ColorRGBA.blue);
        quad.setModelBound(new BoundingBox());
        quad.updateModelBound();
        Node quadNode = new Node("quadNode");
        quadNode.setLocalTranslation(new Vector3f(0,0,-25f));
        quadNode.attachChild(quad);
        scene.attachChild(quadNode);
      
        //update the scene graph for rendering
        scene.updateGeometricState(0.0f, true);
        scene.updateRenderState();
    }

Opaque objects are drawn front to back (based on camera location) on purpose.  This allows cards to quickly toss out pixels rather than do a lot of overdraw.

Is q1 and the quad transparent? Java3d would automaticly render the transparent objects last. In JME I think you have to mark all the transparent objects as transparent with setRenderQueueMode(Renderer.QUEUE_TRANSPARENT).

Ok,  So if does front to back, then why is quad drawing over q1?  I assume if u do front to back, then you would only render what can be seen underneath whats in front of the current object being drawn.  But here, it looks like it doesn't care whats in front and just draws over it.



Nope, nothing should be transparent btw.



I've attached the full source below



import com.jme.app.*;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.*;
import com.jme.input.action.*;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.shape.*;
import com.jme.scene.state.*;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jme.renderer.*;

public class Lesson2 extends BaseGame {

    protected Timer timer;
    //Our camera object for viewing the scene
    private Camera cam;
    //the root node of the scene graph
    private Node scene;
    //display attributes for the window. We will keep these values
    //to allow the user to change them
    private int width, height, depth, freq;
    private boolean fullscreen;
    private ThirdPersonHandler thirdPersonHandler;


    protected void update(float interpolation) {
      //update the time to get the framerate
       timer.update();
       interpolation = timer.getTimePerFrame();
       thirdPersonHandler.update(interpolation);

       //if escape was pressed, we exit
       if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit")) {
          finished = true;
       }
    }

    protected void render(float interpolation) {
        //Clear the screen
        display.getRenderer().clearBuffers();
        display.getRenderer().draw(scene);
    }

    protected void initSystem() {
        //store the properties information
        int width = 640;
        int height = 480;
        int depth = 24;
        int freq = 50;
        boolean fullscreen =false;

        try {
            display = DisplaySystem.getDisplaySystem();
            display.createWindow(width, height, depth, freq, fullscreen);

            cam = display.getRenderer().createCamera(width, height);
        } catch (JmeException e) {
            e.printStackTrace();
            System.exit(1);
        }

        //set the background to black
        display.getRenderer().setBackgroundColor(ColorRGBA.black);

        //initialize the camera
        cam.setFrustumPerspective(45.0f, (float)width / (float)height, 1, 1000);
        Vector3f loc = new Vector3f(0.0f, 0.0f, 50.0f);
        Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);
        Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
        Vector3f dir = new Vector3f(0.0f, 0f, -1.0f);
        // Move our camera to a correct place and orientation.
        cam.setFrame(loc, left, up, dir);
        /** Signal that we've changed our camera's location/frustum. */
        cam.update();

        /** Get a high resolution timer for FPS updates. */
        timer = Timer.getTimer();

        display.getRenderer().setCamera(cam);

        KeyBindingManager.getKeyBindingManager().set("exit",KeyInput.KEY_ESCAPE);
    }

    protected void initGame() {
        scene = new Node("Scene graph node");
        scene.setRenderQueueMode(Renderer.QUEUE_OPAQUE);

       //Create our Sphere
       Arrow arrow = new Arrow("Arrow", 5, 1);
       arrow.setModelBound(new BoundingBox());
       arrow.updateModelBound();

        Node arrowNode = new Node("arrowNode");
        arrowNode.setLocalTranslation(new Vector3f(0,0,0));
        arrowNode.attachChild(arrow);

        // create a third person handler
        thirdPersonHandler = new ThirdPersonHandler(arrowNode,cam);

        InputAction leftAction = new LeftAction();
        KeyBindingManager keyboard = KeyBindingManager.getKeyBindingManager();
        keyboard.set("leftAction",KeyInput.KEY_LEFT);
        thirdPersonHandler.addAction(leftAction,"leftAction",false);

        scene.attachChild(arrowNode);

        Quad q1 = new Quad("q1",5f,5f);
        q1.setDefaultColor(ColorRGBA.red);
        q1.setModelBound(new BoundingBox());
        q1.updateModelBound();
        Node q1Node = new Node("q1Node");
        q1Node.setLocalTranslation(new Vector3f(0,5,-5f));
        q1Node.attachChild(q1);
        scene.attachChild(q1Node);


        // buidl background
        Quad quad = new Quad("background",40f,40f);
        quad.setDefaultColor(ColorRGBA.blue);
        quad.setModelBound(new BoundingBox());
        quad.updateModelBound();
        Node quadNode = new Node("quadNode");
        quadNode.setLocalTranslation(new Vector3f(0,0,-25f));
        quadNode.attachChild(quad);
        scene.attachChild(quadNode);

        //update the scene graph for rendering
        scene.updateGeometricState(0.0f, true);
        scene.updateRenderState();
    }

    protected void reinit() {
      display.recreateWindow(width, height, depth, freq, fullscreen);
    }

    protected void cleanup() {
    }

    public class LeftAction extends InputAction{
        public void performAction(InputActionEvent evt){
            System.out.println("Left button action performed");
            thirdPersonHandler.setTurnSpeed(0.1f);
            thirdPersonHandler.setDoGradualRotation(true);
        }
    }

    public static void main(String[] args) {
       Lesson2 app = new Lesson2();
       app.start();
    }
}

You have no ZBufferState, so no depth information is available for OpenGL to use to throw out pixels.

Ah, so you have to attached the ZBufferState to the root node … so what are the uses for ZBufferState? 



Again, I'm new to jME … Java3D didn't have this concept (that I'm aware of).  I have been going through the tutorials and the user docs but it seems a bit challenging pulling out the right information for setting things up especially since the tutorials set things up differently.



Thanks for helping.

Java3d probably sets its defaults differently.



The ZBufferState controls whether or not your geometry is written into the depth buffer and how it should test the depthbuffer to determine whether it should render each texel.