nardove — 2011-11-16T16:42:46-05:00 — #1
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.
nickhardeman — 2011-11-21T14:31:13-05:00 — #2
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 //
// position of the object in world coords //
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.
nardove — 2011-11-21T16:03:37-05:00 — #3
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?
nickhardeman — 2011-11-22T10:51:12-05:00 — #4
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
Code example spinning the ground from the Simple Example below:
In your setup function:
// set quaternion, so we know which way is up //
groundQuat.set(0, 1, 0, 1.);
ground.create( world.world, ofVec3f(0., 5.5, 0.), groundQuat, 0., 10.f, 1.f, 10.f );
// 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 //
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 //
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 //
I have tested out this code and it appears to work. Let me know if you have any issues.
nardove — 2011-11-24T08:25:42-05:00 — #5
Awesome that did the trick!
Nice one Nick thank you very much for the help