Drawing a Model
Drawing models with XNA is a simple process.
But before you can draw it, you first need to load the model. To load a model, make sure you have added it to your Content pipeline by dragging the model and any of its resources (textures, etc.) into the Content directory in the solution explorer. There a few limitation about what you can load into your game, as that XNA itself only can load '.fbx' and '.x' files natively. There also can be problems with the size of your texture and your graphic card, but XNA will warn you if such problems occur.
Now that XNA knows which models, and assets, you need for the game, we can start to write the code for them. At start we declare the fields that the code will need later.
The Model class holds the whole model itself including informations about bones, BoundingSpheres for each individual mesh in the model, and all meshes the model is made of. As the Model class only holds the informations about the bones, we'll need a matrix to combine all meshes with each bone, and their transformations. This will be done by the matrix array transforms.
The view and projection matrices make up the virtual camera of your game. The view matrix is responsible for instructing the camera on where to be positioned and where to point, while the projection matrix is responsible for instructing the camera on what field of view to have, how close or far away objects can be and still be seen, and what aspect ratio to display in.
Add these variables to your game class:
// Declare a model Model model; // Create an array for the bone transforms Matrix[] transforms; // Declare the view and project matrices Matrix view, projection;
After we have created those fields, we need to give them a value. For this we will add a little code to the LoadContent() method, that was automatically created as you created your game project.
First the Model. We call the content pipeline with the field Content, to tell it then that we want to Load and Model. Now we can enter the asset name of your model. If you don't know what name to use, check the model's properties in the Property Window and look for "Asset Name". By default the asset name is the same as the file name but without the extension.
Next we'll extract the bone transforms from the model. Unlike the View and Projection, this has to happen after we load the model that way our model variable is not null.
Now lets tell the game where you're looking from. We create the view matrix using Matrix.LookAt. The first value is the position of the camera. The second value indicates what point in space the camera is looking at. The third value will tell the game where 'Up' is so that it has an easy way of orienting the camera.
Next we create our projection matrix. The first value is the field of view which tells the camera what angle of sight it has. This value needs to be in radians so if you are more comfortable with degrees, you can use the MathHelper.ToRadian method. The value must be between 0 and Pi (180 degrees). Next we have to specify the aspect ratio of the camera. This can be done easily by dividing the viewport's width by its height. Note you must cast these values to floats to avoid performing integer division. Third is the near plane. This specifies a minimum distance that an object must be from the camera to be seen. Last is the far plane. This specifies the maximum distance that an object can be to still be seen by the camera.
// Load the model
model = Content.Load<Model>("<Model Asset Name Here>");
// Copy any parent transforms.
transforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);
// Create the view and projection matrices. These act as your camera.
view = Matrix.CreateLookAt(new Vector3(0, 0, -100), Vector3.Zero, Vector3.Up);
projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.PiOver4,
(float)GraphicsDevice.Viewport.Width /
(float)GraphicsDevice.Viewport.Height,
1f,
1000f);To render a model, we have to loop through all of the meshes and draw them each individually. For each mesh we also must set some information on the mesh's effect(s) so that it knows what values we have chosen for the view and projection matrices, as well as lighting information and the bone transformations. After that's done, we simply call Draw on the mesh to render it to the screen.
Add this code to your Draw method:
// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in model.Meshes)
{
// This is where the mesh orientation is set, as well as our camera and projection.
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.World = transforms[mesh.ParentBone.Index];
effect.View = view;
effect.Projection = projection;
}
// Draw the mesh, using the effects set above.
mesh.Draw();
}