Problem When Skinning MD5Model

Started by
1 comment, last by whdi0404 9 years, 4 months ago

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
++iter;
}

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));
		XMStoreFloat4(&finalJoint.orientation,joint0Orient);

		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.

http://www.dropbox.com/s/5y6vgwf4wxlz6ai/dx11.jpg?dl=0

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.

http://www.dropbox.com/s/rbplbhhzumj3u0s/opengl.jpg?dl=0

this is the correct result.

Advertisement

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.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

thank you for your advice.

This topic is closed to new replies.

Advertisement