30 out of 40 rated this helpful - Rate this topic

Tutorial 1: Displaying a 3D Model on the Screen

This article details how to use the XNA Framework Content Pipeline to load a 3D model and its associated textures, and it presents the code necessary to display the model on the screen.

The Complete Sample

The code in this tutorial illustrates the technique described in the text. A complete code sample for this tutorial is available for you to download, including full source code and any additional supporting files required by the sample.

Introduction

In Your First Game: Microsoft XNA Game Studio in 2D, you saw a simple example that used the XNA Framework Content Pipeline to load a sprite, represented by a Texture2D object. You also used the XNA Framework to draw the sprite on the screen. This tutorial goes beyond that simple sample to help introduce you to many concepts that XNA Game Studio makes easy, so you can focus on making fun, interactive games.

This first tutorial will introduce you to the Content Pipeline in a little more detail, and will introduce you to some of the XNA Framework API calls you will use to draw 3D objects on the screen. When you complete this tutorial, you'll have a 3D model drawing on your screen. The model will have textures and lighting. Let's get started!

Step 1: Downloading the Art Assets

The first thing that you will need before you start coding are some art assets to play around with. In this case, you need a 3D model, and an associated texture file so that the model has some detail. These assets will be loaded into your game using the XNA Framework Content Pipeline, which is a feature built right into the Solution Explorer feature of supported version of Microsoft Visual Studio tools.

You can find these assets in this sample file (GoingBeyond1_Tutorial_Sample.zip). Download the sample file now and extract its contents to a directory on your local drive.

Step 2: Creating the New Project

Now that the art assets are available to you, the next step is to create the actual code project that you will be writing.

  • Click the File menu, and then click New Project to create a new project. A dialog box will appear with a tree list on the left pane, marked Project Types.

  • Select the XNA Game Studio 3.1 tree node underneath the Visual C# node. A set of available projects will appear in the right pane.
  • In the right pane of the dialog box, click either Windows Game (3.1) or Xbox 360 Game (3.1), depending on whether you are developing on the Xbox 360 or Windows. If you develop for Xbox 360, be sure you have a membership in the XNA Creators Club as described in Connecting to Your Xbox 360 Console with XNA Game Studio 3.1 Otherwise, you will not be able to play your game!
  • Type a name for your game into the Name field, and a path to where you want the game files stored in the Location field.
  • Click OK.

The code for your new game will be displayed. The project already contains many of the methods that are needed to start and run a game. Right now, however, you need to make sure your art assets are being loaded. Then you can modify the game to display them on the screen. Follow these steps to get some art into your project.

  • Make sure you can see the Solution Explorer for your project on the right side of the window. If you cannot see it, click the View menu, and then click Solution Explorer. When it appears, you will see files associated with your project in a tree structure.
  • In Solution Explorer, look for a node named Content. This is where you will store the art and audio for your game. You must add two folders underneath this one.
  • Right-click the Content node, click Add, and then click New Folder. This will create a new folder under the Content node. Name this folder Models.
  • Repeat the last step, creating a new folder under the Content node. This time, call the folder Textures.

Your project structure should look similar to this:

Bb197293.tutorial_2_projectfolders_content(en-us,XNAGameStudio.31).gif

You are now ready to add the art from the previously downloaded sample file. The first is a 3D model that will go into this new Content\Models folder, and the second is a texture that will be drawn on the 3D model; this will go in the Content\Textures folder. The files you need are included in the Content sub-project from the GoingBeyond1_Tutorial_Sample.zip file. To add them:

  • Right-click the Models folder in the Solution Explorer, click Add, and then click Existing Item. Using the dialog box that appears, browse back to the path you extracted the contents of the sample file to and find the Contents\Models folder. Select p1_wedge.fbx. If you cannot see any files, make sure you change the Files of type selection box to read Model Files. Click OK.
  • Now, copy the texture associated with the model into the Textures folder. To do this, open a Windows Explorer window and browse to the Content\Textures folder of the extracted sample. Copy wedge_p1_diff_v1.tga, and then browse to your project folder, then into the Content\Textures folder, and paste in the file you just copied.

