In the previous tutorials, we’ve learned how to draw primitives and 2D textures. It’s time we step up to drawing a 3D model. To start with this tutorial you’ll need the following source code. It’s just an empty project containing our heads up display. Our 3D model is also located in the content folder. When you click on the forklift.fbx file, notice that it uses the Autodesk FBX – XNA Framework importer and Model – XNA Framework processor.
Forklift.fbx is a 3d model which has been exported from 3D Studio Max. You can find screenshots of the model and the export below.
So let’s get started! Add a class to your project and call it Forklift.cs. Then adjust the class so it inherits from DrawableGameComponent. This makes sure that our LoadGraphicsContent, Update and Draw method will be called automatically. When you’re writing a full game, you’ll probably write your own component based system, but for this tutorial, DrawableGameComponent will do just fine.
public class Forklift : DrawableGameComponent
Then we’ll add 3 variables to our class. The first containing the content manager, which will load our content. The second a variable which will contain our model, and last but not least, a variable which will contain the bone transforms of our model (the transform of each bone relative to the parent bone).
// A variable containing our content manager
private ContentManager _content;
// Our model
private Model _model;
// Array holding all the bone transform matrices for the entire model.
// We could just allocate this locally inside the Draw method, but it
// is more efficient to reuse a single array, as this avoids creating
// unnecessary garbage.
Then add the following constructor, where we’ll pass the Game class to the base class and save a reference to our content manager:
public Forklift(Game game, ContentManager content)
_content = content;
Now there are 2 things we have to do left: load the model and draw it. We’ll load the model in the LoadGraphicsContent method.
protected override void LoadGraphicsContent(bool loadAllContent)
_model = _content.Load
// Allocate the transform matrix array.
_boneTransforms = new Matrix[_model.Bones.Count];
//rotate the model 90 degrees
_model.Root.Transform *= Matrix.CreateRotationY(MathHelper.ToRadians(90));
In the first line, we load our model using the content manager and store it in de _model variable. In the second line we make an instance of our _boneTransforms matrix, and give it the number of bones in the model as size. In the third line, I’m just rotating the model 90 degrees, so we’ll see it from the side instead of from the front. The last line is just there so we’d see the model better .
That’s it! Our model is loaded, now let’s draw it.
Drawing the model will of course be done in the Draw method. First we’ll copy our absolute bone transforms to our _boneTransforms matrix. Then we’ll loop over all the model’s meshes, and draw them using their effects. An effect is a shader, which tells your graphics card how to draw stuff. Everything in XNA has to be drawn using shaders. We’ll pass the world, view and projection to this shader, and enable default lighting, so our model is lit properly. More on world, view and projection in our camera tutorial.
public override void Draw(GameTime gameTime)
// Draw the model.
foreach (ModelMesh mesh in _model.Meshes)
foreach (BasicEffect effect in mesh.Effects)
effect.World = _boneTransforms[mesh.ParentBone.Index];
effect.View = Matrix.CreateLookAt(new Vector3(1000, 500, 0),
new Vector3(0, 150, 0),
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
GraphicsDevice.Viewport.Width / GraphicsDevice.Viewport.Height,
If you want to know why exactly you have to draw a model like this, check out this post on Shawn Hargreaves Blog.
That’s it! When you run the project, you should see the image shown below.
As usual, you can download the complete source code.
In the next tutorials, we’ll animate the model and put in a camera.