Issue with small near-plane values in 1.7.1 and 1.7.2

I encountered a problem when I upgraded from Panda 1.7.0 to 1.7.2 (and confirmed the problem exists in 1.7.1 as well), related to near clipping plane values below 0.00299, set with ShowBase’s camLens.setNear(). When I create a scene with some objects, translate ShowBase’s “camera” node backwards in the scene to view the objects, then rotate ShowBase’s “render” node using render.setH(), the objects in the scene individually disappear from view for certain rotation angles. Inserting nodes in between render and camera and rotating them does not help either, however inserting nodes between render and the objects and rotating those does correct the problem. The problem only occurs when setNear() sets the near clipping plane nearer than 0.00299. Here is some example code to demonstrate the issue, again it only occurs on Panda 1.7.1 and 1.7.2. To show/correct the issue, switch the flag “showFlicker” to True or False, to rotate the scene use the ‘R’ and ‘T’ keys. By pressing ‘R’ repeatedly you will notice that for some rotations, only 1 of the 2 boxes disappears, sometimes both disappear, and sometimes both are visible:

from direct.showbase.ShowBase import ShowBase

class RotateTest(ShowBase):
    """
    Demonstrates flickering weirdness in 1.7.1 and 1.7.2, due to small
    values of self.camLens.setNear().  To show the flickering effect,
    set showFlicker to True in self.adjustCamera(), or False to
    turn the flickering off
    """

    def __init__(self):
        ShowBase.__init__(self)

        # Adjust camera
        self.adjustCamera()

        # Create a box to view
        self.createBoxes()

        # Set keys to rotate self.render by +/- 1 degree
        self.accept("r", self.rotate, [-1.0])         
        self.accept("t", self.rotate, [1.0])

    def adjustCamera(self):
        self.disableMouse()

        ###
        # The following setNear() line is the source of the flickering
        # under rotations of self.render, set showFlicker to True
        # to show the flicker vs no-flicker
        showFlicker = True
        if showFlicker:
            self.camLens.setNear(0.00298)
        else:
            self.camLens.setNear(0.00299)        
        ###

        self.camera.setPos((0., -6., 1.))

    def createBoxes(self):
        box0 = self.loader.loadModel("box")
        box1 = self.loader.loadModel("box")
        box1.setPos(0, 0.2, 1.0)
        box0.reparentTo(self.render)
        box1.reparentTo(self.render)        

    def rotate(self, ang):
        H = self.render.getH()
        self.render.setH(H + ang)

    
app = RotateTest()
app.run()

My goal is to rotate a node that lies between render and camera, so I’ve worked around the issue by just using a larger setNear() value – but I wanted to make you aware of this behavior. Thanks.

This is an issue with floating-point precision. If the ratio between the near plane and the far plane values exceed the limits of a single-precision floating-point number, you will get culling errors like this.

To solve it, either increase the near plane, or decrease the far plane.

Another, more advanced, workaround is to adjust the config variable:

lens-far-limit 0.0000001

The value shown is the default value as of 1.7.1. Prior to that, it was hardcoded at the larger value 0.00001, and couldn’t be changed, which is why your code appeared to work in 1.7.0.

The lens-far-limit is the reciprocal of the largest possible far value that should be considered for culling purposes. If lens-far-limit is larger (as it was in 1.7.0), you have fewer artifacts from having a very small near plane, but more artifacts from having a very large far plane. If lens-far-limit is smaller (as it is in 1.7.1 and above), it’s the other way around.

David

Thanks!