Note that you do not see the texture you added in Solution Explorer. When you add a model, the textures that the model uses do not need to be added to the Content Pipeline. If you need to add textures that you will access manually (such as textures used for 2D sprite drawing), do so via Solution Explorer. Otherwise, you can simply copy the texture files to the appropriate folder.

When the files are added to the project, the Content Pipeline automatically identifies them as content files and sets the appropriate processors to run when you build your project. This will happen silently; you will not need to do anything. If you would like to learn more about the Content Pipeline, see Content Pipeline.

Bb197293.note(en-us,XNAGameStudio.31).gifNote
Model files contain path information for the textures they use. The ship model you recently added to your project expects to find its texture in a Textures folder that exists alongside the folder the model is in. This will be true for all models used in this tutorial. Models you create or retrieve from other sources may have different path requirements and therefore may require different folder setups. Determine the correct texture paths by examining the model files, or compiling the model as part of your game using XNA Game Studio and noting any Content Pipeline path errors that are returned.

At this point, you are ready to code.

Step 3: Load the Model by Using the Content Pipeline

Take a look at the code for Game1.cs. It should still be on your screen from opening up your project. You will see a lot already done for you. Each of the methods already in the code are waiting for you to drop in your own calls to the XNA Framework. For now, start by modifying the LoadContent method.

  • In the code, find the LoadContent method.
  • Modify the code (including adding the lines shown above the method) to look like this:

    // Set the 3D model to draw.
    Model myModel;
    
    // The aspect ratio determines how to scale 3d to 2d projection.
    float aspectRatio;
    
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);
    
        myModel = Content.Load<Model>("Models\\p1_wedge");
        aspectRatio = graphics.GraphicsDevice.Viewport.AspectRatio;
    }
    

In that step, you have told the Content Pipeline to load your model into your game when LoadContent is called at the beginning of your game. Note how you have to pass in the path to the asset relative to your project directory. Also note that there is no extension on the asset anymore. The name of the asset can be anything you want, but by default it is the name of the asset file minus its extension. To see more information on how to change the name of your asset, see Game Asset Properties.

The code now loads the model. Your next step is to get it showing on the screen.

Step 4: Display the Model on the Screen (and Make It Rotate)

You will want to modify two of the methods in your Game1.cs file.

  • In the Draw method, you will draw the model on the screen with texture and lighting.
  • In the Update method, you will make the model change its orientation based on time, so it appears to rotate over time.

Do the harder work first—drawing the model. The first step is to use some XNA Framework methods to set up the model's position and lighting.

  • In the code, find the Draw method.
  • Modify the code (including adding the lines shown above the method) to look like this:

    // Set the position of the model in world space, and set the rotation.
    Vector3 modelPosition = Vector3.Zero;
    float modelRotation = 0.0f;
    
    // Set the position of the camera in world space, for our view matrix.
    Vector3 cameraPosition = new Vector3(0.0f, 50.0f, 5000.0f);
    
    protected override void Draw(GameTime gameTime)
    {
        graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
    
        // Copy any parent transforms.
        Matrix[] transforms = new Matrix[myModel.Bones.Count];
        myModel.CopyAbsoluteBoneTransformsTo(transforms);
    
        // Draw the model. A model can have multiple meshes, so loop.
        foreach (ModelMesh mesh in myModel.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] * 
                    Matrix.CreateRotationY(modelRotation)
                    * Matrix.CreateTranslation(modelPosition);
                effect.View = Matrix.CreateLookAt(cameraPosition, 
                    Vector3.Zero, Vector3.Up);
                effect.Projection = Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.ToRadians(45.0f), aspectRatio, 
                    1.0f, 10000.0f);
            }
            // Draw the mesh, using the effects set above.
            mesh.Draw();
        }
        base.Draw(gameTime);
    }
    

This code uses helper methods provided by the XNA Framework to set up the necessary 3D math and lighting to display the model on the screen. Use the World matrix to change the position of the model in the world, the View matrix to change the position and direction of the camera (your eye), and the Projection matrix to control how the view of the 3D world is turned into a 2D image (projected) on your screen.

