Panda Bullet


I’d like to try this out and possibly help with development… I’d much rather be using Bullet than PhysX for my projects, especially since they’ve started integrating OpenCL hardware acceleration support.

I’ve downloaded and tried building it; the .pyd included doesn’t work on Linux apparently:

$ ppython 
DirectStart: Starting the game.
Known pipe types:
(all display modules loaded.)
Traceback (most recent call last):
  File "", line 22, in <module>
    from libpandabullet import BulletWorld
ImportError: No module named libpandabullet

$ file libp ppython 
DirectStart: Starting the game.
Known pipe types:
(all display modules loaded.)
Traceback (most recent call last):
  File "", line 22, in <module>
    from libpandabullet import BulletWorld
ImportError: No module named libpandabullet
libpandabullet.pyd: PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit

So, I tried installing the latest Bullet from SVN (r2243) and building libpandabullet, and the first time running scons seemed to indicate that it was also rather Windows-specific:

$ scons
scons: Reading SConscript files ...
  File "/home/whitelynx/devel/libpandabullet-r9/SConstruct", line 13:
    SConscript([ 'SConscript.%s' % PLATFORM, ])
  File "/usr/lib/python2.7/site-packages/SCons/Script/", line 614:
    return method(*args, **kw)
  File "/usr/lib/python2.7/site-packages/SCons/Script/", line 551:
    return _SConscript(self.fs, *files, **subst_kw)
  File "/usr/lib/python2.7/site-packages/SCons/Script/", line 260:
    exec _file_ in call_stack[-1].globals
  File "/home/whitelynx/devel/libpandabullet-r9/SConscript.VC9", line 4:
    PANDADIR  = os.environ['PROGRAMFILES'] + '/Panda3D-1.7.1'
  File "/usr/lib/python2.7/", line 23:
    raise KeyError(key)

I checked out the SConstruct file, and noticed the PLATFORM line, which seemed to indicate that setting it to ‘Linux’ was valid, but that doesn’t seem to work either:

$ scons
scons: Reading SConscript files ...

scons: warning: Ignoring missing SConscript 'SConscript.Linux'
File "/home/whitelynx/devel/libpandabullet-r9/SConstruct", line 13, in <module>

scons: *** Import of non-existent variable ''env''
File "/home/whitelynx/devel/libpandabullet-r9/SConstruct", line 14, in <module>

Is there currently a way to build this on Linux, or should I hack together a method for doing this? I’m not very familiar with scons aside from reading several articles about it, but I’m very fluent in both Python and waf. (which I prefer over scons from a purely feature-oriented and performance-oriented point of view… we use waf for all of our C/C+±based projects)

If it’d be desirable, I’d also love to write a waf build system for this… but it’s up to you if you’d want that.


The .pyd is a Windows 32bit DLL. It’s not usable on Linux. So far I provide - together with the source code - only Windows binaries.
Also the build script is Windows-only so far. There is a main script (SConstruc) which is platform-independent, and which loads a platform-dependent file for setting up the environment (e. g. SConscript.VC9). All you would have to do is add a script for your platform, and make sure it gets imported by the main script.

I didn’t try to compile on Linux so far. Might be there have to be some smaller changes to the code, but nothing serious.

Once the module is added to the P3D source code it will be compiled for all platforms automatically, so currently I don’t attempt to provide build scripts for Linux, Mac, etc.

I have no problem if you want to provide build script for waf. I haven’t used waf so far, and I’m not fixed on SCons. You will have to spend some time on the interrogate & interrogate_module calls, but I can provide help here.


Ok, I started trying to write a SConscript.Linux file for this, and it mostly seems to be working, but it’s trying to include a file that doesn’t get installed by Bullet:

$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o built/bullet_composite.os -c -fPIC -DFORCE_INLINING -DBUILDING_PANDABULLET -DHAVE_PYTHON -Ibuilt -Isource -I/usr/include/python2.7 -I/home/whitelynx/packages/panda3d-cvs/src/panda3d/built/include -I/usr/include/bullet/bullet source/bullet_composite.cxx
In file included from source/config_bullet.h:26:0,
                 from source/config_bullet.cxx:15,
                 from source/bullet_composite.cxx:1:
source/bullet_includes.h:36:72: fatal error: Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.h: No such file or directory
compilation terminated.
scons: *** [built/bullet_composite.os] Error 1
scons: building terminated because of errors.

