Panda Bullet


#538

Hi,

I’m new to panda and I scout possibilities of bullet. Here’s thing what I try to achieve:

  • have instance of BulletCharacterControllerNode (call it ‘player’)
  • have instance BulletRigidBodyNode (call it ‘box’)
  • ‘player’ perform jump, collides with ‘box’ which is placed above and is knocked back

Now I want to eliminate that knockback. The only thing I’m able to do is to get instance of BulletContact via BulletWorld.contactTestPair(player, box). But I don’t know what can I do with it. Can someone give me some hint? Thanks.


#539

Okay, that’s totally alright with me then, my next question would be what is the easiest way to remove/add a body returned by BulletWorld.contactTest(…)?

Problem I ran into was that BulletWorld.contactTest(…) returns ‘const’ bodies? and so when trying to remove the body, I get the following error:

TypeError: BulletWorld.remove_rigid_body() argument 1 may not be const

Or how else can I remove/add the body? I found a small workaround, by searching the scene graph for a node with a name of the body’s name (bodyNode.getName()) however this only works if each bodyNode has a unique name, any other way to work around this?

That’s actually originally why I wanted to ask about changing objects masks

Thank you,
~powerpup118


#540

Hello, and welcome.
I’m afraid there is very little you can do. The Panda3D Bullet module just exposes the “original” Bullet character controller - it does not implement it’s own character controller. And the original character controller which comes with Bullet is quite incomplete. In particular the interaction between the character and other collision objects is not implemented. The lack of this feature is what you experience. The physics engine detects an overlap of two objects and just pushes them away from each other, without regard of mass or other physical properties. We do mention this lack of features in the Panda3D manual already: http://www.panda3d.org/manual/index.php/Bullet_Character_Controller

What we would need to do is to write our own, better character controller. This is quite a lot of work, and so far I don’t feel able to approach this task. A second aproach would be to find some reference implementation of a better character controller (based on Bullet) within some other open source engine, and adapt it to our Bullet wrappers.

Right now you hit a limitation of the Panda3D Bullet module. Sorry. Any ideas are welcome.


#541

This is the underlying Bullet callback method which gets called when performing a contact test:

virtual btScalar btCollisionWorld::ContactResultCallback::addSingleResult(
    btManifoldPoint &cp,
    const btCollisionObject *colObj0,
    int partId0,
    int index0,
    const btCollisionObject *colObj1,
    int partId1,
    int index1)

Both collision objects are CONST pointers. This means that the collision objects can not be modified within this method. What I do in BulletContactResult is simply store these const pointers and return the associated Panda3D objects (i. e. BulletRigidBody), as CONST pointers.

Usually there is a reason why an API designer passes or returns const pointers or objects. Since Bullet documentation is a bit spares I can only guess why the Bullet API passes a const pointer here: because it will lead some kind of crash if a user modifies the collision objects from within the callback.

But enough of an explanation - what can be done?

(1) Your solution is probably the best way to go. Identify somehow the panda node within the scene graph, and use this node remove/add it from the world. You can do this either by giving each node a unique name, like you mentioned. Or you can set identifying ids on each node (via setPythonTag) and look up the node in a local dictionary. Maybe you are able to do some magic using NodePath’s.

(2) I could try to cast away the const-ness of the Bullet collision object, and then have you test what happens if you modify the returned node. But it is usually not a good idea to cast away const-ness. I’d prefer not to do so.


#542

I removed the const-ness of the nodes returned by BulletContactResult.getNode0 and BulletContactResult.getNode1. So far I did not experience any crash or other problem.


#543

In order to fix the bug https://bugs.launchpad.net/panda3d/+bug/916732 I have renamed the following two methods:

BulletCharacterController.setLinearVelocity --> setLinearMovement
BulletCharacterController.setAngularVelocity --> setAngularMovement

#544

Hi, thanks for your response. After all I solved it by using BulletRigidNode with a few extra constrainst instead of using BulletCharacterController. Character doesn’t bounce away after collision, but only slides on sufrace as I wish: https://www.youtube.com/watch?v=3kAKeF2TltQ


#545

Hi, I’m using Bullet to create collision polygon and check collisions in my simple application.

How can I handle collisions? Can I use Panda Collision Handler and Traverser to check collisions among Bullet collision shapes?
There’s a Bullet method to catch collision events (similar to Panda’s CollisionHandlerEvent)? The only method I’ve found at this time is contactTest
thank you


Bullet collision handler
#546

What do you mean when you say “handling”?

If you mean to get events whenever collisions are detected, then yes, this is possible. Or you can explicitly test for contacts (contactTest). It you want to modify the contact properties then no, this is not exposed.

To get contact notification events you first have to enable this feature via a config option, e. g. like this

from pandac.PandaModules import loadPrcFileData
loadPrcFileData('', 'bullet-enable-contact-events true')

Then you have to activate the creation of contact events for particular nodes, and you have to listen for the created events:

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

    boxNP.node().notifyCollisions(True)