The call to CopyAbsoluteBoneTransformsTo and associated code inside the setup of the World matrix are not strictly necessary for this model. However, when using more complicated models, which often use hierarchical structure (where mesh positions, scales, and rotations are controlled by "bones"), this code ensures that any mesh is first transformed by the bone that controls it, if such a bone exists. The mesh is then transformed relative to the bone transformation.

If you compile and run your code now, you will see your model on the screen! It is a spaceship with detail texture. But if you can resist the urge to compile your project and run, you can easily make the model rotate in real-time so you can see all of it:

  • In the code, find the Update method.
  • Modify the code (including adding the lines shown above the method) to look like this:

    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
            ButtonState.Pressed)
            this.Exit();
    
        modelRotation += (float)gameTime.ElapsedGameTime.TotalMilliseconds *
            MathHelper.ToRadians(0.1f);
    
        base.Update(gameTime);
    }
    

And that's it. Compile and run your project by hitting the F5 key or clicking the Debug menu, and then clicking Start Debugging.

Bb197293.tutorial_2_drawing(en-us,XNAGameStudio.31).jpg

Congratulations!

You did it. There is a lot to making games, but you have taken the first step. A 3D model with lighting and movement in real time. From here, there is no limit to where you could go!

For simplicity's sake, we took some shortcuts that could be optimized for better performance. An obvious improvement would be to precalculate the View and Projection matrices instead of calculating them every time Draw is called, since they do not change. Try out this optimization as a first step. When you are ready to make your game interactive, go to the next tutorial.

Next...

Ideas to Expand

Got the urge to tinker with the project a bit? Try these ideas.

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
how to match the model Bones to kinect Skeleton

hi

first of all sorry for my terrible english.

im developing a kinect virtual dressing room like these:  www.fitnect.com and  http://vimeo.com/25933286

im doing this with VS2010 and XNA4.0 and my kinect

what i have done is: captured the depth,RGB,Skeleton From Kinect and mach them together.
i load the dress 3d model(.fbx) but i cant adapt the dress to the user Body Based On User Skeleton.

how can i do this. i want that , when a user wave his hand the cloth 3dmodel wave its hand.

i belive the answer is in model skeleton or mesh bons. how shoud i mach them???

please help.

mrjm.Cyberman@gmail.com

thanks

How do I get the sample code to run on my XBox360?
I just downloaded the tutorial sample and got it loaded into Visual Studio. It seems to be 2 projects in one, with both a Windows and XBox360 version loading into the IDE at the same time. That's all very well and good, but every time I run the project, it loads up on my PC and not the Xbox. This tutorial says absolutely nothing about this, and doesn't tell me why I need to be connected to XNA Game Studio Connect to run the program locally on my PC, doesn't tell me how to make the program run on my Xbox, and doesn't tell me why the program fails to work at all if I remove the Windows project from the program in the Solution Explorer.

There are other issues with the download that I won't go into, as these are enough for now, I think.
hellow
hellow .
Why I got an error Error loading "Models\p1_wedge".File not found
$0I have fixed this problem. Now it works very well.  In Solution explorer window, You should right click "...Content",  choose Add-->new folder-->Models, then add existing item "p1_wedge", Textures is similar.$0 $0$0 $0 $0$0 $0 $0--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------$0 Hi, $0I always got this error.$0 $0My code is the same with code posted by whoescher.$0 $0Please help me to fix it. Thanks a lot.$0 $0$0 $0
Why I got an error Error loading "Models\p1_wedge".
$0Hi, whoescher,$0 $0My code is the same with yours. But why I always get an error. $0 $0So confused.$0 $0$0 $0 $0$0 $0 I was able to get this working in VS2010 with XNA 4.0 no problemo.$0 $0 The only trick was the new location for the Content, which is now stored in its own project (which will be called "GoingBeyondContent (Content)" if you're following the example). Create the "Models" and "Textures" directories inside that project, then drag and drop the file from the zip file.$0 $0 Here's the entire contents of my Game1.cs file: $0 $0using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace GoingBeyond
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;

Model myModel; // Set the 3D model to draw.
float aspectRatio; // The aspect ratio determines how to scale 3d to 2d projection.
Vector3 modelPosition = Vector3.Zero; // Set the position of the model in world space, and set the rotation.
float modelRotation = 0.0f;
Vector3 cameraPosition = new Vector3(0.0f, 50.0f, 5000.0f); // Set the position of the camera in world space, for our view matrix.

public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}

