Panda Bullet

Hey guys, just passing by I noticed that you finally shot down the ‘debug geometry no-show’ bug.

Just implemented the fix in c++, it now works like a charm!

Cheers
Jean-Claude

Well it cost me one whole day of testing and now im stucked with an access voilation :confused:

EDIT:
Solved the seg vault. BulletTriangleMeshShape does not like empty BulletTriangleMesh at all and findAllMatches directly on a GeomNode results in 0 found so nothing was added to the mesh :wink:.

How should the debug view of a convex hull look like? Because the Convex Hull of the ralph model looks a bit like a cap for his head and not like a hull of the full mesh.
And is it possible that BulletTriangleMeshShape ignores scaling?

EDIT2:

t4 = time.clock()
            counter = 0
            self.world.doPhysics(0.1)
            t5 = time.clock()
            for ghost in self.world.getGhosts():
                #print ghost,
                for res in ghost.getOverlappingNodes(): 
                    counter += 1
            t6 = time.clock()

Results are around
t5-t4: 0.0100 t6-t5: 0.0100
So it looks like the doPhysics is performing the same operation. Is there no way to get the “results” of doPhysics collision detection? Maybe saving it into the world as “last_do_physics_found_collisions”?

Good. I will soon add a guard which warns you if you attempt to use an empty mesh.

Have a look at the sample 02_Shapes.py.

It should work, either using setLocalScale on the shape, or setScale on the BulletbodyNode.
However, like with position it is currently not possible to set the scale on the parent node.

You can’t derive that two code blocks do the same operation just because it takes the same time to execute them.

There is. Bullet stores all information gathered during broadphase and narrow phase collision detection in so-called persistent manifolds. If I remember right I posted this already a day or two ago:

    self.world.doPhysics(dt)
    pairs = [(mf.getNode0().getName(),
              mf.getNode1().getName())
      for mf in self.world.getManifolds() if mf.getNumManifoldPoints() > 0]
    print pairs

Consult the API documentation to see what data you can pull from the manifolds (contact points etc.)

Yeah you are right. You posted this solution just some time ago and i will consider it for tests now.

To the scale problem: codepad.org/iALG3NQZ <- the scale is set before the ghost is created
codepad.org/d5ZgPaR5 <- even as TransformState the Scale seems to be ignored
codepad.org/iI51oF3x <- test with minimal update task and both shapes (Hull and Trianglemesh). Both seems to be unaffected by the scaling and ralphs hull looks strange, does not it?

I just had a look at the first sample, and thing got obvious already. So you load a NodePath from an egg file. You are aware that this NodePath can have children, for sure. Actually it is a small subgraph

ModelRoot ralph.egg T:(pos 0 100 0 scale 0.5)
  Character Ralph
    GeomNode  (2 geoms: S:(ColorAttrib TextureAttrib))

Setting scale and transform on the ModelRoot node does not modify (rescale etc.) the vertices within the two Geoms. It just affect the way how they are rendered.

Now you use the Geoms for creating a TriangleMesh. This is fine, and what I see running your script does not look unexpected. It is just difficult to see the ralph mesh because of the long normals which Bullet debug renderer draws. But inside I can see the well-know ralph model. Try zooming a bit closer. The normals are yellow, the mesh itself white.

You can see the mesh better if you scale it, like this

...
        self.ghost = self.node.attachNewNode(ghost)
        self.ghost.setScale(5.0)

In order to scale a Geom you could use geom.transformVertices(mat4).

Oh, one thing. This loop is dangerous

        geomNodeCollection = self.node.findAllMatches('**/+GeomNode') 
        for nodePath in geomNodeCollection: 
            geomNode = nodePath.node() 
            for i in range(geomNode.getNumGeoms()): 
                geom = geomNode.getGeom(i) 
                mesh.addGeom(geom)

If the GeomNodes found have transforms on them (relative to self.node!) then you will get a weired looking result, because the transforms are lost. You have to find the transforms, transform the Geom vertices using this transform, and then add the Geom to the BulletTriangleMesh.

Hmm i got the loop from post panda3d.org/forums/viewtopic … 4384#74384 . Thanks for this advice. Anyway even if the vertices itself are unaffected the “visible” result is affected by the scale and for what reason should the “collision”-shape be unaffected by the scale? For which situation is this really sensible to only affect the visible but not the logicalshape?

P.S: I never questioned that the trimesh shape is not shown correctly. The “convexhullshape” just seems not very proper.

The reason why the BulletTriangleMesh is not affected by the node’s scale is that the same Mesh could be used in many shapes and bodies. The same is true for Geoms. So it’s a matter of resource economy.

If you use setScale on the NodePath or the related BulletBodyNode then the transform_changed hook will be called, and the scale will be applied as a so-called (Bullet term) “local scale” of the Bullet shape. Not chnaging the BulletTriangleMesh, just the shape.

