Using 3D Models

Introduction

In previous tutorials, we've talked about where to get 3D models from or how to make your own. This tutorial will look at how to use a 3D model in your game. This tutorial will cover the basics, but in future tutorials, we will look at a few more advanced features of drawing in 3D and working with models.

Loading the Model

The first thing we need to do is acquire a 3D model to place in our game. There's a good chance that you've already got something that you want to put in your game, but if not, you can go over to my 3D Model Library and grab one. I will use the SimpleShip model for this tutorial, but you are more than welcome to use one of your own.

Take your model and all associated textures and add them to the content of your project. See the tutorial on managing content if you don't remember how to do this.

The next step is actually to load the model into our game. This is pretty easy to do. We will first create a variable to store the model. MonoGame has a type already created specifically for this called the Model class. So go to the beginning of your class where your other instance variables are (with the template, you should already have one called graphics, and one called spriteBatch), and add the following line of code:

private Model model;

Now, we need to load our model into this object. Go down to the LoadContent() method, and add the following line of code (replace "Ship" with the name of your model if you are using a different model):

model = Content.Load<Model>("Ship");

Your model will now be ready for use!

Drawing the Model

We are now ready to draw our model. It is at this point that we will use the stuff we talked about in the previous tutorial, which discussed Basic Matrices. If you haven't been through that tutorial, I would recommend going back to them now, but I've made the tutorial so that if you want to continue without it, you can still do that. In order to draw, we will need to define the three standard matrices. So go back up to your instance variables section and add the following code:

private Matrix world = Matrix.CreateTranslation(new Vector3(0, 0, 0));
private Matrix view = Matrix.CreateLookAt(new Vector3(0, 0, 10), new Vector3(0, 0, 0), -Vector3.UnitY);
private Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 800f / 480f, 0.1f, 100f);

Why these specific matrices? Remember what we learned in the tutorial on basic matrices.

The world matrix tells us how to transform points defined in the model to their locations in the world. Strictly speaking, this one creates an identity matrix, placing the points right around the origin.

The view matrix decides how the camera is oriented. The first argument is where the camera is located. This location puts the camera 10 units above the origin (along the z-axis). The second argument indicates that the camera looks at the origin (<0, 0, 0>), where we draw the model. These first two values make it so we'll be looking down on the model from above. The last argument indicates that we want "up" for the camera to be pointed along the negative y-axis, which ensures that, from the perspective of the camera, the ship will be pointed toward the top of the screen.

The projection matrix establishes what the "inner workings" of the camera are like. This one has a field of view of 45 degrees, computes the aspect ratio from the default window size in MonoGame (800 by 480), and has a near clipping plane at 0.1 and a far clipping plane at 100.

These values were all chosen to create a useful picture of our 3D model. If you use a different model, you may need to place the camera closer or farther away, or tweak the clipping plane distances, and change the camera's location, target, and up vector.

With these created, we have everything we need to draw. To make things easy for us, let's go down just below the Draw() method and create a new method that will draw a single model with given matrices. We can do this by adding the following code to our program:

private void DrawModel(Model model, Matrix world, Matrix view, Matrix projection)
{
    foreach (ModelMesh mesh in model.Meshes)
    {
        foreach (BasicEffect effect in mesh.Effects)
        {
            effect.World = world;
            effect.View = view;
            effect.Projection = projection;
        }
 
        mesh.Draw();
    }
}

This code shouldn't be too difficult to understand. All it does is go through each of the model's meshes (a model can be made up of multiple objects, which are called meshes), and it goes through each of the effects and sets the effect's matrices to be the matrices we want. We will talk about effects a lot more later. For now, it is enough for you to know that an effect determines how a model will be displayed on the screen. Finally, we tell each mesh of the model to be drawn, and we're done.

All we need to do now is call this method with the appropriate values, and we will see our model appear on the screen. So add the following line of code to your Draw() method:

DrawModel(model, world, view, projection);

You should now be able to run your game and see the model being drawn, as shown below:

screenshot-1.png

You might think it doesn't look too good right now and doesn't do anything but sit there, which is true. We will make big improvements in both of these areas in the next few tutorials.

Download the completed project

What's Next?

In this tutorial, we looked at how to do simple drawing of a 3D model. We still have a way to go before this will be useful in a game, but at least we're making progress. There are two directions you can go from here. First, you can go ahead and look at the tutorials for working with the BasicEffect class, which will help to make your model look cooler. Also, you can go look at the tutorials for doing animation in 3D, which builds directly off of this tutorial.


Troubleshooting.png Having problems with this tutorial? Try the troubleshooting page!