/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here

base.Initialize();
}

/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);

myModel = Content.Load<Model>("Models\\p1_wedge");
aspectRatio = graphics.GraphicsDevice.Viewport.AspectRatio;
}

/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}

/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();

modelRotation += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f);

base.Update(gameTime);
}

/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);

// Copy any parent transforms.
Matrix[] transforms = new Matrix[myModel.Bones.Count];
myModel.CopyAbsoluteBoneTransformsTo(transforms);

// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in myModel.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] * Matrix.CreateRotationY(modelRotation) * Matrix.CreateTranslation(modelPosition);
effect.View = Matrix.CreateLookAt(cameraPosition, Vector3.Zero, Vector3.Up);
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f);
}

// Draw the mesh, using the effects set above.
mesh.Draw();
}

base.Draw(gameTime);
}
}
}$0
XNA 4.0 VS 2010 Folder Layout (Screenshot)
Simply create the folders "Model" and "Textures" under the "Bla Bla(Content)" location, and add as required.                                                                               Screenshot: http://i53.tinypic.com/2v3qygy.png                                                                                                                                                                         I wonder why you can't change it to XNA 4 at the top - Meh -_-                                                                                                                                                  And if anyone sees weird $0 symbols when posting - This editor replaces the "Enter" character with them - Just spam "Spacebar" for new lines.... Its buggy, but it works - Sorta...
Question: How to make a model/texture?
I think you should describe how u make a texture / mode $0.fbx$0 $0.tga$0 $0What program?$0 Please reply$0 $0$0 $0 $0
Clarification of "content" folder structure
The correct folder structure is as follows:
  GoingBeyondContent(Content)
     Models
         p1_wedge.fbx
     Textures
         wedge_p1_diff_v1.tga
Nice tutorial :)
That´s a nice tutorial, thanks dude!

For those with Visual Studio 2010 or Visual C# 2010:

Simply create a new XNA 4.0 windows game project in Visual C# 2010 Express Edition and follow the steps described in tutorial, it will work very well!!

Andre Brazil
Problem with rendering this.
I'm keep getting these kind of error:
System.InvalidCastException was unhandled
  Message=Unable to cast object of type 'Microsoft.Xna.Framework.Graphics.EffectMaterial' to type 'Microsoft.Xna.Framework.Graphics.BasicEffect'.
  Source=WindowsGame2
  StackTrace:
       at WindowsGame2.Game1.Draw(GameTime gameTime) in F:\WindowsGame2\WindowsGame2\WindowsGame2\Game1.cs:line 82
       at Microsoft.Xna.Framework.Game.DrawFrame()
       at Microsoft.Xna.Framework.Game.Tick()
       at Microsoft.Xna.Framework.Game.HostIdle(Object sender, EventArgs e)
       at Microsoft.Xna.Framework.GameHost.OnIdle()
       at Microsoft.Xna.Framework.WindowsGameHost.RunOneFrame()
       at Microsoft.Xna.Framework.WindowsGameHost.ApplicationIdle(Object sender, EventArgs e)
       at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at Microsoft.Xna.Framework.WindowsGameHost.Run()
       at Microsoft.Xna.Framework.Game.RunGame(Boolean useBlockingRun)
       at Microsoft.Xna.Framework.Game.Run()
       at WindowsGame2.Program.Main(String[] args) in F:\WindowsGame2\WindowsGame2\WindowsGame2\Program.cs:line 15
  InnerException:

Seriously, I did the code exactly what you did, nothing, still.
Can not convert
Could not convert to use in VS 2010.

ps: Why do you code with such old VS? :(