ofxBullet , make ofNode position always equal to btRigidBody position?

hey @NickHardeman ! Thanks for making ofxBullet!

I’ve set up a situation where I have a series of ofNodes with of3dPrimitives as children of those nodes

I’ve also created a series of ofxBulletRigidBody’s and I want to ideally run the rigid bodies through their physics simulation, and have the ofNodes update their positions without creating an update loop that goes through both vectors assigning positions from RigidBodies to Nodes. Does that sound possible?

I was thinking I could use pointers to do that but I just tried to sketch some things out but all the functions I found that went from btTransforms to Vec3fs didn’t seem like possibilities

Hi @sterlingcrispin,

You could make a vector of shared_ptr< ofxBulletRigidBody > and then pass that reference into your class that has of3dPrimitive (which already extends ofNode ). Then you can use the shared_ptr of the rigid body to update the rotation and position of the 3d primitive in its update function.

yourNode.setTransformMatrix( yourRigidBodySharedPtr->getTransformationMatrix() );

or
yourNode.setPosition( yourRigidBodySharedPtr->getPosition() );
yourNode.setOrientation( yourRigidBodySharedPtr->getRotation( ) );

Let me know if the rotation look funky. There might have been a change somewhere regarding using radians vs. degrees.

Cheers!

3 Likes

hey thanks! I didn’t know about shared_ptr until now. Also those methods of getting pos and rot are much more straightforward

I was following some code in the utils header that was more like

btTransform trans;
rigidBodies[i]->getRigidBody()->getMotionState()->getWorldTransform(trans);


btVector3 btv = trans.getOrigin();
nodes[i].setGlobalPosition(btv.getX(), btv.getY(), btv.getZ() );

btScalar yaw, pitch, roll;
btMatrix3x3 mat = btMatrix3x3( trans.getRotation() );

mat.getEulerYPR(yaw, pitch, roll);
nodes[i].setOrientation(ofVec3f(yaw,pitch,roll));

@NickHardeman so I’m getting a ton of memory leaks and I rewrote all of my pointers into shared pointers, happy to see that ofxBulletSoftBodyMeshExample had an example of that. It’s helped a lot but I’m still not quite in the clear yet.

one thing I noticed that was causing problems was if I pushed a rigidbody into a vector before I called add() it would unpredictably crash

// this is buggy as hell
shared_ptr< ofxBulletSphere> something( new ofxBulletSphere() );

something->create( world.world, camera.getPosition(), 1, 1 );

rigidBodies.push_back(something);

rigidBodies[rigidBodies.size()-1]->add();


// but this is fine?
shared_ptr< ofxBulletSphere> something( new ofxBulletSphere() );

something->create( world.world, camera.getPosition(), 1, 1 );

something->add();
rigidBodies.push_back(something);

Do you know why? I don’t see why it would matter.

However I can modify all sorts of other properties of the rigidbody once its in the vector, as long as the shared_ptr had add() called before being pushed back, like this is fine

rigidBodies[rigidBodies.size()-1]->applyCentralForce( num );

actually I’m still getting random crashes on rigid bodies, pointers or shared pointers on this add() line , it seems to crash around 14-19,000 rigid bodies

specifically line 518 ofbtAxisSweep3.h is “EXC_BAD_ACCESS”

pHandle->m_uniqueId = static_cast<int>(handle);

called by line 234 of the same file, called by 129 of btCollisionWorld.cpp collisionObject->setBroadphaseHandle

shared_ptr< ofxBulletSphere> something( new ofxBulletSphere() );

something->create( internalWorldPointer->world, camera.getPosition(), 1, 1 );

something->add();

rigidBodies.push_back(something);

my internalWorldPointer is an ofxBulletWorldRigid that I’m initializing like so

void myClass::init( shared_ptr<ofxBulletWorldRigid> externalWorld){

    if( internalWorldPointer == nullptr){
      internalWorldPointer = externalWorld;
    }
}

and externalWorld is elsewhere in the main ofApp setup like

externalWorld = make_shared<ofxBulletWorldRigid>();
externalWorld->setup()
externalWorld->setupCamera(&cam);
etc...
myclassvar.init( externalWorld );

Is rigidBodies a vector of shared_ptr< ofxBulletBaseShape > ? I wonder if calling add() after it is added to the vector does not properly call it’s super class. In the case of your example, ofxBulletBaseShape->add() would get called instead of ofxBulletSphere->add().
The add() function is what adds the bullet rigid body to the bullet world. So if the add call is happening before the bullet world is being created, then it will crash.
The make_shared call should work. Can you try calling externalWorld = shared_pr< ofxBulletWorldRigid >( new ofxBulletWorldRigid() )?

rigidBodies is a vector o shared_ptr ofxBulletRigidBody right now, I’m a little confused why all of the examples show ofxBullet variables as some form of pointers, do they need to be?

The only thing in my instance I really want to be a pointer is the BulletWorld so I can have many classes with references to a single global world and add rigid bodies into the same context

I tried

externalWorld = shared_pr< ofxBulletWorldRigid >( new ofxBulletWorldRigid());

but I’m still getting the same results,

since the ofxBulletRigidBodies contain references / pointers to bullet instances, the shared_ptrs help maintain consistency.

For example, when pushing back references in a vector, those references are destroyed and then re-created. With a shared_ptr, then remain the same object pointing to the same pointer in memory. So you can add / remove from a vector and it shouldn’t cause issues with pointer references.

Does the crash happen when there are less rigid bodies? Maybe it’s a memory issue.
If you post more code, it might provide some more insight.

I think you’re right it might be a “memory issue” but I don’t understand what exactly. Xcode reports the program uses something like 800mb before crashing and my machine has 16GB of RAM.

I just tried a very simple program and bumped the total rigid body count to something like 16000 and it’s giving the same crash errors

example based on ofBulletJointsExample

ofApp.cpp (8.6 KB)
ofApp.h (1.3 KB)

hey so I think I narrowed the problem down to parameters I was passing to ofxBulletCylinder.create ,

If the radius is smaller than 0.0001 , the program might compile but the physics will behave really unpredictably and things will “explode” and go flying everywhere

even a zero radius is fine somehow, but smaller than 0.0001 isn’t

if the radius becomes negative, the program will still be stable as long as there’s no decimal place.

with a negative value and decimal place I’ve had the program fail to compile or crash at random unpredictable places

I just tried the same negative radius with ofxBulletSphere and it didn’t seem to have a problem, also tried passing negative height to ofxBulletCylinder but didn’t see any problems

Im still having intermittent crashes in btAxisSweep seems related to the small object issue http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=2319&view=previous

Interesting. Seems like an issue with the bullet library. For your situation, can you just make the size of the bullet objects larger?

yeah I threw in some if statements to check minimum size and make sure they weren’t too small, I do have lots of small objects but I could always scale everything up by a unit of 100 and then scale it down again before I manufacture it

FYI this is what I’ve been up to:

thanks for all your work making ofxBullet available, definitely going to make some pull requests as I keep using it

That’s beautiful. Looking forward to your progress. :slight_smile: