rotating several btRigidBodies correctly

Post Reply
CarinaCruz
Posts: 21
Joined: Wed Mar 25, 2015 2:04 pm

rotating several btRigidBodies correctly

Post by CarinaCruz »

Hello everyone!

I have many btRigidBodies that make up a hand, and I want to rotate them from data received from a device. I tried to rotate from the quaternion but not work, the fingers of the hand give off... the palm was fixed to a point and is not what I want...


I'm using constraints to fix the hands parts, and to move the fingers i'm using a rotation in the x angle to open and close the hand (moving the fingers from a glove data).

When I try to rotate only the palm, the fingers did not follow the hand rotation, only maintained the rotation data glove...

My question is: there is a way to rotate the hand all together ? In order that the fingers and the hand move to the same direction?

:cry: :cry: :cry:

Thanks!
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: rotating several btRigidBodies correctly

Post by drleviathan »

I don't think there is an simple way to do it, but you can manually compute the transform of each body.

First you'd need to compute the relative transform of each body in its parent's local frame. Then after rotating the palm you would compute the new world-frame transforms down each chain of linked parts always doing the parent before its children.

I've done this using an array of indices that indicate each body's parent in an array. I've got an array of btRigidBody* that represent all the bodies of the hand, and an array of parent indieces:

Code: Select all

btRigidBody bodies[NUM_BODIES_IN_HAND];
int parentIndices[NUM_BODIES_IN_HAND];
So the ith element of parentIndices is the index into bodies of the parent of the ith body in bodies. Each body's parent must preceed it in the bodies array and the topmost parent (the palm in your case?) has no parent, so it must come first in bodies and its corresponding value in parentIndices is -1 which is an invalid index.

Once you have those arrays set up (maybe you already do?) then you can iterate over them to compute current local transforms and then iterate again to compute new world-transforms.

In code it would look something like this:

Code: Select all

// BEFORE the main root body is moved to its new position
// loop over bodies to compute local transforms 
btTransform localTransforms[NUM_BODIES_IN_HAND];
for (int = 1; i < NUM_BODIES_IN_HAND; ++i) 
{
    btRigidBody* parent = bodies[parentIndeces[i]]];
    btTransform parentTransform = parent->getWorldTransform();

    // NOTE: the new childWorldTransform could be computed like so:
    //     childWorldTransform = parentWorldTransform * childLocalTransform
    // HENCE: after doing math we can derive the formula for computing the childLocalTransform:
    //     childLocalTransform = invParentWorldTransform * childWorldTransform
    
    localTransforms[i] = parentWorldTransform.inverse() * bodies[i]->getWorldTransform();
}

//...

// AFTER the main root body has been moved to a new transform
// compute the new world-frame transforms of the child bodies 
for (int = 1; i < NUM_BODIES_IN_HAND; ++i)
{
    // using the formula:
    //     childWorldTransform = parentWorldTransform * childLocalTransform
    bodies[i]->setWorldTransform(bodies[parentIndices[i]]->getWorldTransform() * localTransforms[i]);
}
Note that slamming the positions of bodies in Bullet risks putting them into penetration with other bodies and causing glitches when the penetration resolution code kicks in. An alternative would be to push them there by poking their velocities or applying forces, but that would be even more math. So... try just moving them first: maybe it will Just Work.
CarinaCruz
Posts: 21
Joined: Wed Mar 25, 2015 2:04 pm

Re: rotating several btRigidBodies correctly

Post by CarinaCruz »

Thanks for the answer!

I'll try it! =)
Post Reply