btTransform::getRotation() and btTransform::getBasis()

MOD666
Posts: 2
Joined: Fri Oct 29, 2010 12:59 am

btTransform::getRotation() and btTransform::getBasis()

Post by MOD666 »

Given I'm rather new to 3D-game-programming it might be I'm just missing something, but when building a simple test-platformer using Ogre for graphics I got confused with the direction btTransform::getRotation() is transforming spaces from/to.

The character-example in bullet uses btTransform::getBasis() to get the forward-direction for moving (yet it's not obvious if using rows or cols from the matrix is the right thing to do and if the example does what it should).

The Ogre MotionState example uses btTransform::getRotation() to get a quaternion that is directly used for Ogre::SceneNode::setOrientation.

Now my problem was that my character-model was turning in another direction than the one the character would walk in. My first guess was that Ogre uses the Quaternion to transform local coordinates to world coordinates while it's the opposite direction in Bullet. While using getRotation().inverse() to set model-orientation solves the facing-problem, it breaks pretty much everything else. So I'd guess Bullet does use the btTransform-objects to project from local space to world space as well. Still the getBasis()-method as used in the Character-Example gives me what I'd get by applying getRotation().inverse() to the basis vectors. Building a basis by quatRotating the three basis-vectors with the getRotation()-quaternion worked for me, but I'd still like to know what the right way is to handle this.
Coderro
Posts: 7
Joined: Fri Jan 21, 2011 4:25 am

Re: btTransform::getRotation() and btTransform::getBasis()

Post by Coderro »

Are you certain that your character model was built to face the direction you had meant it to face? My game uses +Y for forward and Blender expects -Y for forward, so it's happened to me.
MOD666
Posts: 2
Joined: Fri Oct 29, 2010 12:59 am

Re: btTransform::getRotation() and btTransform::getBasis()

Post by MOD666 »

While there's always the chance I'm implicitly forcing a left-hand-coordinate-system on the system without noticing, I really doubt I do it (and I'm not even sure the effect of doing that would be the same). I'm also not doing any modifications to the quaternion I get from btTransform::getRotation() and pass on to Ogre::SceneNode::setOrientation(). I'm moving the model along the axis I get from either picking btTransform::getBasis()[] or from transforming the basis according to btTransform::getRotation() (by now I'd know better there). As a side-note: I'm using Y as up-vector just as Ogre does it. The problem I'm having is also not an additive 180°-rotation of the model, but that if the movement axis (as retrieved from getBasis() in the CharacterDemo) is rotated clockwise, the visual representation of the object rotates counterclockwise.

But I'll reduce the question to something with less variables. Here is a code-example that only uses bullet-structures.

Code: Select all

btTransform transform(btQuaternion(btVector3(0,0,1),PI/2));
btVector3 fromGetBasis=transform.getBasis()[0]; // as in the Character-example I use [0] here which equals to .getRow(0)
btVector3 fromGetRotation=quatRotate(transform.getRotation(), btVector3(1,0,0));
//since the matrix from getBasis() is orthogonal that's the same as picking row 0 from the inverse matrix:
btVector3 fromGetBasisAlt=transform.getBasis().getColumn(0);
//Results coming in:
std::cout<<std::fixed; //quatRotate does give you a small nonzero-value for x
std::cout<<"getBasis:        "<<fromGetBasis[0]<<"/"<<fromGetBasis[1]<<"/"<<fromGetBasis[2]<<std::endl;
std::cout<<"getRotation:     "<<fromGetRotation[0]<<"/"<<fromGetRotation[1]<<"/"<<fromGetRotation[2]<<std::endl;
std::cout<<"getBasis.Column: "<<fromGetBasisAlt[0]<<"/"<<fromGetBasisAlt[1]<<"/"<<fromGetBasisAlt[2]<<std::endl;
The result would be:

Code: Select all

getBasis:        0.000000/-1.000000/0.000000
getRotation:     -0.000000/1.000000/0.000000
getBasis.Column: 0.000000/1.000000/0.000000
So if Ogre applies the quaternion it receives to translate local offset to global offset for points, the x-axis of the model will obviously point in another direction than getBasis()[0]. Now the question: do I want transform.getBasis()[0] to be the 'strafing direction'-Vector in the CharacterDemo or should rather transform.getBasis().getColumn(0) be used? Side note: While looking for the code I've used as reference I noticed the btRaycastVehicle-source seems to actually use columns.