How can I attach a model to the bone of another model?

Posted by kaykayman on Game Development See other posts from Game Development or by kaykayman
Published on 2012-11-26T23:42:06Z Indexed on 2012/11/27 5:31 UTC
Read the original article Hit count: 323

Filed under:
|
|
|

I am trying to attach one animated model to one of the bones of another animated model in an XNA game.

I've found a few questions/forum posts/articles online which explain how to attach a weapon model to the bone of another model (which is analogous to what I'm trying to achieve), but they don't seem to work for me.

So as an example: I want to attach Model A to a specific bone in Model B.

Question 1. As I understand it, I need to calculate the transforms which are applied to the bone on Model B and apply these same transforms to every bone in Model A. Is this right?

Question 2. This is my code for calculating the Transforms on a specific bone.

private Matrix GetTransformPaths(ModelBone bone)
{
    Matrix result = Matrix.Identity;
    while (bone != null)
    {
        result = result * bone.Transform;
        bone = bone.Parent;
    }
    return result;
}

The maths of Matrices is almost entirely lost on me, but my understanding is that the above will work its way up the bone structure to the root bone and my end result will be the transform of the original bone relative to the model.

Is this right?

Question 3. Assuming that this is correct I then expect that I should either apply this to each bone in Model A, or in my Draw() method:

private void DrawModel(SceneModel model, GameTime gametime)
{
    foreach (var component in model.Components)
    {
        Matrix[] transforms = new Matrix[component.Model.Bones.Count];
        component.Model.CopyAbsoluteBoneTransformsTo(transforms);

        Matrix parenttransform = Matrix.Identity;
        if (!string.IsNullOrEmpty(component.ParentBone))
            parenttransform = GetTransformPaths(model.GetBone(component.ParentBone));


        component.Player.Update(gametime.ElapsedGameTime, true, Matrix.Identity);

        Matrix[] bones = component.Player.GetSkinTransforms();

        foreach (SkinnedEffect effect in mesh.Effects)
        {
            effect.SetBoneTransforms(bones);                  

            effect.EnableDefaultLighting();
            effect.World = transforms[mesh.ParentBone.Index]
                * Matrix.CreateRotationY(MathHelper.ToRadians(model.Angle))
                * Matrix.CreateTranslation(model.Position)
                * parenttransform;
            effect.View = getView();
            effect.Projection = getProjection();
            effect.Alpha = model.Opacity;
        }
    }
    mesh.Draw();
}

I feel as though I have tried every conceivable way of incorporating the parenttransform value into the draw method. The above is my most recent attempt. Is what I'm trying to do correct? And if so, is there a reason it doesn't work?

The above Draw method seems to transpose the models x/z position - but even at these wrong positions, they do not account for the animation of Model B at all.

Note: As will be evident from the code my "model" is comprised of a list of "components". It is these "components" that correspond to a single "Microsoft.Xna.Framework.Graphics.Model"

© Game Development or respective owner

Related posts about XNA

Related posts about matrix