The methods which get called must have this signature:

def onContactAdded(self, node1, node2):

#547

Hi Enn0x,

I have a question in general about Bullet, and thought perhaps you would know the answer (or at least be able to share your knowledge)

is Bullet physics predictable? Or does Bullet use random numbers somewhere?

Example: If I set up a scene with boulders falling off a hill, and I ran that at the same exact point in time, on one thousand different computers, would the boulders fall exactly the same way, assuming that they started at the same time?

Would I need to pass specific parameters into BulletWorld.doPhysics(), in that case?

I only ask as I am interested in using Bullet physics are artificial intelligence (monsters ‘running’ towards players etc) and having all monsters synced across every client using a timestamp, for instance.

if you could shed any knowledge on this,

Thank you,
~powerpup118


#548

I am not aware of any random numbers used within the Bullet source code. But I can not tell for sure, since I just use the Bullet library and don’t know it’s sources by heart. So yes, Bullet can be deterministic.

Here are a few tips to get as much determinism as possible (not specific to Bullet, but any physics engine we support):
1.) The biggest problem with determinism is that you have to completely decouple the physics simulation from the game loop.
2.) Fixed timesteps are mandatory for determinism!
3.) Never use the computers time - not even if you have a secure time server (e.g. IEEE 1588 Precise Time Protocol) in your network. In other words: feed only constants to BulletWorld.doPhysics, and never variables.
4.) Don’t sync between clients using a timestamp - use the integral count of the simulation frame.

All the samples I have written so far do not care about determinism or decoupling physics from framerate. I even do not bother to some time slip because of user input handling. It’s probably a question of how much determinism you really need.


#549

This is great news to me!

I knew about all of your points (decouple the physics simulation from the game loop… fixed timesteps… no using computer’s time…)

Very good idea about using integral count of the simulation frames vs a timestamp, I would have never thought of that.

Thank you again,
~powerpup118

P.S. will try to get a sample going at some point in case anyone else is interested in the same idea


#550

Hi,

I’m having issues with the bullet implementation, when my physics driven object gets around 15000 units away from the origin point the object starts to jitter. It seems as if it’s some sort of floating point precision issue.

My question is, is the build of bullet in panda a double precision build or is there any other way you know I could handle these large worlds ?

I’ve tried making sure no other bullet enabled objects is further than ~4k units in order to try to minimize the floating point “stretching” but it seems to have no effect.

I’d rather not try to move the bullet world origin because I think this would create a lot of messy situations that are hard to debug.

I’ve heard plenty of good things where scaling the bulletworld and it’s occupants can solve plenty of issues. bulletphysics.org/mediawiki-1.5. … _The_World
But would this also imply you cannot make an “infinite” world within bullet ?

Regards
Red15


#551

The default build settings are - afaik - single precision. You can compile with double precision too, but you have to compile both Bullet AND Panda3D wird double precision.

Infinite is a tricky word when dealing with computers. If a floating point value is to be kept in on CPU register then there is a limit for it’s size. On the other hand, when using arbitrary size/precision numbers performance drops to inaceptable values. In other words: out of the box no physics engine supports infinite worlds. By the way: infinite worlds also imply infinite objects! If the number of objects is finite then the size is also finite.

Even more problematic than huge scales are huge differences is size, i. e. very small objects and very large objects in one scene. You should keep rations below a few decades, or you will become unstable results.

I don’t know a real scenario where you need an infinite world. If you have large objects at large distances you could use another scale: maybe 1000 meter per unit, or 1 lightyear if you want (default is 1 meter per unit).

If you can’t scale your world then think about particioning your universe. Attach only those objects to a particion which CAN interact with eachother. If you have a starship fighting in the asteriod belt of one solar system then obviously the next solar system is of no importance.

Besides this non-Bullet specific advide you should have a look at the config variables “bullet-broadphase-algorithm” and “bullet-sap-extents”.


#552

Is there a specific reason only single precision is chosen for panda / bullet compilation ? Does it yield more performance or less memory usage when using only single precision?

This I understand, apparently bullet by default works best with objects scaled from 0.05 to 100,

The problem with scaling my world up is that it makes me scale the moving objects to ridiculously small scales, for example 1 object is about 3m³ on my current scale of 1 unit = 1m, scaling the unit to say 1 lightyear would make my object something along the scale of 3.0e-100 which would bring again the floating point precision problem back.

So this means I could make a different world “partition” per sector ? Would there be problems when these worlds would “overlap” and thus objects could be attached to 2 (similar) worlds when transitioning from one world to another ?

Thanks for your swift reply and accurate assessment of my problem.


#553

Both, better performance (in most cases) and less memory. Also consider that the transforms passed to Bullet come from Panda3D nodes and Panda3D is compiled with single precision by default. It does not make sense to have double precision computation for physics if all input is delivered in single precision.
-> Default is single precision Panda3D and single precision physics
-> If you need you can compile yourself and SETUP both Panda3D and Bullet for double precision.