I’m assuming this file is in the Bullet source… is this actually needed? Shouldn’t we be sticking to things that Bullet provides in the install?


Hmmm… I checked out r2243 this weekend, and I still can see this file. Directory trees checked out from SVN should be the same both on Windows and Linux.


Ok, I think I found the issue… apparently the AUR package for Bullet has BUILD_EXTRAS turned off for some odd reason. I’m working on that package to try and get those files installed; I’ll let you know how it goes.


Even manually building Bullet, it never installs that file, which leads me to believe it should be an internal-only file, and should not be used by external projects. The btBulletWorldImporter.h file and btBulletWorldImporter class don’t even show up in the Bullet API docs. If it should be externally accessible, we’ll need to talk to the Bullet team and get it changed upstream; otherwise, we really should be sticking to what’s available in their public API, or this won’t work at all on Linux systems without getting the source.


Ah, glad that nobody will ever again ask me when hardware acceleration will be enabled, e. g. OpenCL. It’s not part of the “public” API, so we don’t need to care about it. Sorry for the sarcasm.

Seriously, I don’t believe your problems with compiling Bullet including the extra libs will be a real issue. You can either compile the extra libs and link statically, or link dynamically and distribute them alongside

For now, if you really want to explore, you can simply remove the includes and all methods dealing with serialisation/deserialisation from the source code. Don’t be afraid to mess around with code. The next release will be a full rewrite anyway.


Sorry, I thought I had sent this like a week ago…

Ok, didn’t realize Bullet was that far behind on making sure their public code was actually accessible. (and sorry if I’m coming across as antagonistic… I tend to get a bit worked up when code isn’t written to be easily portable)

For now I’ll compile against the source dir. (this just won’t work on source distros like gentoo, because there the source directory is removed once the install is completed, and you can’t expect prebuilt binaries to work because everything’s built from source)

I’ve changed the SConscript.Linux file I’m writing to point to the Bullet source directory, and I’ve put together a small patch to fix some compilation errors under GCC. I’ll have to look at it again in a couple days when things calm down at work, but then I should be able to post it.


Well, Bullet is quite young, and far from stable. There are lots of “experimental” features.

About compiling: I didn’t include the Bullet source code directly, but have been running the MSVC projects which come with Bullet. The output has been (1) executables for the demos, and (2) static libraries for the major Bullet components. When building libpandabullet I include the Bullet headers, and then link the shared library against the static Bullet libs. Should be possible to reproduce on Linux too.

About build system: I am playing around a bit with waf currently. Not really my favorite, and I still have to find out how to run interrogate & interrogate_module, but waf supports Python 3 (unlike SCons), and I will be moving to Python 3 for most of my work soon.

There is still a lot o do at work before the end of the year, but in January/February I will have more spare time to spend on this project.


I think I found another glitch. I just started working on terrains, and I was trying to sync Panda’s terrain with Bullets. When just using a block as a character it works fine, but when ever a Bullet Character collides with the terrain the window freezes up and stops working.

Any ideas?


I have been able to reproduce this problem. It’s the same as with plane shapes. No problem with my wrappers, but with the Bullet library itself.


Oh, thats a pain. I am now using a sphere, and setting the cameras position to that of the sphere. It actually works quite well, as long as you set the damping to a high level.


I patched Bullet r2250 as suggested in the following post, and it seems to fix the problem:

For those who can’t compile themselves, here is an updated binary:

Besides this I would suggest using either capsules or sphere for character controllers. Boxes tend to get stuck rather easy.


Here is a new version - it’s experimental and a complete rewrite with lots of API changes:

Summary of changes:

  • All physics objects are derived from PandaNode now (this is rigid body, soft body, ghost, character and vehicle).
  • Collision filtering is based on Panda3D’s CollideMask. Only the “from” collide mask is used.
  • Compound shapes are no longer required for bodies with several shapes. The btCompoundShape is created internally (I still have to optimize this, since currently a btCompoundShape is always internally created, no matter how many shapes are added to a rigid body).
  • Many objects and methods have been renamed, in order to fit better with Panda3D’s naming pattern.
  • Build system is now ‘waf’. Still Windows-only. Currently I am not using anything from Bullet’s “extra” directories.

I still have problems with synchronization of soft body transforms, so please don’t use soft bodies yet.

