Sign in to follow this  
stefan5000

MD5 Anim -- problem computing baseframe quaternion

Recommended Posts

Hi everyone, I'm currently trying to add md5 model support to my engine. Till now I'm able to draw the mesh correctly. But now, when it goes on to compute the baseframe joints, I'm running in problems. Therefore I decided to rethink the math behind it and to stop working around with the code. I've now created an Excel/Open Office TableDoc (if anyone want's to take a look at it (I hope so) , please tell me!), wherein I can easily can change things. My model is the Doom3's main characters head, which I've animated using MAX. The baseframe is the same as the pose in the MD5Mesh file. So I can easily compare my computed values to the ones in the mesh file. Here some example: md5mesh:
...
( 0 0 0 ) ( -0.4999999404 -0.5000000596 -0.5000000596 )
( 15.967792511 -0.0144653134 10.7254972458 ) ( -0.4999999404 -0.5000000596 -0.5000000596 )
( 15.9677934647 1.3034828901 10.7254972458 ) ( -0.4999999404 -0.5000000596 -0.5000000596 )
...

md5anim (baseframe)
...
( 0.0 0.0 0.0 ) ( -0.5 -0.5 -0.5 )
( -0.0144691 10.7255 15.9678 ) ( 0.0 0.000119209 0.0 )
( 1.31795 0.0 0.000953674 ) ( -0.707107 0.0 -0.707107 )
...

and my computed values:
...
( 0.0 0.0 0.0 ) ( -0.5 -0.5 -0.5 )
( 15.9678 -0.0144691 10.7255 ) ( -0.499940392 -0.500059601 -0.500059601 )
( 15.968439451 1.303481090 10.7255 ) ( 0.707106995 0.000084294 -0.000084294 )
...

Well, I don't want to post all my way of computing here, but if anyone would like it, I could do that. But I hope you decide to take a look at my Excel/Open Office TableDoc. thanks for any help! cu

Share this post


Link to post
Share on other sites
Okay guys,

I decided to do a little bit of work and set up a pseudo-code for you!


for(int index = 0; index < NumJoints; index++)
{
float temp; // just for computing the w-component of quats

Joint thisJoint;
if(BaseFrameJointList[index].ParentIndex == -1)
{
thisJoint.Position = BaseFrameJointList[index].Position;
thisJoint.Orientation = BaseFrameJointList[index].Orientation;
temp = (1.0f - (thisJoint.Orientation.x*thisJoint.Orientation.x) - (thisJoint.Orientation.y*thisJoint.Orientation.y) - (thisJoint.Orientation.z*thisJoint.Orientation.z));
if(temp < 0.0f)
{
thisJoint.Orientation.w = 0.0f;
}
else
{
thisJoint.Orientation.w = sqrt(temp);
// no minus here, because I found out,
//that the POSITION values are mixed otherwise
// *.z would become *.x
// *.x would become *.y
// *.y would become *.z
}
}
else
{
// Just using floats here for testing (--> so, no 'real' matrix)
float m11, m12, m13,
m21, m22, m23,
m31, m32, m33;

// ParentQuat
Quat ParentQuat;
ParentQuat.x = BaseFrameJointList[BaseFrameJointList[index].ParentIndex].Orientation.x;
ParentQuat.y = BaseFrameJointList[BaseFrameJointList[index].ParentIndex].Orientation.y;
ParentQuat.z = BaseFrameJointList[BaseFrameJointList[index].ParentIndex].Orientation.z;

temp = (1.0f - (ParentQuat.x*ParentQuat.x) - (ParentQuat.y*ParentQuat.y) - (ParentQuat.z*ParentQuat.z));
if(temp < 0.0f)
{
ParentQuat.w = 0.0f;
}
else
{
ParentQuat.w = sqrt(temp);
// no minus here, because I found out,
//that the POSITION values are mixed otherwise
// *.z would become *.x
// *.x would become *.y
// *.y would become *.z
}

// Now creating the rotation matrix
// m11 = 1 - 2y^2 - 2z^2
m11 = 1 - (2*ParentQuat.y*ParentQuat.y) - (2*ParentQuat.z*ParentQuat.z);
// m12 = 2xy - 2wz
m12 = (2*ParentQuat.x*ParentQuat.y) - (2*ParentQuat.w*ParentQuat.z));
// m13 = 2xz + 2wy
m13 = (2*ParentQuat.x*ParentQuat.z) + (2*ParentQuat.w*ParentQuat.y));
// m21 = 2xy + 2wz
m21 = (2*ParentQuat.x*ParentQuat.y) + (2*ParentQuat.w*ParentQuat.z));
// m22 = 1 - 2x^2 - 2z^2
m22 = 1 - (2*ParentQuat.x*ParentQuat.x) - (2*ParentQuat.z*ParentQuat.z));
// m23 = 2yz - 2wx
m23 = (2*ParentQuat.y*ParentQuat.z) - (2*ParentQuat.w*ParentQuat.x));
// m31 = 2xz - 2wy
m31 = (2*ParentQuat.x*ParentQuat.z) - (2*ParentQuat.w*ParentQuat.y));
// m32 = 2yz + 2wx
m32 = (2*ParentQuat.y*ParentQuat.z) + (2*ParentQuat.w*ParentQuat.x));
// m33 = 1 - 2x^2 - 2y^2
m33 = 1 - (2*ParentQuat.x*ParentQuat.x) - (2*ParentQuat.y*ParentQuat.y));

// this Joint Position
D3DXVECTOR3 tempPos = BaseFrameJointList[index].Position;
thisJoint.Position[0] = (tempPos[0]*m11 + tempPos[1]*m21 + tempPos[2]*m31) + AnimJointList[thisJoint.ParentIndex].Position[0];
thisJoint.Position[1] = (tempPos[0]*m12 + tempPos[1]*m22 + tempPos[2]*m32) + AnimJointList[thisJoint.ParentIndex].Position[1];
thisJoint.Position[2] = (tempPos[0]*m13 + tempPos[1]*m23 + tempPos[2]*m33) + AnimJointList[thisJoint.ParentIndex].Position[2];

// Compute Quaternion (Maybe the problem is somewhere in here)

// First of all: Invert the baseframes quaternion (otherwise the computed quat is wrong (I compared it to the mesh quaternion)
Quat tempQuat;
tempQuat.x = -BaseFrameJointList[index].Orientation.x;
tempQuat.y = -BaseFrameJointList[index].Orientation.y;
tempQuat.z = -BaseFrameJointList[index].Orientation.z;

temp = (1.0f - (tempQuat.x*tempQuat.x) - (tempQuat.y*tempQuat.y) - (tempQuat.z*tempQuat.z));
if(temp < 0.0f)
{
tempQuat.w = 0.0f;
}
else
{
tempQuat.w = sqrt(temp);
// no minus here, because I found out,
//that the ORIENTATION values are mixed otherwise
// *.z would become *.x
// *.x would become *.y
// *.y would become *.z
}

D3DXQuaternionMultiply(&thisJoint.Orientation,
&tempQuat,
&AnimJointList[thisJoint.ParentIndex].Orientation);

AnimJointList[index] = thisJoint;
}
}



hope that helps you helping me! :)

Share this post


Link to post
Share on other sites
I can't help you atm (quat skills not that good) but when i wrote my MD5 lib, this site helped me out a lot. This guy first has a short rundown of the major issues in the MD5Model/MD5Anim formats, and then he even provide you with source code.
I also found this thread to be helpful when you're up against computing weighted normals...
Hope you get it to work! =)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this