Models, meshes, parts, and bones

Originally posted to Shawn Hargreaves Blog on MSDN, Monday, November 20, 2006


If you look inside the XNA framework Model class, you will see that it contains a Meshes property holding a collection of ModelMesh instances. If you look inside the ModelMesh class, you will see that each one contains a MeshParts property holding a collection of ModelMeshPart instances. Not to mention the Model.Bones property, which holds a collection of ModelBone instances. What is this all about?

In XNA, a Model can represent any kind of logical entity. It could be a person, or a car, or a level. If you were crazy you could even combine all the meshes for your entire game into a single Model instance! (not that I would recommend that…)

Within a Model, each ModelMesh represents a single physical object. Each ModelMesh can be moved independently, and some can be drawn while others are skipped. For instance a Model of a car would probably contain one ModelMesh for the body of the vehicle, four for the wheels, and a couple for the doors (assuming we are building a sexy sports coupe…)

Within a ModelMesh, each ModelMeshPart represents a single graphics card draw call. It contains a set of triangles that share the same material (stored in the ModelMeshPart.Effect property) and vertex declaration. For instance the ModelMesh for the body of our car might contain one ModelMeshPart for the painted car surface, one using an environment mapping effect for the reflective windscreen, and another using a normalmap texture for the snakeskin leather seats (I hasten to assure concerned readers that no snakes were harmed during the production of this blog post…)

The ModelBone objects describe how the ModelMesh instances are positioned. Each mesh has a ParentBone property, in which you can find a transform matrix describing where that ModelMesh is located relative to the Parent of the ParentBone. This allows you to build up hierarchies of jointed objects (wheel bone and door bone to car body bone, spinning windmill blades to windmill tower, thigh bone to knee bone…)

Putting this all together, we can draw some hopefully useful conclusions:

At this point the astute reader may be wondering what the ModelMesh.Effects property is all about. You thought I'd forgotten to explain that, didn't you? Not in the least…

The actual effect instances used to render your model are stored in the Effect property of the ModelMeshPart class. This is inevitable, really, since each ModelMeshPart can potentially have a different effect. If you want to change the effect used to render your model, you will need loop over each ModelMeshPart and assign a new value to their Effect property.

The ModelMesh.Effects property is just a shortcut that gives you a combined list of all the effects used on all the parts of the mesh. This allows you to draw an entire mesh using this code:

    Matrix[] transforms = new Matrix[model.Bones.Count];

    Model.CopyAbsoluteBoneTransformsTo(transforms);

    foreach (ModelMesh mesh in model.Meshes)
    {
        foreach (BasicEffect effect in mesh.Effects)
        {
            effect.World = transforms[mesh.ParentBone.Index];
            effect.View = viewMatrix;
            effect.Projection = projectionMatrix;
        }

        mesh.Draw();
    }

This is really just a shortcut for:

    Matrix[] transforms = new Matrix[model.Bones.Count];

    Model.CopyAbsoluteBoneTransformsTo(transforms);

    foreach (ModelMesh mesh in model.Meshes)
    {
        foreach (ModelMeshPart part in mesh.MeshParts)
        {
            if (part.Effect == null)
                throw new IneffectiveException("Huh?");

            BasicEffect effect = (BasicEffect)part.Effect;

            effect.World = transforms[mesh.ParentBone.Index];
            effect.View = viewMatrix;
            effect.Projection = projectionMatrix;
        }

        mesh.Draw();
    }

But the first version is better because:


Blog index   -   Back to my homepage