Bullet Debug Renderer

In the previous “hello world” sample we have been introduced to a few Bullet physics objects, for example the rigid body (BulletRigidBodyNode) or box and plane collision shapes (BulletPlaneShape, BulletBoxShape).

These objects are part of the Panda3D scene graph. But they are not visible. In order to be able to actually see a rigid body we had to reparent a visible geometry below the rigid body node. This is fine, since we (1) can control the way an object looks like, by choosing whatever visible geometry we want, and (2) we can create invisible objects too, by not reparenting any geometry below a rigid body.

But when developing a game it sometimes would be handy to actually see where the physical objects are. This is what the BulletDebugNode is for. It’s not meant for users playing the game, but as an aid in finding problems while developing the game.

The debug node is pretty easy to use. We just need to create such a node, place it in the scene graph, and tell the Bullet world that we have such a node. From now on Bullet will create a “debug” visualisation of the world’s content within the debug node, whenever doPhysics() is called. The following code snippet shows how to do this:

from panda3d.bullet import BulletDebugNode

debugNode = BulletDebugNode('Debug')
debugNode.showWireframe(True)
debugNode.showConstraints(True)
debugNode.showBoundingBoxes(False)
debugNode.showNormals(False)
debugNP = render.attachNewNode(debugNode)
debugNP.show()

world = BulletWorld()
world.setGravity(Vec3(0, 0, -9.81))
world.setDebugNode(debugNP.node())

We can control the amount of information rendered using the following methods:

showWireframe()

Displays collision shapes in wireframe mode.

showConstraints()

Display limits defined for constraints, e.g. a pivot axis or maximum amplitude.

showBoundingBoxes()

Displays axis aligned bounding boxes for objects.

showNormals()

Displays normal vectors for triangle mesh and heightfield faces.

There is one thing to pay attention to: By default the BulletDebugNode is hidden right after creation. If we want to see the debug visualisation from the first frame on we have to unhide it, using show().

Since debug rendering is not very fast we can turn debug rendering on and off, without having to remove the debug node from the scene graph. Turning debug rendering on and of is simply done by hiding or showing the debug node. The following code shows how to toggle debug node visibility on and off, using the F1 key:

from direct.showbase.DirectObject import DirectObject

o = DirectObject()
o.accept('f1', toggleDebug)

def toggleDebug():
    if debugNP.isHidden():
        debugNP.show()
    else:
        debugNP.hide()