# 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.

## 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
++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);

XMMATRIX TranslateMat=XMMatrixTranslation( finalJoint.pos.x, finalJoint.pos.y, finalJoint.pos.z );

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.

##### 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

1. 1
Rutin
46
2. 2
3. 3
4. 4
5. 5
JoeJ
19

• 13
• 10
• 12
• 10
• 13
• ### Forum Statistics

• Total Topics
632998
• Total Posts
3009808
• ### Who's Online (See full list)

There are no registered users currently online

×