Nathan
Nathan

Reputation: 621

3D animation with bones and their matrices

I really am asking this as a last resort. I haven't been able to solve this for 2 days now. So if someone knows a thing or two about 3D, Matrices and animation I would really appreciate your input.

I have downloaded this project and implemented it into my own project: http://xbox.create.msdn.com/en-US/education/catalog/sample/skinned_model. The character in my game move his hands as he casts a spell. I have successfully made this animation and imported it into the project. But I need to spawn particles inside the palms of his hands which move according to an animation. All I need is the 3D position of the palms of his hands after the animation has been applied.

Picture of hands during the animation: http://s18.postimg.org/qkaipufa1/hands.png

If you take a look at the skinned model sample project: Class: AnimationPlayer.cs you will notice that it processes the matrices 3 times:

    public void Update(TimeSpan time, bool relativeToCurrentTime,
                       Matrix rootTransform)
    {
        UpdateBoneTransforms(time, relativeToCurrentTime);
        UpdateWorldTransforms(rootTransform);
        UpdateSkinTransforms();
    }

And allows us to access them after each of the steps:

        /// Gets the current bone transform matrices, relative to their parent bones.
    /// </summary>
    public Matrix[] GetBoneTransforms()
    {
        return boneTransforms;
    }


    /// <summary>
    /// Gets the current bone transform matrices, in absolute format.
    /// </summary>
    public Matrix[] GetWorldTransforms()
    {
        return worldTransforms;
    }


    /// <summary>
    /// Gets the current bone transform matrices,
    /// relative to the skinning bind pose.
    /// </summary>
    public Matrix[] GetSkinTransforms()
    {
        return skinTransforms;
    }

I should also mention that I know the index of the bone in the palm and the index of all its parents:

10 - 11's parent, Root bone

11 - 12's parent

12 - 13's parent

13 - 14's parent

14 - 15's parent

15 - 16's parent

16 - The bone in the palm

As far as I understand this project is that all of the GetXXXXXXXX Commands I listed above return an array of Matrix[] ordered according to the index of the bone. So to get the Transform of Bone 10. I believe the code will look like:

Matrix[] M = animtionplayer.GetSkinTransforms();
Matrix transform = M[10];

OK, now for the parts I don't understand. I don't know which of the 3 GetXXXXXXXXX functions I need to use to get the palms position.

I think the way the shaders calculate the position of the bones is by multiplying them by each of their parent bones. So:

Matrix[] M = animtionplayer.GetBoneTransforms();
Matrix transform = M[10];
transform = transform * M[11];
transform = transform * M[12];
transform = transform * M[13];
transform = transform * M[14];
transform = transform * M[15];
transform = transform * M[16];
//maybe apply the world position of the model? 
transform = transform * MyWorld;

And then maybe to get a vector3 position.

Vector3 HandPosition = transform.Up;

Well when I try the solution above I get mixed results. With certain bones it moves correctly for the middle section of the animation. But honestly nothing good. Can someone explain whats going on here? How do I get the position of the bone in the palm? I'm really in the dark here. I only learnt what a matrix was 2 months ago, and animation with bones only this week.

Upvotes: 3

Views: 1593

Answers (2)

Nathan
Nathan

Reputation: 621

Alright so this bug was quiet frustrating so I took a break from coding for about a week. I started working on it again 2 days ago. Trying many random things.... looking at the values of the matrices looking for patterns and I finally got it. Here is an image where the hands are animated and all the bones are highlighted perfectly with big white spheres. And it follows the animation perfectly too! http://s27.postimg.org/f48i7ae4x/2014_07_30_18_H14_M20_S.jpg

The code:

Matrix[] BoneTransforms = animtionPlayer.GetWorldTransforms();
for (int i = 0; i < BoneTransforms.Length; i++)
{
    Vector3 v3 = new Vector3(BoneTransforms[i].M41, BoneTransforms[i].M42, BoneTransforms[i].M43);
    v3 = Vector3.Transform(v3, GetWorld(Position, Rotation, Scale));//GetWorld is the models world matrix: position, rotation and scale.
    Game1.DrawMarker(v3); //v3 is the position of the current Bone.
}

I just made that code by watching all of the values of the specific Matrix. I learnt that M41, M42, M43 are the X, Y, Z cords from the specific bone.

Upvotes: 2

ThisHandleNotInUse
ThisHandleNotInUse

Reputation: 1153

Reopen your mesh designer, put an empty in his hands about where the particle effect should be, parent the empty to the "palm" bones and keep track of what direction in local coords the empty is facing so you can face the particles in the right direction, rebake the animation and reimport it. I will admit I'm not familiar with the "mesh skinner" you're using - but I would imagine it supports child objects of bones like empties as they're frequently employed for such purposes. You're overthinking this. If you can't do this with the X-box kit, I don't know.

A "transform matrix" isn't necessarily the location of the bone - so I'm confused about what these functions return. They probably just return the matrix it uses to calculate the position of the vertices which are weighted to those bones. There isn't a function to return the "world position" of a palm bone and simply track your animation to the world position of the empty or palm bone? I'm confused what you need to use the transform matrices for. If the library you're using is good, there will almost certainly be a way to get a bone's world coordinate in which case adding a "tracking bone" just outside the palm will let you track animations or objects to that bone or even directly parent them.

Upvotes: 0

Related Questions