How to rotate and translate a ofxBullet body?

I would like to know how to manipulate a ofxBullet body rotation and translation, for example how to rotate a body with the arrow keys?

Googling around I came across btTransform on this link http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6282 but I have no idea how to use it to rotate an object.

Any help will be much appreciated.

1 Like

Hi nardove,

You can use a btTransform to apply all transformations to the rigid body. Keep in mind, that if you do not make the rigid body static, it may react weird if the bullet world is also trying to manipulate it.

There are some helper functions in ofxBullet. https://github.com/NickHardeman/ofxBullet
You should check out ofxBulletUtils.h and some of the create functions for shapes that take an ofQuaternion as an argument.

I haven’t tested the code, but this should be a good start.

  
  
// transform of the rigid body, which we will get from the object and then manipulate //  
btTransform tr;  
// position of the object in world coords //  
ofVec3f myPos;   
ofQuaternion myQuat; // this is what you can manipulate with arrow keys // etc.  
rigidBody->getMotionState()->getWorldTransform( tr );  
// set the position //  
tr.setOrigin( btVector3( btScalar(myPos.x), btScalar(myPos.y), btScalar(myPos.z)) );   
// zero out rotation, if you want //  
tr.getBasis().setEulerZYX( 0,0,0 );   
// apply your quat rotation to the transform //  
tr.setRotation( btQuaternion(btVector3(myQuat.x(), myQuat.y(), myQuat.z()), myQuat.w()) );  
// apply your new transform to the rigid body //  
rigidBody->getMotionState()->setWorldTransform( tr );  
  

If you want to get the orientation and position of the rigid body, check out the following

  
  
btQuaternion rotQuat	        = rigidBody->getWorldTransform().getRotation();  
ofVec3f	rigidBodyPos	= ofGetVec3fLocFromRigidBody( rigidBody ); // see ofxBulletUtils.h //  
btVector3 btaxis			= rotQuat.getAxis();  
ofVec3f axis			= ofVec3f( btaxis.getX(), btaxis.getY(), btaxis.getZ() );  
float angle				= rotQuat.getAngle();  
  

Let me know if that works out.

Hi Nick sort of work to be more specific I am trying to apply the rotation to the ground body in the Simple example from the ofxBullet addon, I try your code and I manage to rotate the grey box but the debug green outlines doesn’t rotate, I guess that green outline box is the collision shape I try to apply the rotations to that shape but unsuccessful any ideas?

Many thanks

  • rS

Ahh yes. The problem is that the object you are manipulating needs to be declared as kinematic. It must have a mass of 0.f!! Then you must apply your transformations and activate the rigid body. I have updated ofxBullet to include this in the shapes. You need to pull the latest from git to have the convenience functions
https://github.com/NickHardeman/ofxBullet

Code example spinning the ground from the Simple Example below:

In your setup function:

  
  
// set quaternion, so we know which way is up //  
ofQuaternion groundQuat;  
groundQuat.set(0, 1, 0, 1.);  
ground.create( world.world, ofVec3f(0., 5.5, 0.), groundQuat, 0., 10.f, 1.f, 10.f );  
ground.setProperties(.25, .95);  
ground.add();  
// allows manipulation of object. The object will not react to other objects, but will apply forces to them //  
// just like a static object, except you can move it around //  
ground.enableKinematic();  
  

Now in the update function:

  
  
// store the position of the ground //  
ofVec3f pos = ground.getPosition();  
  
// create a bullet transform object and set the position to that of the object //  
btTransform trans;  
trans.setOrigin( btVector3( btScalar(pos.x), btScalar(pos.y), btScalar(pos.z)) );  
  
// get the rotation quaternion from the ground //  
ofQuaternion rotQuat = ground.getRotationQuat();  
// print out the angle  
cout << "rotation " << rotQuat.w() << endl;  
float newRot = rotQuat.w();  
// rotate it a bit //  
newRot += .01f;  
// clamp values between PI and -PI so there is no jumping //  
if(newRot >= PI) newRot -= PI;  
if(newRot <= 0) newRot += PI;  
  
// set the rotation of the bullet transform to that of the axis of the stored quaternion  
// and apply the new rotation   
trans.setRotation( btQuaternion(btVector3(rotQuat.x(), rotQuat.y(), rotQuat.z()), newRot) );  
// apply the transform to the rigid body //  
ground.getRigidBody()->getMotionState()->setWorldTransform( trans );  
// tell the ofxBulletWorldRigid that we have moved rigid body and it should update the collision object //  
ground.activate();  
  

I have tested out this code and it appears to work. Let me know if you have any issues. :slight_smile:

2 Likes

Awesome that did the trick!

Nice one Nick thank you very much for the help

Hi,

I am trying to understand how to rotate some boxes I am creating from default “vertical position”. Can I create the boxes on the rotation position I like? Or must I make the rotation after the creation like its explained above here?

Also, it’s the center of the box the position taken as point?

    boxVector = pointTo - pointFrom; // botton to top side of the box
    groundQuat = ofQuaternion(boxVector.x, boxVector.y, boxVector.z, 0); // ?
