Search code examples
c++openglmatrixrotationbulletphysics

Rotate rigidBody on its edge?


I'm creating a simple game that involves swinging a club using the bullet library in c++. However, I'm having trouble rotating the club (rigid body) the way I want.

For reference, here is the club structure:

struct Club {
    btRigidBody *btPhys;    
    btScalar rotateAmount;
    btVector3 axis;
}

Here is how I rotate the club:

//Create a rotation matrix from the club's world transform 
btMatrix3x3 orn = club.btPhys->getWorldTransform().getBasis();
//Apply a rotation to the matrix
orn *= btMatrix3x3(btQuaternion( btVector3(0, 0, 1), btScalar(degreesToRads(club.rotationAmount))));
//Set the rotation of the club
club.btPhys->getWorldTransform().setBasis(orn);  

However, this just rotates the rigid body on the center of the club. I want the rigid body to be rotated near it's edge (the club's handle).

So I added a transform to move the club upward above the pivot point: (this code follows directly after the previous code)

btTransform trans;
//Get the club's trasnform
club.btPhys->getMotionState()->getWorldTransform(trans);
float x, y, z;
x = trans.getOrigin().getX();
y = trans.getOrigin().getY();
z = trans.getOrigin().getZ();
//Set the transform to be 2 units above the club's origin (the club is 4 units long)
trans.setOrigin(btVector3(btScalar(x), btScalar(y + 2.0f), btScalar(z)));
//Apply the transform to the club
club.btPhys->getMotionState()->setWorldTransform(trans);

However, this doesn't change the pivot point, it just moves the club above the pivot point (creating an unwanted space).

In short, the rotation matrix just rotates the rigidbody around it's center. I just want to move the pivot point from the center of the rigid body to the edge of the rigidbody.


Solution

  • SetWorldTransform of MotionState always transforms the body around its center of mass.

    There are two ways in which you can solve your problem. If you're using btDefaultMotionState as your motion state, you can specify the offset of center of mass in the constructor. This way the body will rotate around another point. There is however a serious side effect of this approach. All physical interaction with this object will treat the new pivot point as the center of mass. If your body is kinematic, it is perfectly fine but if it is dynamic, the effects may differ from desired effects.

    Another probably more safe approach is to stack 3 transformations together to achieve the rotation you're looking for. First, translate the body to the location of desired pivot. Next, rotate it. Finally, translate it back where the center of mass should be.