[solved] Node disappear in front of the camera

How can I debug culling issue ?

The symptom :

Some info :

  • reproductible for same camera position
  • nodes are present in the scenegraph under the same branch (no change)
  • I update the camera with the following code :
              CameraNode cam = rc.cam;
              Quaternion rot = pgex.cnv(cmd.getRotation(), cam.getLocalRotation());
              cam.setLocalRotation(rot.clone());
              cam.setLocalTranslation(pgex.cnv(cmd.getLocation(), cam.getLocalTranslation()));
              Camera cam0 = rc
                      .view
                      .getViewPort()
                      .getCamera();
              //System.out.printf("setEye camera %s for %s - %s / %s\n", cam0.hashCode(), remoteCtx.view, rc.view, rc.view.getViewPort());
              cam.setCamera(cam0);
              if (cmd.hasNear()) cam0.setFrustumNear(cmd.getNear());
              if (cmd.hasFar()) cam0.setFrustumFar(cmd.getFar());
              if (cmd.hasProjection()) cam0.setProjectionMatrix(pgex.cnv(cmd.getProjection(), new Matrix4f()));
              cam0.update();
              cam.setEnabled(true);
    

Thanks

I had this issue when i forgot to call updateWorldBounds when modifying vertex data manually

During the video, I only change the camera, no change on vertex.

I don’t find the updateWorldBounds method.

before Geometry.setMesh I call

        mesh.updateCounts();
        mesh.updateBound();

Yes, but the only thing that would cause what you are seeing is an improper model bounds on the Geometry. We don’t really have enough information to determine why it’s bad but 95% guaranteed that it’s the issue.

should be Geometry.updateworldbound after setting the mesh i think

it’s a protected method, and I doesn’t “extends” Geometry.

protected  void updateWorldBound()

Ups:

        Geometry.updateGeometricState();
        Geometry.updateModelBound();

I think the second did fix my issue.

But you can confirm it is a geometry culling problem if you set a very large bounding volume manually

If I doesn’t made error,in the display of bounds. it seems correct.

  • red line => world bounds
  • orange => model bounds (hidden by red line)

Imgur

the bounds display code :

I forgot to say that I update the camera (projection,…) at each frame (frame are generated on demand when camera moves)

Does the issue happen when using perspective camera instead of orthographic?

I"d got the issue in perspective camera, I didn’t use the ortho or perspective methode from jme, and directly set the projection (see top message).

I’d the issue all the day, but since I change the model, and reload the previous, I can’t reproduce it. Previously I restart the jme side, several times to add trace, visual info (ftustum, bounding box) but I keep blender as is, and was able to reproduce each time. I’ll try with an other model (I got the issue last WE).

@Momoko_Fan is the winner, I reproduce the bug only with orthographic projection matrix.

Any idea, how to fix it ?

Thanks.

If you know the camera is orthographic, call camera.setParallelProjection(true).
If that doesn’t work, I have no idea what the issue is …

It doesn’t work :frowning: . But it’s the right direction, it’s related to orthographic projection.

The updated code

            CameraNode cam = rc.cam;
            Quaternion rot = pgex.cnv(cmd.getRotation(), cam.getLocalRotation());
            cam.setLocalRotation(rot.clone());
            cam.setLocalTranslation(pgex.cnv(cmd.getLocation(), cam.getLocalTranslation()));
            Camera cam0 = rc
                    .view
                    .getViewPort()
                    .getCamera();
            //System.out.printf("setEye camera %s for %s - %s / %s\n", cam0.hashCode(), remoteCtx.view, rc.view, rc.view.getViewPort());
            cam.setCamera(cam0);
            if (cmd.hasNear()) cam0.setFrustumNear(cmd.getNear());
            if (cmd.hasFar()) cam0.setFrustumFar(cmd.getFar());
            if (cmd.hasProjection()) {
                Matrix4f proj = pgex.cnv(cmd.getProjection(), new Matrix4f());
                cam0.setParallelProjection(cmd.getProjMode() == ProjMode.orthographic);
                cam0.setProjectionMatrix(proj);
            }

            cam0.update();
            cam.setEnabled(true);

OK, I see a few weird things. First, never use Camera.setProjectionMatrix(), because it will not update the camera frustum planes. Second, never use Camera.setFrustumNear / setFrustumFar, you should be using either Camera.setFrustumPerpsective or Camera.setFrustum.

I didn’t use setFrustumPerspective(float fovY, float aspect, float near, float far) and setFrustum(float near, float far, float left, float right, float top, float bottom)

Because Blender (the data source) doesn’t provide fovY, aspect, left,… If I try to evaluate the value from available data (on blender side) and use them in jme, the final projection matrix is different, So displayed objects move/scale/… when I switch from jme POV to blender regulars view (solid,…).

Maybe the workaround will be on jme side (of the project) to do :

projection matrix → extract fovY,… → setFustrum

Here’s the projection matrix equation. You should be able to derive the four values from this … somehow.

it’s the projection matrix for perspective only, the easiest. I’ll search for the missing. With your help I found the cause, the hardest part. I’ll reverse how jme compute projection matrice to give it the expected value :wink:

Thanks.

I fixed the issue by reverse the expected data for orthographic view :

            if (cmd.hasNear()) cam0.setFrustumNear(cmd.getNear())
            if (cmd.hasFar()) cam0.setFrustumFar(cmd.getFar())
            if (cmd.hasProjection()) {
                val proj = xbuf.cnv(cmd.getProjection(), new Matrix4f());
                cam0.setParallelProjection(cmd.getProjMode() == ProjMode.orthographic)

                if (cmd.getProjMode() == ProjMode.orthographic) {
                    cam0.setProjectionMatrix(null)
                    val lr = pairOf(proj.m00, proj.m03)
                    val bt = pairOf(proj.m11, proj.m13)
                    val nf = pairOf(-proj.m22, proj.m23)
                    cam0.setFrustum(nf.key, nf.value, lr.key, lr.value, bt.value, bt.key)
                } else {
                    cam0.setProjectionMatrix(proj)
                }
            }
            cam0.update()
            cam.setEnabled(true)
        ]
    }

    def Pair<Float, Float> pairOf(float m0, float m3) {
        // m00 = 2.0f / (right - left);
        // m03 = -(right + left) / (right - left);
        // m11 = 2.0f / (top - bottom)
        // m13 = -(top + bottom) / (top - bottom);
        //m22 = -2.0f / (far - near)
        //m23 = -(far + near) / (far - near);
        val l = (-m3 - 1) / m0
        val r = (2f + (m0 * l)) / m0
        //System.out.printf("m0 %s - m0' %s = %s\n", m0, (2.0f / (r - l)), m0 - (2.0f / (r - l)))
        //System.out.printf("m3 %s - m3' %s = %s\n ", m3, (-1 * (r + l) / (r - l)), m3 - (-1 * (r + l) / (r - l)))
        new Pair(l,r)
    }


Thanks for your help

This would cause culling artifacts when the Blender camera FoV is greater than jME3’s. You cannot use setProjectionMatrix, no no no, cannot use it, no, its there, but its not for you, so don’t use it.
The equation I gave you describes exactly how to derive the values … You just need to solve for alpha. Here’s the solution:

EDIT: Here’s the equation in Java:

float fovY = 2f * FastMath.RAD_TO_DEG * FastMath.atan(1f / projMatrix.m11);