Panda Bullet

“Solution” that i use is creating a bullet “couple of cm” in front of model/collision body. When you create bullet, first move it forward on y, and then attach physics body.

Well thats the workaround im currently using. But i noticed that the turrets bound by a constraint seems to collide with the body as well which raises collisiontest amount dramatically without benefit. So a more sophisticated approach would save a lot performance in my case. I guess the most flexible approach would be the exposition of the collision callback but a C->Python call is very expensive. Maybe another 2d data storage than a matrix would be a solution.

First, you are right, the bitmasks are 32-bit. I have choosen 32 bit because this is the length used by Panda3D’s CollisionMasks, and because longer masks would mean less performance on 32-bit computers.

A Python callback is of course the most flexible method, but it is also the slowest (by far).

Now, since I know that one size never fits all I have made it possible to extend the collision filter callbacks. In you config settings you choose which collision filter algorithm you want. Currently we have two algorithms implemented. I can easily add another one (or two).

But YOU have to specify how this algorithm should work. I will read you proposal, and check if it is possible to implement and what the impact on the existing code is.

Im aware of two different approaches:

  1. replace the matrix/flag with a 2d list (list within a list). This is only senseful if the number of set flag is much lower than the possible “flags”.

  2. Add a “deny collision with” list to every body. But this implies some ugly object-object dependencies. But if Bullet uses IDs anyway one may use them to speficify the objects. But then one has to deal with the proper cleanup which will results mostlikely in a O(n^2) or a O(n*log n) algo.

Hmm, I was expecting a bit more to work with. Anyway, let’s see.

I don’t get this one. A matrix is a list of lists. But this is not important. what matters is what you want to put into these lists/arrays/matrices.

I guess what you wanted to say is that collision filtering is not done based on masks or groups, but by explicitly specifying which objects collide with which other objects. This means we have to manage and store information wether or not a pair of objects should collide or not. Can be done in (at least) two ways:
(1) on the world we store pairs of objects which should collide.
(2) on each object we store which other objects should collide with the object.

Both are management nightmares when objects get removed or destroyed. However, do you want to pick up from here, maybe specify methods suited for management of the required data in both cases?

Here is just one idea.

Make new filtering algorithm based on new one (collision groups). Add optional variable “tagId” or something like that, and if two nodes have same “tagId”, they do not collide.

Complicate it a bit more:
Add another bitmask to node, if two nodes have same “tagId” they will use that new bitmasks to check whether they should collide. If they have different “tagId” use “ordinary” collision filtering (symmetrical matrix from groups).

tagId would be some int that we provide or that you create from string.

enemy1:1
enemy4:2
player1:3
rudolph:4

so i would call .setCustomMagicTagName(“player1”)
for player capsule,weapon,ammo going out,each body part.
Then i would disable collision between body capsule(used for walking on terrain) and body parts and weapons (close combat or ranged, does not matter).
So player for example would not cut himself with sword , but would be able to hit enemies with same sword :slight_smile:

I used “tagId”, “groupId” is probably better name, but it could lead to some confusion regarding collision groups.

For almost all scenarios i could think of, special handling of collision is needed only for objects in one group. And with this approach you dont need to traverse array of deny objects
So basically its just one “if” on top of current group based system, and some extra stuff in memory.

I am aware of my problem with explaining things, so if you prefer i could write some python (others call it pseudo code :slight_smile: ) its rather simple system.

if obj1.tagId == obj2.tagId:
    #use "secondary" bitmasks of both objects
else:
    #use "normal" bitmasks for both objects

Ok, thank you for your input. So far I have no idea where we will go in the end, and I really consider providing a Python callback now. Further ideas are always welcome.

to idea 2 some pseudocode:
collisioncallback(bt_obj1,bt_obj2)
if bt_obj1 in bt_obj2.ignorecollisionwith or bt_obj2 in bt_obj1.ignorecollisionwith:
return
[…]

Assuming that bullet uses ids there would be no problem with cycle references but im not in the bullet internas.

Just wanted to drop a note that I did not forget about you. I currently have a bunch of bullet source code files modified, because I try something, and would like to finish this and check in before I start working on something else.

Ok, I added a third collision filtering algorithm: a Python callback function. This is probably the most flexible one, but also slower than the others.

In oder to have this collision filteirng algorithm installed you have to set the config variable

bullet-filter-algorithm python-callback

Setting the callback function is simple:

self.world.setPythonFilterCallback(self.filter)

The callback itself is called with two PandaNodes, and should return a bool value (True if the objects should collide, False otherwise):

def filter(self, node1, node2):
  ...
  return True

I updated the Bullet samples archive - a new sample for this collision filter algorithm is added.

Using Panda Bullet, how can I set the CFM/ERP parameters of BulletConstraint()'s?

In C++ code

constraint->setParam(BT_CONSTRAINT_STOP_CFM, myCFMvalue, index)
constraint->setParam(BT_CONSTRAINT_STOP_ERP, myERPvalue, index)

How would one set those parameters in Panda Bullet? I looked at BulletConstraint’s API, as well as those who inherit from it (BulletHingeConstraint) and found no method to.

Thank you,
~powerpup118

These parameters are not exposed so far. I have just added them.

Thank you Enn0x, I really appreciate all of your work.

Thank you :smiley:

~powerpup118

Hello,
I’ve tried to use an egg file as a map for a test, and … look at the screen shots:

The code i used for the map is:

	# Load the environment model.
		self.map = self.loader.loadModel("models/map")
		geom = self.map.findAllMatches('**/+GeomNode').getPath(0).node().getGeom(0)
		mesh = BulletTriangleMesh()
		mesh.addGeom(geom)
		shape = BulletTriangleMeshShape(mesh, dynamic=False)
		body = BulletRigidBodyNode('map')
		bodyNP = self.worldNP.attachNewNode(body)
		bodyNP.node().addShape(shape)
		bodyNP.setCollideMask(BitMask32.allOn())
		self.world.attachRigidBody(bodyNP.node())
		self.map.reparentTo(bodyNP)

Where is the problem ? Blender 2.63 don’t export (with Yabee) the blend file, but with export directx and x2egg, i can use it with panda. But is it possible that there is a problem with the geom ?

Here is the blend and egg files : http://www.benicourt.com/bullet/models.rar

The problem ist that the geom you pick from the loaded model has a transform, which you not regard when creating the collision mesh:

...
<Group> Root {
  <Transform> {
    <Matrix4> {
      1 0 0 0
      0 0 1 0
      0 1 0 0
      0 0 0 1
    }
  }
  <Group> Root1 {
...

Good luck that you .egg file only contains one geom, because you only regard the very first geom found inside the .egg file.

This is a more complete ways of creating collision meshes from models:

    np = loader.loadModel('map.egg')
    mesh = BulletTriangleMesh()
    for geomNP in np.findAllMatches('**/+GeomNode'):
      geomNode = geomNP.node()
      ts = geomNP.getTransform(np)
      for geom in geomNode.getGeoms():
        mesh.addGeom(geom, ts)
    shape = BulletTriangleMeshShape(mesh, False)
    ...

Anyway, it might be very convenient to simply create collision meshes from visible models. And Bullet and PhysX can do collision detection with triangle meshes quite fast, but I still recommend using simplified meshes for collisions.

@ enn0x, thank you very much, i’ve modified the egg file, only the transformation matrix, and it’s good. In the panda manual, i’ve read that the model must not have a scale transformation, not a rotation… now, i know.
I’ve noticed also the code if there is more than one geom. Thank you again.

I tried to compile a c++ panda program wishing to use bullet.

I get

1>C:\Panda3D-1.8.0\include\bullet_includes.h(20): catastrophic error: cannot open source file "btBulletDynamicsCommon.h"
1>  #include "btBulletDynamicsCommon.h"

So what are the bullet include files needed for use in a c++ panda app, and where are they located. Grazie.

Another concern: I tried to compile a complete Panda3D version including the latest Bullet svn (2.8?) (from bullet svn repository).
Here is what I get.

Zonzagolo

The Panda3D Bullet module is a wrapper/integration for the C++ Bullet library. The classes provided by the Panda3D Bullet module “wrap” original Bullet classes. Therefor they need to know the original Bullet objects, and in order to compile you need the Bullet headers and libs. Ok, but I think you already know this.

  1. Dependencies of Panda3D are located in a so-called “third-party” libs directory, which should be downloadable from the Panda3D download section (for Windows users). There are only a few exceptions, like the Platform SDK, DirectX or PhysX). Bullet headers and libs should be there too.

  2. The latest Bullet SVN is not working - you need the right version of the Bullet headers and libs. Either from the third-party libs, or from Bullet SVN. I am using Bullet SVN r2476, and I think rdb has the same version on the Panda3D build machines.

A bit more information if you like to know: Bullet is an active project, and changes it’s API frequently. Keeping up-to-date would mean (1) a lot of work for us, and (2) possible changes to the Panda3D Bullet API if the Bullet API changes. This is not what we want, because people using Panda3D should have some consistenty of the API they depend on.

Our update plan look like this:

  • Update to the latest Bullet SVN for each new “feature” release of Panda3D (1.8.0, 1.8.2, 1.8.4, 1.9, … you get the pattern - odd releases are mainly bugfix releases).
  • Update to the latest Bullet SVN if there are critical bugs which require a newer Bullet version for fixing.

Grazie,
I can’t find svn2476 in code.google.com/p/bullet/downloads/list, is svn2440 ok or outdated?

No problem with the headers in the Third-party directory, my first question was: what are the headers to be included in a panda3d c++ bullet program?

It is a little bit confusing since during a full panda3d build (without installer) it appears that some directories are not copied automatically by makepanda into the build directory hierarchical structure, and some manual transfer has to be done.
With Python this is ok but It’s not clear where to put the various bullet headers and files such as “btBulletDynamicsCommon.h” so that a Panda C++ program can refer to them.

If I remember right there has not been much changes betweem 2440 and 2476. You could give it a try - I can’t tell for sure without trying myself.
Of you could use an SVN client to get exactly the version r2476 from the SVN server.

The following source file has a list of all include which are required: panda/src/bullet/bullet_includes.h

#include "btBulletDynamicsCommon.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
#include "BulletCollision/CollisionShapes/btConvexPointCloudShape.h"
#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h"
#include "BulletCollision/Gimpact/btGImpactShape.h"
#include "BulletDynamics/Character/btKinematicCharacterController.h"
#include "BulletDynamics/Vehicle/btRaycastVehicle.h"
#include "BulletSoftBody/btSoftBodyHelpers.h"
#include "BulletSoftBody/btSoftBodyInternals.h"
#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"

Umm… I’m a bit confused here too. There is no need to copy anything usually. Panda3D’s include directory contains only the header files of the Panda3D objects. The third-party header files should be picked up by a C++ program directly from the third-party directory.