Panda Bullet

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 libpandabullet.so statically, or link dynamically and distribute them alongside libpandabullet.so.

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:
http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=6107

For those who can’t compile themselves, here is an updated binary:
http://enn0x.p3dp.com/libpandabullet-r10.zip

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:
http://enn0x.p3dp.com/libpandabullet-r11.zip

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:
http://enn0x.p3dp.com/libpandabullet-r12.zip

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,
~powerpup118

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 direct.actor.Actor 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)


    base.cam.setPos(0, -20, 4)
    base.cam.lookAt(0, 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)


    render.clearLight()
    render.setLight(alightNP)
    render.setLight(dlightNP)


    # 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
    self.setup()


  # _____HANDLER_____


  def doExit(self):
    self.cleanup()
    sys.exit(1)


  def doReset(self):
    self.cleanup()
    self.setup()


  def toggleWireframe(self):
    base.toggleWireframe()


  def toggleTexture(self):
    base.toggleTexture()


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


  def doScreenshot(self):
    base.screenshot('Bullet')

  def doJump(self):
    self.player.setMaxJumpHeight(5.0)
    self.player.setJumpSpeed(8.0)
    self.player.doJump()


  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.setAngularVelocity(omega)
    self.player.setLinearVelocity(speed, True)


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


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


    return task.cont


  def cleanup(self):
    self.mgr = None
    self.worldNP.removeNode()


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


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


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


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


	np = self.worldNP.attachNewNode(BulletRigidBodyNode('Box'))
	np.node().setMass(1.0)
	np.node().attachShape(shape)
	np.setPos(0, 0, 4)
	np.setCollideMask(BitMask32.allOn())


	self.mgr.attachRigidBody(np.node())


	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.node().attachShape(shape)
	np.setPos(0, 0, 0)
	np.setCollideMask(BitMask32.allOn())
	self.mgr.attachRigidBody(np.node())
	#- 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.node().attachShape(shape)
	np.setPos(0, 0, -1)
	np.setCollideMask(BitMask32.allOn())
	self.mgr.attachRigidBody(np.node())
	#- 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)
	np.setH(0)
	np.setCollideMask(BitMask32.allOn()


	self.mgr.attachCharacter(np.node())


	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.reparentTo(np)
	self.playerNP.setScale(0.3048) # 1ft = 0.3048m
	self.playerNP.setH(180)
	self.playerNP.setPos(0, 0, -1)


b = World()
run()

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.

~powerpup118

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

Right, but I’m using a patched version of Bullet which solves this bug.
See the above post for details:
[url]Panda Bullet - #49 by enn0x]

What causes the crash here is some weirdness in BulletDebugNode, in particular the colors for lines. I will investigate the weekend.

Turning off the debug renderer should work as a temporary workaround.

I think I fixed the problem:
http://enn0x.p3dp.com/libpandabullet-r13.zip

Hey enn0x, it works great!

Your patch fixed it and the code works good now, many thanks.
~powerpup118

Hey enn0x, back again - I know what you’re thinking, “When will he leave? >.>” nah just kidding though if you want me to just shush and let you work let me know :wink:

(Does the BulletHeightFieldShape (or it’s node) provide a way to display a visual texture? otherwise I assume that I must build my visual heightmap using panda’s heightfield generator found here, in which case)

When matching a bullet heightfield with a panda visual heightfield, several inconvenient things happen (which I think might be easy-ish to include)

you have to turn the visual map using setH(90) because I guess panda or bullet disagree with the starting rotation or something
after that, the bullet map starts in the center point of the image (image width / 2 image height / 2, basically), the panda visual heightmap starts… in some corner, so you have to set it’s X and Y to offset half the image (which is weird), I wonder if either we could offset the bullet heightfield to match the panda3d one, OR add a way for a texture to be set on the bullet heightfield

these are just idea’s and I’m only hoping to give good feedback, what you’ve done so far is brilliant and I really want to see it go further :wink:
So it’s totally up to you if you think this is important or non important or anything
~powerpup118