//            groundQuat = ofQuaternion(0., 0., 1., 0);
//            groundQuat = ofQuaternion(1., 0., 0., 0);
//            groundQuat = ofQuaternion(0., 1., 0., 0); 
    ((ofxBulletBox*)boxes[boxes.size()-1])->create( world.world, boxCenter, groundQuat, 0.5, boxSizeX, boxSizeY, boxSizeZ);
    boxes[boxes.size()-1]->add();

I can’t understand how to do it. I don’t understand how to use the Quaternion and where to start to read… I am very lost as you can see…

Should I use one quaternion for each of the 3 axis and make his own degree rotation?

(There’s some // in degress // section on ofxBulletUtils.h but it’s commented and not implemented)

You can pass in the quaternion like you are doing to the create function.
It might be easier to use an ofNode, do you rotations on that since there are some convenience functions like tilt, pan and roll and then pass in node.getOrientationQuat()

1 Like

I have been working on the orientation issues. Bullet handles quaternions different than OF. I am working on a dev branch to be ready for OF 009. I added a convenience function that will work with older versions of Bullet.

static btQuaternion ofGetBtQuat( ofQuaternion aQuat ) {
    float angle;
    ofVec3f axis;
    aQuat.getRotate( angle, axis );
    btQuaternion btquat;
    btquat = btQuaternion::getIdentity();
    btquat.setRotation( ofGetBtVector( axis ), angle * DEG_TO_RAD );
    return btquat;
}

I also added a rotation example to the branch that I am currently developing. But you will have to use the above function to convert from OF quat to bullet quat when passing to the function. Or you could just pass in the bullet transform using

static btTransform ofGetBtTransform( ofVec3f aGlobalPos, ofQuaternion aQuat ) {
    btTransform trans;
    trans.setIdentity();
    trans.setRotation( ofGetBtQuat(aQuat) );
    trans.setOrigin( ofGetBtVector( aGlobalPos ) );
    return trans;
}

If you are wondering how to create quats along a direction, check out this example. IF you are using an older version of bullet, you will have to use ofGetBtTransform after calculating the OF quat.

2 Likes

Wow man! I had not seen that you had responded until now! Thanks a lot. I’ll check soon. :smile:
Thanks again for your support and your addon work, of course.

PS: btw, On the github issue I wrote you some days ago, I didn’t replied you because I am not sure, but maybe the Xcode examples projects were not working. Anyway the addon (master branch) is working fine now with the 0.9 like expected!!

Glad to help. Working towards 09, so some of the examples might be broken. :blush:

Let me know if any other issues arise

1 Like

Hey @NickHardeman. cool! I made it work like you said; using the 009 branch and looking to the rotationExample:

            boxVector = pointTo - pointFrom;
            posBox = (pointTo + pointFrom) * 0.5;
            boxLength  = boxVector.length();
            
            boxVector.normalize();
            
            boxSizeY = boxLength - boxesMargin;
            
            boxes.push_back( new ofxBulletBox() );
            
            ofVec3f localBoxAxis( 0, 1, 0 );
//            ofVec3f localBoxAxis( 1, 0, 0 );
//            ofVec3f localBoxAxis( 0, 0, 1 );
            
            ofQuaternion rotation;
            rotation.makeRotate( localBoxAxis, boxVector );
            
            ((ofxBulletBox*)boxes[boxes.size()-1])->create( world.world, posBox, rotation, 0.5, boxSizeX, boxSizeY, boxSizeZ);
            
            boxes[boxes.size()-1]->add();

PS: Now, on this tree structure, I am trying to learn how to articulate it (with forces like wind) around nodes between boxes, like a tree / arm elbow / bones. I am using joints to try to limit the movements with the join constraints. I am using ofxBullet just for this, and I am not sure if there is another easier way… Anyway I’ll open soon a new thread on the forum and I’ll post the link here too! Thanks a lot for your help.

Hey @NickHardeman, here’s the link to the topic I opened about the articulation I was talking about:

Nothing worked for me here :(,
but after visiting the bulletphysics forum, I tried this
sphere->getRigidBody()->setCenterOfMassTransform(trans);

instead of:
ground.getRigidBody()->getMotionState()->setWorldTransform( trans );

I works in my case :slight_smile:

Hey guys,
I work on a Project where i want to controll the Orientation of a ofxBullet Object via a Motion Sensor. For example your Task could be to balance a ball on a board without dropping it.
I tried to use the code posted earlier, and i did manage to rotate the ground box. So far so good.
Furthermore i tried to update the code so I could change the rotation of the ground by a butten press.
But it didn’t work like I imagined.
My Problems:
If I rotate the groundbox, the wireframe stays in the original position and other objects collide in the same way as if it hasn’t been rotated.

I managed to rotate the box on the mouse button release (by putting basically the whole code postet earlier by Nick Hardeman, in the mouseReleased method), but only once. I mean, the box rotates only on the first button release and stays in the position even if I press it again.

I don’t really have any code example. I tried to change the newRot variable to change the rotation. Which worked. But with that I only know how to rotate the obj on one axis. I’m absolutly overstrained and need help. :smiley:

I’m pretty new to Openframeworks and ofxBullet and can need all the help possible. I also hope my english is understandable.

Thanks in advance!
Cheers
Mikko