Jump to content
  • Advertisement
Sign in to follow this  

OpenGL Problem When Skinning MD5Model

This topic is 1415 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Save the inversebindposeMatrix After load a file 

while ( iter != MD5Model.joints.end() )
const Joint& joint = (*iter);
XMMATRIX boneRotate = XMMatrixRotationQuaternion( XMLoadFloat4(&joint.orientation) );
XMMATRIX boneTranslate = XMMatrixTranslationFromVector( XMLoadFloat3(&joint.pos) );

XMMATRIX boneMatrix = XMMatrixMultiply(boneRotate, boneTranslate);

XMMATRIX inverseBoneMatrix = XMMatrixInverse(&XMVectorSet(0,0,0,0),boneMatrix );
MD5Model.bindPoseMat.push_back( inverseBoneMatrix );//Save inversebindposeMatrices

and Calculate each InterpolatedBoneMatrix with inversebindposeMatrix

void ModelMD5::UpdateMD5Model(float deltaTime, int animation)
	animations[animation].currAnimTime += deltaTime;			// Update the current animation time

	if(animations[animation].currAnimTime > animations[animation].totalAnimTime)
		animations[animation].currAnimTime = 0.0f;

	// Which frame are we on
	float currentFrame = animations[animation].currAnimTime * animations[animation].frameRate;	
	int frame0 = floorf( currentFrame );
	int frame1 = frame0 + 1;

	// Make sure we don't go over the number of frames	
	if(frame0 == animations[animation].numFrames-1)
		frame1 = 0;

	float interpolation = currentFrame - frame0;	// Get the remainder (in time) between frame0 and frame1 to use as interpolation factor

	//std::vector<Joint> interpolatedSkeleton;		// Create a frame skeleton to store the interpolated skeletons in

	// Compute the interpolated skeleton
	for( int i = 0; i < animations[animation].numJoints; i++) // numJoints = 31;
		XMMATRIX finalMatrix=XMMatrixIdentity();
		Joint finalJoint = animationskeleton.vector_joint[i];

		Joint joint0 = animations[animation].frameSkeleton[frame0].vector_joint[i];		// Get the i'th joint of frame0's skeleton
		Joint joint1 = animations[animation].frameSkeleton[frame1].vector_joint[i];		// Get the i'th joint of frame1's skeleton
		finalJoint.parentID = joint0.parentID;											// Set the tempJoints parent id

		// Turn the two quaternions into XMVECTORs for easy computations
		XMVECTOR joint0Orient = XMVectorSet(joint0.orientation.x, joint0.orientation.y, joint0.orientation.z, joint0.orientation.w);
		XMVECTOR joint1Orient = XMVectorSet(joint1.orientation.x, joint1.orientation.y, joint1.orientation.z, joint1.orientation.w);

		// Interpolate positions
		finalJoint.pos.x = joint0.pos.x + (interpolation * (joint1.pos.x - joint0.pos.x));
		finalJoint.pos.y = joint0.pos.y + (interpolation * (joint1.pos.y - joint0.pos.y));
		finalJoint.pos.z = joint0.pos.z + (interpolation * (joint1.pos.z - joint0.pos.z));

		// Interpolate orientations using spherical interpolation (Slerp)
		XMStoreFloat4(&finalJoint.orientation, XMQuaternionSlerp(joint0Orient, joint1Orient, interpolation));

		finalMatrix = XMMatrixMultiply(XMMatrixRotationQuaternion(XMLoadFloat4(&finalJoint.orientation)),XMMatrixTranslation(finalJoint.pos.x,finalJoint.pos.y, finalJoint.pos.z ));
		XMMATRIX TranslateMat=XMMatrixTranslation( finalJoint.pos.x, finalJoint.pos.y, finalJoint.pos.z );
		XMMATRIX RotateMat=XMMatrixRotationQuaternion(XMLoadFloat4(&finalJoint.orientation));

		finalAnimMatrix[i] = XMMatrixMultiply(bindPoseMat[i],finalMatrix);

and Skinning with this Matrices.




The general movement of the mesh is correct but some vertices move with an strange direction / orientation which forces a lot of clipping to occur.





this is the correct result.

Share this post

Link to post
Share on other sites

The problem isn't obvious from the images, and may be in any of a number of areas, and you may have more than one error. You'll have to do something other than stare at code to, at a minimum, determine a small section of code where an error is occurring. You may want to look through this journal entry. In addition, you might want to read through this article to determine if you're doing the necessary steps and doing them correctly.


Some questions for you to answer:


1. Have you tried your code with a much simpler model, such as just 2 cubes and 2 bones with a trivial animation?

2. Have you loaded the bind pose data correctly?

3. Have you loaded the animation data correctly?

4. It appears you have a demo which renders it correctly. Have you compared the joint orientation/translation data, the inverse bind pose matrices and final matrices with the demo?

5. Is your shader behaving correctly? I.e., if you set all final matrices to the identity matrix, does the model appear in bind pose?

6. Are the bone indices and bone weights correct for each vertex?


The code you posted above looks generally correct. However, it's not clear that you're calculating the inverse bind pose matrix correctly. Only you know what your "Joint" structure is, and how you load data into it. But it appears you're calculating the inverse of the bone's local ("to-parent") pose matrix, before you've combined that local matrix with the parent local matrix, the parent-parent's local matrix, etc.


In the section of the linked skinned mesh article "Back Into Initialization - The Offset Matrix," look at the information leading up to the definition below of the offset matrix (I believe you're calling that "inverse bind pose matrix"). Ensure that your process results in a matrix as described.


offsetMatrix = MeshFrame.ToRoot * Inverse( bone.ToParent * parent.ToParent * ... * root.ToParent );

Another relatively quick test you can make: pick a time in the animation where the animated pose is close to the bind pose. Multiply a bone's inversebindpose matrix with it's animation matrix at that time in the animation. The result of that multiplication should be "close" to an identity matrix. If it isn't, then either the offset matrix is incorrect, the animation matrix is incorrect, or both.

Edited by Buckeye

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!