Huh? As far as I know one lightyear is 10e11 meters and not 10e100. Anyway, I didn’t say you should scale to 1 unit = 1 ly. I said you should choose a reasonable scale, which depends on the sizeof your objects AND the spacing between your objects.

I don’t think you have 3 meter large objects which are separated by 1 lightyear. Consider that at a distance of 100 km your 3-meter-object would be less than one pixel on your screen. 3D graphics simply don’t make sense at such scales.

So please disclose how large your objects are and what the distances between your objects are.

I think there is a bit of a misunderstanding here. sure, you can have multiple worlds at the same time, and these worlds can overlap. But there won’t be interaction BETWEEN the worlds, i. e. objects from one world colliding with objects of another world.
Sidenote: PhysX offer such a feature.

What I meant is to divid your universe into smaller areas, and do physics simulation only for the local area. When moving on to another area stop simulating the first area and continue with the next area. There can be overlap between areas, of course. The main difficulty is to write a manager which activates/deactivates areas.

It’s up to you if you use one BulletWorld instance for each area, or re-use a single BulletWord instance.


#554

I’m planning on using the bullet engine not only for graphics but for a dedicated server which will need to simulate all active areas so

It is the worst case scenario, I will have human size objects to building size objects seperated maximally by some 2 ** 32 units

Not even if an object is attached to both worlds ?

I have tried removing all objects from the BulletWorld instance (except my player) but when my player goes beyond that ~15.000 unit mark the shaking still happens, would that mean I would have to ‘recenter’ the bullet world to avoid having big numbers ?

This would cause serious trouble if I was to try to implement the different worlds which overlap because they would all have to become centered around 0.0 and thus an object would be at 0,0,-1000 in the old zone while in the new zone it would be at 0,0,1000

Again this would only be on the server side which needs to do validation of all players / objects moving around (client side I guess I could cheat a bit more with only having one BulletWorld etc)


#555

Since you didn’t tell me how many units a “human” is I am going to assume that a human is 2 units tall. In other words, 1 unit is 1 meter.

Now come on, 2**32 meters (=4294967296) is 700 times the radius of our planet. And this is just one dimension of extent! Assuming your world has not much z-extent you have an area of 18446741531089 square kilometers!

Even if you have only one collision primitive or triangles per square kilometer you won’t find a server which has enough memory to hold all these objects, let alone CPU power.

No. I don’t know what would happen if you do so, but most likely nothing useful. One object should be part of only one world.

This is strange. I modified both my basic and my character sample in such a way that the objects are located around (17000, 0, 0), and I get no shaking at all. Can you post a working sample which reproduces your problem?


#556

Correct

Actually the world would be (2**32) ** 3 in size but will not contain an awful lot (space is mostly empty you know :slight_smile:

However it does contain some stuff and when users are zipping through this massive space at a relative high speed I would still like to have correct collision handling. I’m not expecting the user to cover more than 1000m (or units) per second though so this is why I’d like my world to be roughly 2000-3000 units across to make sure they at least “enter” a world instead of zipping over it without “landing” in one of the intermediate worlds.

Not every zone has to be activated at the same time, only if players are near the zone in question, similar like minecraft chunks for instance.

So you would suggest creating an intermediate world in between 2 worlds which would contain the transitioning objects ? This seems rather counter-productive, means even more worlds in memory: 3 worlds for one object transitioning from world A to world B in zone AB_transition or something.

I would rather attach the object to both worlds and as long as nothing is hindering it’s path it will be a smooth ride. I will try writing a small proof of concept soon.

Will combine this with my effort of transitioning worlds concept.

Again enn0x, thanks for all the time you’ve put into reading/answering my posts. If you’re ever in Belgium stop by and let me at least get you a beer or something :slight_smile:


#557

First of all enn0x: congrats on 1000 posts :slight_smile:

Secondly, I’ve upgrade to 1.8.0 release and have found a bug, I’ve been able to confirm that it happens on ubuntu 64 bit but not on Windows platform.

The problem occurs when I attempt to do following (simplified) code:

world = BulletWorld()
body = BulletRigidBodyNode()
world.attachRigidBody(body)

body.set_mass( 100 )
body.set_angular_damping(0)
body.set_linear_damping(0)

mesh = BulletTriangleMesh()
mesh.addGeom(...)
body.add_shape( BulletTriangleMeshShape(mesh, dynamic=True) )

def update():
	""" Gets called after each doPhysics call """
	contacts = world.contactTest(body).getContacts()
	for contact in contacts:
		mpt = contact.get_manifold_point()
		collide(mpt)

def collide(manifoldpoint):
	print("collide", manifoldpoint)
	impact_force = manifoldpoint.get_applied_impulse()
	print("impact_force:", impact_force)

The error occurs in the call manifoldpoint.get_applied_impulse() it just segfaults out. Ofcourse this only happens when a contact was happening with this body and it does not seem to crash at the first touch either, the print statements get called a few dozen times usually before it crashes.