topical media & game development
game-xna-intro-XnaGraphicEngineChapter5-Graphics-Model.cs / cs
// Project: XnaGraphicEngine, File: Model.cs
// Namespace: XnaGraphicEngine.Graphics, Class: Model
// Path: C:\code\XnaBook\XnaGraphicEngine\Graphics, Author: Abi
// Code lines: 36, Size of file: 900 Bytes
// Creation date: 27.11.2006 03:27
// Last modified: 27.11.2006 03:50
// Generated with Commenter by abi.exDream.com
#region Using directives
using System;
using System.Collections.Generic;
using System.Text;
using XnaModel = Microsoft.Xna.Framework.Graphics.Model;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using XnaGraphicEngine.Game;
using XnaGraphicEngine.Helpers;
using Microsoft.Xna.Framework.Input;
#endregion
namespace XnaGraphicEngine.Graphics
{
<summary>
Model
</summary>
public class Model : IGraphicContent
{
#region Variables
<summary>
Name of this model, also used to load it from the content system.
</summary>
string name = "";
<summary>
Underlying xna model object. Loaded with the content system.
</summary>
XnaModel xnaModel = null;
<summary>
Transform matrices for each mesh part, we only have to get them once
if the model is not animated.
</summary>
Matrix[] transforms = null;
<summary>
Scaling of model. Used to create objecMatrix.
</summary>
float scaling = 1.0f;
<summary>
Default object matrix to fix models from 3ds max to our engine!
</summary>
Matrix objectMatrix =
Matrix.CreateRotationX(MathHelper.Pi / 2.0f);
<summary>
Normalize cube map, initialized when needed!
</summary>
TextureCube normalizeCubeMap = null;
#endregion
#region Properties
<summary>
Name for this model, this is the content name.
</summary>
<returns>String
</returns>
public string Name
{
get
{
return name;
} // get
} // Name
#endregion
#region Constructor
<summary>
Create model
</summary>
<param name="device">Device
</param>
<param name="filename">Filename
</param>
public Model(string setModelName)
{
name = setModelName;
Load();
BaseGame.RegisterGraphicContentObject(this);
// Get matrices for each mesh part
transforms = new Matrix[xnaModel.Bones.Count];
xnaModel.CopyAbsoluteBoneTransformsTo(transforms);
// Calculate scaling for this object, used for rendering.
scaling = xnaModel.Meshes[0].BoundingSphere.Radius *
transforms[0].Right.Length();
if (scaling == 0)
scaling = 0.0001f;
// Apply scaling to objectMatrix to rescale object to size of 1.0
objectMatrix *= Matrix.CreateScale(1.0f / scaling);
} // Model(device, filename)
#endregion
#region Load
public void Load()
{
if (xnaModel == null)
xnaModel = BaseGame.Content.Load<XnaModel>(
@"Content\" + name);
} // Load()
#endregion
#region Dispose
public void Dispose()
{
xnaModel = null;
} // Dispose()
#endregion
#region Render
bool useShaderModel11 = false;
<summary>
Render
</summary>
<param name="renderMatrix">Render matrix
</param>
public void Render(Matrix renderMatrix)
{
if (xnaModel == null ||
xnaModel.Meshes.Count == 0 ||
xnaModel.Meshes[0].MeshParts.Count == 0)
return;
if (Input.KeyboardKeyJustPressed(Keys.LeftControl))
useShaderModel11 = !useShaderModel11;
// Apply objectMatrix
renderMatrix = objectMatrix * renderMatrix;
// Go through all meshes in the model
foreach (ModelMesh mesh in xnaModel.Meshes)
{
// Assign world matrix for each used effect
BaseGame.WorldMatrix =
transforms[mesh.ParentBone.Index] *
renderMatrix;
// And for each effect this mesh uses (usually just 1, multimaterials
// are nice in 3ds max, but not efficiently for rendering stuff).
foreach (Effect effect in mesh.Effects)
{
// Set technique (not done automatically by XNA framework).
if (useShaderModel11)
{
effect.CurrentTechnique = effect.Techniques["Specular"];
if (normalizeCubeMap == null)
normalizeCubeMap = BaseGame.Content.Load<TextureCube>(
@"Content\NormalizeCubeMap");
effect.Parameters["NormalizeCubeTexture"].SetValue(
normalizeCubeMap);
} // if
else
{
effect.CurrentTechnique = effect.Techniques["Specular20"];
} // else
// Set matrices, we use world, viewProj and viewInverse in
// the ParallaxMapping.fx shader
effect.Parameters["world"].SetValue(
BaseGame.WorldMatrix);
// Note: these values should only be set once every frame!
// to improve performance again, also we should access them
// with EffectParameter and not via name (which is slower)!
// For more information see Chapter 6 and 7.
effect.Parameters["viewProj"].SetValue(
BaseGame.ViewProjectionMatrix);
effect.Parameters["viewInverse"].SetValue(
BaseGame.InverseViewMatrix);
// Also set light direction (not really used here, but later)
effect.Parameters["lightDir"].SetValue(
BaseGame.LightDirection);
} // foreach (effect)
// Render with help of the XNA ModelMesh Draw method, which just goes
// through all mesh parts and renders them (with vertex and index
// buffers).
mesh.Draw();
} // foreach (mesh)
} // Render(renderMatrix)
<summary>
Render
</summary>
<param name="renderPos">Render position
</param>
public void Render(Vector3 renderPos)
{
Render(Matrix.CreateTranslation(renderPos));
} // Render(renderPos)
#endregion
#region Unit Testing
if DEBUG
public static void TestRenderModel()
{
Model testModel = null;
TestGame.Start("TestRenderModel",
delegate
{
testModel = new Model("Apple");
TestGame.game.SetCamera(new RotationCamera(TestGame.game));
},
delegate
{
TextureFont.WriteText(20, 40,
"Press Space to disable rotating camera");
TextureFont.WriteText(20, 80,
"Press Ctrl to switch to Shader Model 1.1");
if (Input.KeyboardSpaceJustPressed)
TestGame.game.SetCamera(new SimpleCamera(TestGame.game));
testModel.Render(Matrix.CreateScale(10));
});
} // TestRenderModel()
endif
#endregion
} // class Model
} // namespace XnaGraphicEngine.Graphics
(C) Æliens
20/2/2008
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.