# MD5 Anim -- problem computing baseframe quaternion

## Recommended Posts

stefan5000    122
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 on other sites
stefan5000    122
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 on other sites
Android_s    164
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! =)