The only problem is if you set a scale on the parent or grandparent etc of the BulletBodyNode. So far the Panda3D Bullet module won’t detect this. The same problem as with setPos called on the parent node. I am currently searching for ways to also support this.

By the way: Bullet and PhysX have transform states which don’t know about scale or shear. So the easy answer would be to say “this is not supported by the underlying physics engines.”. However, Bullet support this “local scale”, and I try my best to connect the Panda3D node scale with this property.

Shear is not supported in any way, neither by Bullet or PhysX.

Excuse my French. Of course I meant shapes not the geom itself then I asked for the reason why the scale is not taken into account.

Well the position is correctly taken into account as one could see in these samples but the scale is not set at all as far as I could tell. If the position would not be applied correctly the shape would not show directly above the ralph. But whatever scale is set nothing changes at all. Even in the last example were the reparentTo(parent) thing is called frequently no effect on the scale appears.

Out of curiosity, do you plan integrating btBulletWorldImporter?
It’s used to load binary bullet files which describe setups.

More on that here: bulletphysics.org/mediawiki-1.5. … ialization .

Using this we could use Blender to create compound shapes and do other useful things.

The serialisation/loader for .bullet binary file format has been included in a very early stage of the project. It has been removed due to user requests, because some of the classes are not part of the “core” Bullet library (they are “extras”), not part of the API documentation, and for most Linux distributions not included in their binary packages.

To bring it back it problematic, since now Bullet rigid bodies etc. are integrated with Panda3D in the form of classes derived from PandaNode. This mean that loading only the information from .bullet files is not enough to create instances e.g. BulletRigidBodyNode. On the other hand we sooner or later have to add serialisation of e.g. BulletRigidBodyNode as BAM.

We have to think very, very careful abou this first. without thinking about this some more I would say that

  • we will habe BAM serialisation (not compatible with Blender)
  • .bullet won’t be supported
  • we might be able to export from Blender using the EGG format.

What about having collada support?
From what i see, its kind of goal to make egg deprecated (over long period of time), and use collada as main format.

COLLADA is an option. But…
1.) Let’s wait until the COLLADA support for the rendering part is finished and stable, and then see how it can be extended.
2.) COLLADA is, even the most current versions, not able to store some of the advanced features provided by Bullet or PhysX (e.i. Soft Body, Character Controller, Vehicle, …)

Then there is another problem when loading physics objects from a file. PandaBullet (and PandaOde, PandaPhysX) are Add-On modules. Panda can be built without these modules. I think it is not wise to make the Panda3D core dependend from any of these Add-On modules.

And what should the model loader do if he finds a “rigid body” object in the COLLADA file? Create Panda3D-internal physics objects, create ODE object, or Bullet objects?

Again, this is something where we still have to think about carefully, and where we have to discuss. So ideas or viewpoints are welcome.

I’ve been giving this some thought, too. I definitely think that having support for COLLADA Physics is a good idea. We could have a config variable indicating whether to read the physics objects as Panda3D solids or as Bullet solids.

With your permission of course, I think it would be best if instead of making the COLLADA loader depend on Bullet, do it the other way around; make the Bullet module provide the necessary code for the COLLADA integration (I’d help with that, when the time comes).

Does anyone know if the current Blender collada exporter supports physics objects, or at least collision solids?

Thanks for your thoughts, guys.

Another short question:
The difference between a dynamic rigid body and a static one are determined by either setting a mass or not, right?
In that case, how do you define a kinematic body?

Do you have a collada exporter for blender 2.5x?
Mind pointing me to the source? I couldn’t find any.

There is also none on the official extensions list: wiki.blender.org/index.php/Exten … Py/Scripts

There’s a collada exporter that comes default. From a fresh install, I’ve been able to just go Export>Collada and then run dae2egg against it and load models into Panda.

I’ll preface that with saying that I haven’t tried anything complicated yet, so I don’t know the status of things like animation, normal maps, and other texture effects, but it appears to work fine for static models.

If you set a mass > 0 then the body is dynamic, and if you set mass = 0 then it will be static. Another way is to use node.setStatic(True), no matter what the mass is.

You can use node.setKinematic(True) to create a kinematic body, and node.isStatic() and node.isKinematic() to find out of a body is static or kinematic.

Currently I was abled to get collision detection at least in some way with the following “parameterset”:
-BulletGhostNode + BulletConvexHullShape
-update method

obj.ghost.reparentTo(obj.ghost.getParent())
obj.ghost.setScale(obj.ghost.getParent().getScale(render))

-collision check as ennox suggested

But following problems occured for which I did not found a working workaround yet:
-the rotation of the bullet shapes/ghost seems to be not correct. Can be easily doublechecked by rotating a ghost parented to render with a hpr of (0,0,90).
-if I replace BulletConvexHullShape by BulletTriangleMeshShape the collisions are not detected correctly.
[/code]

Doublechecked and seems to be corrent. Please try to setup a sample and explain what is not as expected.

Same as above.