All the changes have been done in order to find a tighter integration with Panda3D. I’m not 100 percent convinced that this is the right way of providing Bullet physics in Panda3D, so please feel free to comment on the new version or - even bettere - suggest other ways.


And yet another version:

What’s new:

  • Built using Panda3D-2010.12.28-82 and Bullet r2260
  • Debug renderer: sphere shapes are now rendered as spheres, and not as diamonds like before.
  • Prevent nodes from getting flattened out.
  • BulletDebugNode: it’s no longer necessary to call hide/show after calling setVerbose.
  • Mass properties will be updated automatically after shapes are added/removed from a rigid body.
  • Classes derived from PandaNode have been renamed to reflect the inheritance, e. g. BulletGhost --> BulletGhostNode.
  • Optimized adding/removing of shape. No implicit btCompoundShape will be created if only one shape is added.
  • “Explosions” caused by “setPos” etc. being not applied right after creation of an object should no longer appear.


Id like to see your results, but i cant compile your project with waf

on win7 64bit


The important part of the console output, which gives information about what is going wrong, is ABOVE what you posted as screenshot. I guess you will see something like this:

Waf: Entering directory `C:\Development\BulletMk4\built'
[1/6] libbullet_igate.cxx:  -> built\libbullet_igate.cxx
    *** Error in bullet_utils.h near line 31, column 73:
    parse error
Error parsing file: 'bulletAllHitsRayResult.h'
Waf: Leaving directory `C:\Development\BulletMk4\built'
Build failed

The problem is that you probably didn’t set the path to Panda3D (current snapshot builds, 1.7.0 is not enough!). Check if those paths you see on your screenshot are right:

-S"C:\\Program Files/Panda3D-1.7.1/include" 
-S"C:\\Program Files/Panda3D-1.7.1/include/parser-inc"

Finally, if you have adjusted all paths, including the path to the compiled Bullet library, you should adjust the compiler flags and defines for 64bit Windows. I see in your screenshot that you are using 32bit defines.

I’m sorry, but I don’t have a Windows7/64bit machine, so I can’t test anything for you. Maybe someone can send me a full build log of Panda3D on Windows7 (with --verbose of course). I could try to make a best guess then.


Hi, your work is AMAZING! I really really enjoy it! Everything works really well (I had lots of fun with the car demo :wink:)

Keep up the great work,


Hi, I was wondering, are Character Controller Nodes supported on heightfields?

I ask because I tried to place the character demo into the height field demo, with the code looking like:

import sys
import direct.directbase.DirectStart

from import Actor
from direct.showbase.DirectObject import DirectObject
from direct.showbase.InputStateGlobal import inputState

from panda3d.core import AmbientLight
from panda3d.core import DirectionalLight
from panda3d.core import Vec3
from panda3d.core import Vec4
from panda3d.core import Point3
from panda3d.core import TransformState
from panda3d.core import BitMask32
from panda3d.core import Filename
from panda3d.core import PNMImage

from libpandabullet import BulletManager
from libpandabullet import BulletPlaneShape
from libpandabullet import BulletBoxShape
from libpandabullet import BulletRigidBodyNode
from libpandabullet import BulletDebugNode
from libpandabullet import BulletCapsuleShape
from libpandabullet import BulletCharacterControllerNode
from libpandabullet import BulletTriangleMesh
from libpandabullet import BulletTriangleMeshShape
from libpandabullet import BulletHeightfieldShape
from libpandabullet import ZUp

