Panda Bullet

Hi,

is it possible that with “groups-mask” enabled BulletGhostNodes are not affected by the set flags? Because if i replace the BulletGhostNode with BulletRigidBodyNode the collision is dropped correctly but i cannot use BulletRigidBodyNode because i get bounceeffects on my triggervolumes realized with BulletGhostNode.

Is it possible to use Bullet only for colision detection for the floor and wall, without the physics?

In theory if you use ghost objects, they should be only checked for collisions, no much sense to simulate ghosts?

Sorry for the long delay. We had a very very busy time at work, and I din’t even turn on my computer when getting home late in the evening. But back again now. I try to catch up with all the posts regarding Bullet the next days.

Hmm… I didn’t know this so far. But you are right. Since our filter callbacks make no difference between rigid bodies or ghost objects it must be Bullet itself. So far I don’t see a workaround, but I keep it in mind. Maybe I stumble over some info in future.

Bullet itself can be used as a collision-only engine, but the way we have integrated Bullet with Panda3D does not support this. Sorry.

well ghosts have no physical response so one can use them for pure collision detection, cannot one?

Yes, this is possible. I mean I have not tried it myself, but I see n reason why this should not work. However, it would also be possible to create plain rigid bodies and use

body = BulletRigidBodyNode('...')
body.setCollisionResponse(False)

This raises/clears the btCollisionObject::CF_NO_CONTACT_RESPONSE flag, which controls if a collision object should not only detect collisions, but also respond to collisions. At least if I understand the Bullet API right.

But with Ghosts you will just get something like Panda’s CollisionHandlerEvent/Queue. You will need to manually calculate wall sliding and keeping the node in the floor, right?

Yes, of course. If you use Bullet only for collision detection you have to handle collision response yourself. No matter if you use ghosts or disable collision response for rigid bodies. But this has been the original question by redpanda - if it is possible to have collision detection without the collision handling (aka physics).

to the best of my knowledge the setCollisionResponse flag deactivates the automatic handle by the queue handler too. So this is no real option (i already tested this to get something like triggervolume but switched to ghosts then).

The automatic handle by the queue handler? Sorry, but you lost me now. Are you attempting to mix Bullet collision/physics with Panda3D’s built-in collision handlers?

Sorry I just mixed up things. I mean the doPhysics + getManifolds/in-out-event way of collision handling.

I’m not sure if this is right. Even objects with collision response disabled should (1) create persistent manifold points, and (2) generate collision notification messages. But I have to verify this when at home (either this evening or tomorrow).

Might be that both ways don’t create identical results (something which hopefully is fixed when upgrading to Bullet 2.80, see coppertops thread about Bullet KKC).

This is what I used for testing:

  def update(self, task):
    dt = globalClock.getDt()
    self.processInput(dt)
    self.world.doPhysics(dt, 10, 0.008)
    print self.world.getManifolds()
    return task.cont

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

  def onContactAdded(self, node1, node2):
    print 'ADDED:', node1, node2

  def onContactDestroyed(self, node1, node2):
    print 'DESTROYED:', node1, node2

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

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

    self.world = BulletWorld()
    self.world.setDebugNode(self.debugNP.node())

    # Sphere 1
    shape = BulletSphereShape(0.6)
    np = self.worldNP.attachNewNode(BulletRigidBodyNode('S1'))
    np.node().setMass(1.0)
    np.node().addShape(shape)
    np.node().setDeactivationEnabled(False)
    np.setPos(3, 0, 0)
    np.setCollideMask(BitMask32.allOn())
    np.node().setCollisionResponse(False)
    np.node().notifyCollisions(True)
    self.world.attachRigidBody(np.node())

    self.body = np.node()

    # Sphere 2
    shape = BulletSphereShape(0.6)
    np = self.worldNP.attachNewNode(BulletRigidBodyNode('S2'))
    np.node().setMass(1.0)
    np.node().addShape(shape)
    np.setPos(-3, 0, 0)
    np.setCollideMask(BitMask32.allOn())
    np.node().setCollisionResponse(False)
    np.node().notifyCollisions(True)
    self.world.attachRigidBody(np.node())

    # Enable contact reporting
    self.accept('bullet-contact-added', self.onContactAdded)
    self.accept('bullet-contact-destroyed', self.onContactDestroyed)

