Hello everyone.
I'm new to bullet and I have a question please regarding rotating objects. For example, a normal box object can be created like this:
btCollisionShape* link = new btBoxShape(btVector3(0.05,1.0,0.05));
btDefaultMotionState* linkMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0.0,0.5,0)));
btScalar mass = 1;
btVector3 linkInertia(0,0,0);
link->calculateLocalInertia(mass,linkInertia);
btRigidBody::btRigidBodyConstructionInfo link2RigidBodyCI(mass,linkMotionState,link,link2Inertia);
btRigidBody* linkRigidBody = new btRigidBody(linkRigidBodyCI);
btCollisionObject* linkCol = static_cast<btCollisionObject*>(linkRigidBody);
This represents a rod-like object that is 1 meter high and standing on one end on the ground. How can I create the same object but in such a way that it is inclined at a certain angle? In other words, if I have 2 points in space, how can I create a box-like rod that extends between then? I'm not sure what btQuaternion means exactly or how to make rotations in bullet, so I'd really appreciate any help you can give. Thanks a lot.
Regards,
Nick
Rotations of Objects
-
robagar
- Posts: 48
- Joined: Fri May 21, 2010 1:49 am
Re: Rotations of Objects
'fraid you're going to have to figure out quaternions
The Ogre wiki has a good non-mathematical introduction: http://www.ogre3d.org/wiki/index.php/Qu ... ion_Primer. The code is Ogre not Bullet, but the concepts are the same.
-
Flix
- Posts: 456
- Joined: Tue Dec 25, 2007 1:06 pm
Re: Rotations of Objects
The btQuaternion class has has a ctr that takes a btVector3 (the axis of rotation) and a btScalar (the amount of rotation).YAN3 wrote:[...] how to make rotations in bullet [...]
Now I don't remember exactly the order in which these two arguments appear in the ctr, but if you want for example your body to be rotated 60 degrees around the vertical (Y) axis you can use a transform like this:
Code: Select all
btTransform T(btQuaternion(btVector3(0,1,0),btRadians(60)),btVector3(0.0,0.5,0));-
YAN3
- Posts: 11
- Joined: Fri May 07, 2010 2:18 pm
Re: Rotations of Objects
@robagar: Thanks a lot, that was very helpful 
@Flix: Thanks for the help. I tried that and it seems to work. But it seems to me that the rotation takes place around the specified axis as if that axis were placed at the center of the object ((0.05,1.0,0.05) in our example). How can I rotate the object around a different point? For example, I want to rotate that box around the x-axis with an angle of 90 degrees, but about its base (0,0,0) so that it would be lying on the ground along the z-axis afterwards. Is that possible? Thanks a lot.
Best regards,
Nick
@Flix: Thanks for the help. I tried that and it seems to work. But it seems to me that the rotation takes place around the specified axis as if that axis were placed at the center of the object ((0.05,1.0,0.05) in our example). How can I rotate the object around a different point? For example, I want to rotate that box around the x-axis with an angle of 90 degrees, but about its base (0,0,0) so that it would be lying on the ground along the z-axis afterwards. Is that possible? Thanks a lot.
Best regards,
Nick
-
Flix
- Posts: 456
- Joined: Tue Dec 25, 2007 1:06 pm
Re: Rotations of Objects
Well, this is a much more complicated question! (and I suppose that shifting the center of mass of your body through a compound shape isn't an option...).YAN3 wrote:How can I rotate the object around a different point?
I believe It's possible to do it through multiplication of two other transforms, one placed at the center of rotation and the other at the position of your body, relative to the first one, (or through multiplication of their inner components: vector and basis), but unluckily I've got no "ready to use code" to share at the moment
Good luck!
-
Flix
- Posts: 456
- Joined: Tue Dec 25, 2007 1:06 pm
Re: Rotations of Objects
Some additional thing and ideas you can try (I didn't):
Basically you have an (old) transform for your body (let's call it T), and you must move it "inside" the space of your rotation transform (let's call it TR).
Now you must calculate the new value of T.
You can simply try: T(new) = TR * T(old).
It might work, but since I can't look at Bullet source code at the moment, I'd say (this is NOT correct cpp code):
T(new).origin = TR.origin + TR.basis * T(old).origin // But this is correct only if T(old).origin was set as the distance between TR and T(old) !
T(new).basis = TR.basis * T(old).basis
So, if T(old) is in the "absolute" space:
T(new).origin = TR.origin + TR.basis * (T(old).origin - TR.origin)
T(new).basis = TR.basis * T(old).basis
Could you try and see if it works?
(I bet it won't... doing things "on the fly" without trying it before is not very professional and not a good practice in a forum post; I'm sorry
)
Basically you have an (old) transform for your body (let's call it T), and you must move it "inside" the space of your rotation transform (let's call it TR).
Now you must calculate the new value of T.
You can simply try: T(new) = TR * T(old).
It might work, but since I can't look at Bullet source code at the moment, I'd say (this is NOT correct cpp code):
T(new).origin = TR.origin + TR.basis * T(old).origin // But this is correct only if T(old).origin was set as the distance between TR and T(old) !
T(new).basis = TR.basis * T(old).basis
So, if T(old) is in the "absolute" space:
T(new).origin = TR.origin + TR.basis * (T(old).origin - TR.origin)
T(new).basis = TR.basis * T(old).basis
Could you try and see if it works?
(I bet it won't... doing things "on the fly" without trying it before is not very professional and not a good practice in a forum post; I'm sorry
-
YAN3
- Posts: 11
- Joined: Fri May 07, 2010 2:18 pm
Re: Rotations of Objects
@Flix
Thank you so much for your advice and help. I'm sorry for the late reply, but I haven't been able to work on this for the past week. I will give it a try and get back to you
Regards,
Nick
Thank you so much for your advice and help. I'm sorry for the late reply, but I haven't been able to work on this for the past week. I will give it a try and get back to you
Regards,
Nick
-
Flix
- Posts: 456
- Joined: Tue Dec 25, 2007 1:06 pm
Re: Rotations of Objects
No problemYAN3 wrote:Thank you so much for your advice and help. I'm sorry for the late reply, but I haven't been able to work on this for the past week. I will give it a try and get back to you
I've finally written this piece of code that seems to work (although it should be further tested to be sure it's reliable).
The only problem is that it's not as intuitive as I wanted: in fact it takes the rotation in the global space (instead of local space).
In the code I've used for testing it, I've explained how to overcome this problem, but I still can't figure out how to integrate this
solution in my method.
Anyway, feel free to test it, use it, improve it, and so on...
Here is the code:
Code: Select all
SIMD_FORCE_INLINE static btTransform RotateGlobalSpace(const btTransform& T,const btMatrix3x3& rotationMatrixToApplyBeforeTGlobalSpace,const btVector3& centerOfRotationRelativeToTLocalSpace) {
// Note: - centerOfRotationRelativeToTLocalSpace = TRelativeToCenterOfRotationLocalSpace (LocalSpace is relative to the T.basis())
const btVector3 TRelativeToTheCenterOfRotationGlobalSpace = T.getBasis() * (-centerOfRotationRelativeToTLocalSpace); // Distance between the center of rotation and T in global space
const btVector3 centerOfRotationAbsolute = T.getOrigin() - TRelativeToTheCenterOfRotationGlobalSpace; // Absolute position of the center of rotation = Absolute position of T + PositionOfTheCenterOfRotationRelativeToT
return btTransform(rotationMatrixToApplyBeforeTGlobalSpace*T.getBasis(),centerOfRotationAbsolute + rotationMatrixToApplyBeforeTGlobalSpace * TRelativeToTheCenterOfRotationGlobalSpace);
}
SIMD_FORCE_INLINE static btTransform RotateGlobalSpace(const btTransform& T,const btQuaternion& rotationToApplyBeforeTGlobalSpace,const btVector3& centerOfRotationRelativeToTLocalSpace) {
return RotateGlobalSpace(T,btMatrix3x3(rotationToApplyBeforeTGlobalSpace),centerOfRotationRelativeToTLocalSpace);
}
#ifdef NOT_WORKING
SIMD_FORCE_INLINE static btTransform Rotate(const btTransform& T,const btMatrix3x3& rotationToApplyBeforeTLocalSpace,const btVector3& centerOfRotationRelativeToTLocalSpace) {
return RotateGlobalSpace(T,T.getBasis()*rotationToApplyBeforeTLocalSpace,centerOfRotationRelativeToTLocalSpace);
// This does not work, because:
/*
const btTransform T; [...] // SET IT WITH A Quaternion!=identity
const btQuaternion qLocalSpace(btVector3(0,1,0),btRadians(30));
const btQuaternion qGlobalSpace(T.getBasis() * btVector3(0,1,0),btRadians(30)); // Correct!
Now:
const btMatrix3x3 mLocalSpace(qLocalSpace);
const btMatrix3x3 mGlobalSpace(qGlobalSpace);
But I don't know how to derive a qGlobalSpace (or mGlobalSpace) from a qLocalSpace (or mLocalSpace) given T. For sure:
mGlobalSpace != T.getBasis() * mLocalSpace;
// Anyway you can use RotateGlobalSpace() for now with a global space quaternion calculated as above...
*/
}
SIMD_FORCE_INLINE static btTransform Rotate(const btTransform& T,const btQuaternion& rotationToApplyBeforeTLocalSpace,const btVector3& centerOfRotationRelativeToTLocalSpace) {
return Rotate(T,btMatrix3x3(rotationToApplyBeforeTLocalSpace),centerOfRotationRelativeToTLocalSpace);
}
#endif //NOT_WORKINGCode: Select all
//Testing Code
{
btCollisionShape* shape = new btBoxShape(btVector3(1,0.4f,1));
m_collisionShapes.push_back(shape);
btTransform transform;transform.setIdentity();transform.setOrigin(btVector3(0,2,0));transform.setRotation(btQuaternion(btVector3(0,1,0),btRadians(60)));
const btScalar mass(0.);
const bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic) shape->calculateLocalInertia(mass,localInertia);
btDefaultMotionState* myMotionState = new btDefaultMotionState(transform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
btWorld->addRigidBody(body);
// Ok, now we test our Rotate method
// We make the box rotate around its top/far edge (parallel to X axis):
btTransform T = transform;
//const btQuaternion rotationLocalSpace(btVector3(1,0,0),btRadians(-30)); // -30 degrees around (local) X axis
const btVector3 relativeCenterOfRotation(0,0.4f,-1); // This is in the local space (i.e. should work even if "transform" has a quatenion!=identity)
for (int i = 0; i < 6; i++) {
//--------------------------------------------------------------------------------
const btQuaternion rotationGlobalSpace(T.getBasis()* btVector3(1,0,0),btRadians(-30)); // -30 degrees around (local) X axis (depends on T, so it should be put inside the cycle in the general case)
T = btMathHelper::RotateGlobalSpace(T,rotationGlobalSpace,relativeCenterOfRotation);
//---------------------------------------------------------------------------------
//T = btMathHelper::Rotate(T,rotationLocalSpace,relativeCenterOfRotation);
//---------------------------------------------------------------------------------
myMotionState = new btDefaultMotionState(T);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia);
body = new btRigidBody(rbInfo);
btWorld->addRigidBody(body);
}
}You do not have the required permissions to view the files attached to this post.