class World(DirectObject):
  def __init__(self):
    base.setBackgroundColor(0.0, 0.0, 0.6, 1)
    base.setFrameRateMeter(True), -20, 4), 0, 0)

    # Light
    alight = AmbientLight('ambientLight')
    alight.setColor(Vec4(0.5, 0.5, 0.5, 1))
    alightNP = render.attachNewNode(alight)

    dlight = DirectionalLight('directionalLight')
    dlight.setDirection(Vec3(1, 1, -1))
    dlight.setColor(Vec4(0.7, 0.7, 0.7, 1))

    dlightNP = render.attachNewNode(dlight)


    # Input
    self.accept('escape', self.doExit)
    self.accept('r', self.doReset)
    self.accept('f1', self.toggleWireframe)
    self.accept('f2', self.toggleTexture)
    self.accept('f3', self.toggleDebug)
    self.accept('f5', self.doScreenshot)

    self.accept('space', self.doJump)
    self.accept('c', self.doCrouch)

    inputState.watchWithModifiers('forward', 'w')
    inputState.watchWithModifiers('left', 'a')
    inputState.watchWithModifiers('reverse', 's')
    inputState.watchWithModifiers('right', 'd')
    inputState.watchWithModifiers('turnLeft', 'q')
    inputState.watchWithModifiers('turnRight', 'e')

    # Task
    taskMgr.add(self.update, 'updateWorld')

    # Physics

  # _____HANDLER_____

  def doExit(self):

  def doReset(self):

  def toggleWireframe(self):

  def toggleTexture(self):

  def toggleDebug(self):
    if self.debugNP.isHidden():

  def doScreenshot(self):

  def doJump(self):

  def doCrouch(self):
    self.crouching = not self.crouching
    sz = self.crouching and 0.6 or 1.0

    self.player.getShape().setLocalScale(Vec3(1, 1, sz))

    self.playerNP.setScale(Vec3(1, 1, sz) * 0.3048)
    self.playerNP.setPos(0, 0, -1 * sz)

  # ____TASK___

  def processInput(self, dt):
    speed = Vec3(0, 0, 0)
    omega = 0.0

    if inputState.isSet('forward'): speed.setY( 3.0)
    if inputState.isSet('reverse'): speed.setY(-3.0)
    if inputState.isSet('left'):    speed.setX(-3.0)
    if inputState.isSet('right'):   speed.setX( 3.0)
    if inputState.isSet('turnLeft'):  omega =  120.0
    if inputState.isSet('turnRight'): omega = -120.0

    self.player.setLinearVelocity(speed, True)

  def update(self, task):
    dt = globalClock.getDt()

    self.mgr.doPhysics(dt, 10, 0.008)

    return task.cont

  def cleanup(self):
    self.mgr = None

  def setup(self):
	self.worldNP = render.attachNewNode('World')

	# Manager
	self.debugNP = self.worldNP.attachNewNode(BulletDebugNode('Debug'))

	self.mgr = BulletManager()
	self.mgr.setGravity(Vec3(0, 0, -9.81))

	# Box (dynamic)
	shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5))

	np = self.worldNP.attachNewNode(BulletRigidBodyNode('Box'))
	np.setPos(0, 0, 4)


	self.boxNP = np # For applying force & torque
	#- This heightfield code with a character is broken.. why?
	img = PNMImage(Filename('models/elevation2.png'))
	shape = BulletHeightfieldShape(img, 3.0, ZUp)
	np = self.worldNP.attachNewNode(BulletRigidBodyNode('Heightfield'))
	np.setPos(0, 0, 0)
	#- Comment out the code below for static planes and enable this code to see what I mean
	''' Heightfield is broken with character?
	#- Using static planes works fine with the character
	shape = BulletPlaneShape(Vec3(0, 0, 1), 0)
	np = self.worldNP.attachNewNode(BulletRigidBodyNode('Ground'))
	np.setPos(0, 0, -1)
	#- Comment the static plane code out and uncomment the heightfield code
	#- It then crashes saying:
	#- Assertion failed: (_flags & F_lock_count) != 0 at line 68 of c:\buildslave\dev_sdk_win32\build\panda3d\built\include\mutexSimpleImpl.I
	# Character
	self.crouching = False

	h = 1.75
	w = 0.4
	shape = BulletCapsuleShape(w, h - 2 * w, ZUp)

	node = BulletCharacterControllerNode(shape, 0.4, 'Player')
	np = self.worldNP.attachNewNode(node)
	np.setPos(-2, 0, 4)


	self.player = node # For player control

	self.playerNP = Actor('models/ralph/ralph.egg', {
			              'run' : 'models/ralph/ralph-run.egg',
			              'walk' : 'models/ralph/ralph-walk.egg',
			              'jump' : 'models/ralph/ralph-jump.egg'})
	self.playerNP.setScale(0.3048) # 1ft = 0.3048m
	self.playerNP.setPos(0, 0, -1)

b = World()

that, and it error’s out (crashes python.exe)
here’s the only thing it prints to the terminal:

Assertion failed: (_flags & F_lock_count) != 0 at line 68 of c:\buildslave\dev_sdk_win32\build\panda3d\built\include\mutexSimpleImpl.I

was just curious if I had done something wrong or what, I know this is still uber beta, even if it is uber cool.



There is a bug in Bullet that does not allow the use of characters on height fields.