Only the relevant part of the script. Two bodies, each with disababled collision response. And this is the output I get for a single pass of sphere-1 through sphere-2:

[]
[]
[]
[]
[<libpandabullet.BulletPersistentManifold object at 0x03187698>]
[<libpandabullet.BulletPersistentManifold object at 0x031876C8>]
[<libpandabullet.BulletPersistentManifold object at 0x03187698>]
ADDED: BulletRigidBodyNode S1 (1 shapes) mass=1 T:(pos -2.0112 0 0)
 BulletRigidBodyNode S2 (1 shapes) mass=1 T:(pos -3 0 0)

[<libpandabullet.BulletPersistentManifold object at 0x031878F0>]
[<libpandabullet.BulletPersistentManifold object at 0x03187698>]
[<libpandabullet.BulletPersistentManifold object at 0x031878F0>]
[<libpandabullet.BulletPersistentManifold object at 0x03187698>]
[<libpandabullet.BulletPersistentManifold object at 0x031878F0>]
[<libpandabullet.BulletPersistentManifold object at 0x03187698>]
ADDED: BulletRigidBodyNode S1 (1 shapes) mass=1 T:(pos -3.1344 0 0)
 BulletRigidBodyNode S2 (1 shapes) mass=1 T:(pos -3 0 0)

[<libpandabullet.BulletPersistentManifold object at 0x031876C8>]
[<libpandabullet.BulletPersistentManifold object at 0x03187698>]
[<libpandabullet.BulletPersistentManifold object at 0x031876C8>]
[<libpandabullet.BulletPersistentManifold object at 0x03187698>]
[<libpandabullet.BulletPersistentManifold object at 0x031876C8>]
[<libpandabullet.BulletPersistentManifold object at 0x03187698>]
[]
DESTROYED: BulletRigidBodyNode S1 (1 shapes) mass=1 T:(pos -4.4304 0 0)
 BulletRigidBodyNode S2 (1 shapes) mass=1 T:(pos -3 0 0)

DESTROYED: BulletRigidBodyNode S1 (1 shapes) mass=1 T:(pos -4.4304 0 0)
 BulletRigidBodyNode S2 (1 shapes) mass=1 T:(pos -3 0 0)

[]
[]
[]
[]

You see I get a persistent manifold point between the two objects (so the “world.getManifolds” way is working. Just keep in mind that a manifold is created as soon as their bounding boxes overlap. And I get collision events.

I beg your pardon. Seems like memory betrayed me but I was sure that my attempt to simulate a triggervolume with disabled bodies failed. I apologize for inconvenience.

No need to be sorry. I feel very uneasy with regard to Bullet’s collection reporting. There is another thread currenty where coppertop found that there are duplicated manifold points created, and despite the fact that this behaviour seems to be gone if using current Bullet version (2.80) I don’t want to claim that there is no bug on our side.

I’m really confused with the BulletConeTwiseConstraint.
After reading the manual page, I still don’t get what the TransformStates are used for, as well as swing1, swing2 and twist values. Are those respectively heading, pitch and roll of the first node the other rotates around?

I have spent a stupidly long time trying to figure out how to get collision events from bullet.

I found this on page 9 of this thread:

Is all of this still true?

If I’m understanding you correctly, I can turn on collision notification but I will get events published for each of your internally calculated contact points; potentially seeing many many notifications for each collision.

Getting some nice logical collision events would be super cool.

If you’re busy working on other features, how can I help make this happen? I’ve got a project I’m currently working on and I need this functionality, faking it in my python will be far too slow.

Welcome to Bullet. To be honest I never managed myself to fully understand the effect of those values, but they have been easy to wrap.

Ok, so here is what I know: Constraints have some “location” where the two bodies are connected. This location does not have to be inside or on the surface of either of the two bodies. Depending on the type of constraint it could be a point (e.g. ball and socket), or a line (e. g. hinge or piston).

Now the TransformStates given in the constructor are the transform to this connection point/line, given inside the local reference frames of each boy. Or looking at it the other way: when starting at the connection point/line they are the inverse transform to the two bodies.

Be aware that a TransformState does not only have an rotation (heading/pitch/yaw), but also a translation (x/y/z). Scale and shear are not used here.