Jump to content
  • Advertisement
Sign in to follow this  
Leks

OpenGL .x file skinning problem

This topic is 1133 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

Well, i read lots of articles and codes for the skinning (and animation) of .x file.

 

But i still can't make it right

 

Let me show some information i have learned first.( Please tell if i am wrong )

 

(1) Let's forget the animation now, only skinning

 

There're 3 key datas: 

1. FrameTransformMatrix (bones and other Frames)

2. BoneOffsetMatrix 

3. Vertex Positions, bone indices, weights

 

(2) The formulas for calculating ( OpenGL order ):

 

1. BoneCombinedTransformMatrix = RootFrameTransformMatrix * ... * ParentBoneTransformMatrix * CurrentBoneTransformMatrix

 

My file data looks like this:

[attachment=29058:hierarchy.png]

 

2. SkinnedPosition = BoneCombinedTransformMatrix * BoneOffsetMatrix * VertexPosition 

 

Then i get the "Rest Pose" model skinned right

[attachment=29059:cat_rest.png]

 

OK, everything seems good yet.

But when i export the .x file in "Bind Pose", the problem comes out

 

In Blender, the "Bind Pose":

[attachment=29060:cat_bind_pose_blender.png]

 

In my app, becomes...

[attachment=29061:cat_bind_pose.png]

 

Well, i thought it must be the exporter's bug, so i load it in a .x MeshViewer, it's perfect...

 

So i tried to figure out the relations between all these datas, but my math is bad.. 

 

i analyze the structure in blender:

[attachment=29064:struct.png]

 

after i done lots of matrix calculations, then i have this...

[attachment=29062:bad_1.png]

 

and this...

[attachment=29063:bad_2.png]

 

and so on...

 

i also picked one animation data to multiply with, but it just going more crazy...

 

Is that something missing in the formula?

I read others code, but still can't find the key point, they seems just use the formulas above...

 

please help~~thanks~

 

 

Share this post


Link to post
Share on other sites
Advertisement

I wrote my own animation exporter in blender for my engine.  One thing that blows it up, is if there is any rotation applied to the mesh or the armature. Make sure those both have no rotation before digging in. If it has rotation, you unparent the mesh to the armature, you can use something like tools->Apply Scale and Rotation.

 

Until this equation here equal the identity matrix for all bones, then obviously you need to debug it. Bolded part should be wrong. I'll have to look later but I believe you need to apply the root bone or the inverse root bone transform, BEFORE you apply the currentBone transform.

BoneCombinedTransformMatrix = RootFrameTransformMatrix * ... * ParentBoneTransformMatrix * CurrentBoneTransformMatrix

Share this post


Link to post
Share on other sites
thank you dpadam450. i follow your idea Apply Scale and Rotation for meshes, then the meshes and animations mess up... Even if it could work, i may not be able to modify every models in this way. The directx sdk works well with it, maybe we just need a little more calculation? Or can you give a little information about your exporter?

Share this post


Link to post
Share on other sites

The best piece of advice I can give you is to simplify the example you are using. 

 

Create a Model with just two or three bones, maybe just two cylinders that are connected at a right angle.

 

This way you can more easily debug the information.

Share this post


Link to post
Share on other sites

Your issue may be that you are not in openGL coordinates, or not applying the keyframe animation by the inverse bind pose.

Animation is always buggy to figure out at first.

This is the line of code I use to compute my final matrix for a given frame at load time.

1.) I store position and rotation separate. I don't remember why.

2.) .x will be in Blender coordinates which are DirectX coordinates, not OpenGL

 

My Blender (DirectX) to openGL matrix is this, and the inverse of this is just simply the Transpose (look up matrix transpose if you don't know what it is, its simple).

[1  ,  0,  0,  0]
[0  ,  0,  1,   0]
[0 , -1,  0,  0]
[0,  0, 0,  0]
 

*(bone->Animation_Frames[j]) = frame_translate*bind_pose_translate*inv_to_GL*(*bone->Animation_Frames[j])*inv_Bind_Pose*to_GL*inv_translate;

 

So I translate to bone to the origin 0,0,0 by applying the inverse of the bones bind pose position, I apply the to openGL matrix, so that all the next stuff applied will be in openGL coordinates from here on.  Then I take the inverse of the bind pose (again just the transpose of the rotation  no position). This is applied because the animation frames are in bone space, not global space, so they must be applied relative to the bone. So I have to apply the current animatino frame relative to the original bind pose. Next the animation frame is multiplied. Then I apply the inverse to openGL because the next 2 final matrices for translation are in openGL space. I export positions already in openGL space that is why I do that. I then apply "bind_pose_translate" which now takes that rotated bone right back to where it lives at the bind pose. Finally if the bone has moved this frame I apply the frame translation for the bone.

I believe the position and rotation separation was due to simplicity and debugging. Eventually you will find something that works. But this is what I did.

 

NOTE:  the final computed matrix for the bind pose, should be the identity matrix for all bones. To test this, animation_Frame* inverse_bind_pose should be the identity matrix. And why?...... because the matrix for the bind pose, and an animation frame that is literally the bind pose, means those 2 matrices are identical, and multiplying a matrix by its inverse, is the Identity matrix. IE input vertices did not move.

I'm in and out on here anymore so you can PM me but that is about it. Make sure you get the identity and you should be fine.
 

Edited by dpadam450

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!