How to: Render a Model

This example demonstrates how to load and render a model using the XNA Framework Content Pipeline. It is assumed that an existing Windows game project is loaded in XNA Game Studio Express. In this example, the project is called "CPModel".

This example has three main parts: importing and processing the model (design-time code), drawing the resultant managed object as a model with full lighting effect in the game (run-time code), and enabling movement of the model with the Xbox 360 game pad (run-time code).

To add the model to the game

  1. From Solution Explorer, add a new subfolder to the solution called Media. This is where you will store the model and any related files.
  2. Right-click the Media folder, click Add, and then click Existing Item.
  3. From the Files of type: control, click XNA Content Files.
  4. Navigate to the proper folder and select the model to be added. For this example, the wedge_player1.x file was selected.

  5. Click the small arrow to the right of the Add button and then click Add as Link. This creates a reference to the selected asset (and not a copy) in the Media folder of your project.


    Making a reference to an existing file in your project is quite different than adding an existing item to your project. A file reference only stores the path to the file in question, not a copy of the contents. This is useful if the referenced file is dependent on additional external files and ensures that the latest version is always used by the solution. This differs from adding a copy of the file to the project. In this case, it is possible to break external file dependencies and create extra work if the original content changes but the copy is not updated.

    For these reasons, it is recommended that any media used by the solution be in a subfolder of the solution and that a reference to the media is added and not a copy.

  6. After the asset is added, open the Properties window and verify that the proper importer and processor are specified. For this example, the Content Importer is X File and the Content Processor is Model. For ease of reference, the asset name value was manually changed to "ship" using the Properties window.

    For more information on the Properties window of a game asset, see Game Asset Properties.

  7. Save the solution.

At this point, build the solution.

This completes the design-time portion of the example. The remaining parts render the model using the managed object (called "ship") and add some user control of the model. All code modifications for this part occur within the game1.cs file of the game project.

To render the model

  1. From Solution Explorer, double-click the game1.cs file.
  2. Modify the Game1 class by adding the following code at the beginning of the declaration.

    private Model myShip;

    This member is used to hold the ship model.

  3. Modify the LoadGraphicsContent method by replacing // TODO: Load any ResourceManagementMode.Automatic content with the following code.

    myShip = content.Load<Model>( "media\\ship" );

    This code loads the model into the myShip member (using Load).

  4. Create a new private method (called DrawModel) in the Game1 class by adding the following code before the existing Draw method.

    private void DrawModel( Model m )
        Matrix[] transforms = new Matrix[m.Bones.Count];
        float aspectRatio = graphics.GraphicsDevice.Viewport.Width / graphics.GraphicsDevice.Viewport.Height;
        m.CopyAbsoluteBoneTransformsTo( transforms );
        Matrix projection = Matrix.CreatePerspectiveFieldOfView( MathHelper.ToRadians( 45.0f ),
            aspectRatio, 1.0f, 10000.0f );
        Matrix view = Matrix.CreateLookAt( new Vector3( 0.0f, 50.0f, Zoom ), Vector3.Zero, Vector3.Up );
        foreach (ModelMesh mesh in m.Meshes)
            foreach (BasicEffect effect in mesh.Effects)
                effect.View = view;
                effect.Projection = projection;
                effect.World = MyWorldRotation * transforms[mesh.ParentBone.Index] * Matrix.CreateTranslation( Position );

    This code sets up the lighting effects for each sub-mesh of the model. The MyWorldRotation and Zoom variables are used for player control. This functionality is added later.

    This render code is designed for only those models with a BasicEffect. For custom effects, the inner for-each loop should be changed to use Effect instead of BasicEffect. In addition, you must manually set the world, view, and projection matrices by using EffectParameter objects.
  5. Modify the Game1.Draw method by replacing the following code // TODO: Add your drawing code here with the following code:

    DrawModel( myShip );

    This causes the effects initialization of the model before the entire model is rendered.

  6. Save the solution.

At this point, the rendering code for the model is complete, but the user control code still needs implementation.

To move the model:

  1. Modify the Game1 class by adding the following code after the myShip declaration.

    private Vector3 Position = Vector3.One;
    private float Zoom = 2500;
    private float RotationY = 0.0f;
    private float RotationX = 0.0f;
    private Matrix MyWorldRotation;

    These members store the current position, zoom, and rotation values. In addition, the MyWorldRotation simplifies the UpdateGamePad code.

  2. Add a private method (called UpdateGamePad) before the call to Update.

    private void UpdateGamePad()
        GamePadState state = GamePad.GetState( PlayerIndex.One );
        if (state.Buttons.A == ButtonState.Pressed)
        Position.X += state.ThumbSticks.Left.X * 10;
        Position.Y += state.ThumbSticks.Left.Y * 10;
        Zoom += state.ThumbSticks.Right.Y * 10;
        RotationY += state.ThumbSticks.Right.X;
        if (state.DPad.Up == ButtonState.Pressed)
            RotationX += 1.0f;
        else if (state.DPad.Down == ButtonState.Pressed)
            RotationX -= 1.0f;
        MyWorldRotation = Matrix.CreateRotationX( MathHelper.ToRadians( RotationX ) ) *
            Matrix.CreateRotationY( MathHelper.ToRadians( RotationY ) );

    This code implements an exit method for the game (pressing the A button) and updates the position members with the current input of the game controller.

  3. Modify the Update method by adding a call to UpdateGamePad, before the call to Update.


    This code updates the state of the position variables with the latest input.

  4. Save the solution.

At this point, all development is complete and you can control the ship location with the game pad and exit by pressing the A button.