使用 XNA 创建简单 3D 游戏 / 渲染模型
首先,打开 Visual c#,选择“文件”/“新建项目”。在那里选择创建一个新的 C# 项目。
您应该会看到标准的 XNA 启动代码。从之前下载的蒙皮模型示例中添加项目“SkinnedModelPipeline”和“SkinnedModelWindows”,并通过输入using SkinnedModel;
以及其他 using 语句,并在右键单击您的项目并选择“添加引用”下的它们来添加对它们的引用。
此外,请确保该类通过更改类的第一行来引用“Game”类,如下所示。
public class ModelRenderer : Microsoft.Xna.Framework.Game
并将“SkinnedModelWindows”项目中的“SkinnedModel.fx”文件放入项目的 content 文件夹中,因为您的模型将使用它进行渲染。
接下来,创建一个名为“ModelRenderer”的新游戏组件文件。从这里,添加以下类变量。
public AnimationPlayer animationPlayer; //Controls the animation, references a method in the pre-loaded project
public AnimationClip clip; //Contains the animation clip currently playing
public Model currentModel; //Model reference
public SkinningData skinningData; //Used by the AnimationPlayer method
public Vector3 Translation = new Vector3(0, 0, 0); //Fishes current position on the screen
public Vector3 Rotation = new Vector3(0, 0, 0); //Current rotation
public float Scale = 1.0f; //Current scale
将构造函数更改如下。
public ModelRenderer(Model currentModelInput)
{
currentModel = currentModelInput;
// Look up our custom skinning information.
skinningData = currentModel.Tag as SkinningData;
if (skinningData == null)
throw new InvalidOperationException
("This model does not contain a SkinningData tag.");
// Create an animation player, and start decoding an animation clip.
animationPlayer = new AnimationPlayer(skinningData);
}
这段代码(或多或少取自原始示例)初始化了最终将用于动画过程的方法。
接下来,删除预制更新方法中的代码,并用以下代码替换它。
if ((clip != null))
animationPlayer.Update(gameTime.ElapsedGameTime, true, Matrix.Identity);
此处的 .Update 方法将确保由该方法当前播放的动画将按顺序播放,并与使用传递的“gameTime”的所有其他内容同步。
该类的主要成分是下面的 Draw 方法
public void ModelDraw(GraphicsDevice device, Vector3 cameraPosition, Vector3 cameraTarget, float farPlaneDistance)
{
Matrix[] bones = animationPlayer.GetSkinTransforms();
for (int i = 0; i < bones.Length; i++)
{
bones[i] *=
Matrix.CreateRotationX(Rotation.X) //Computes the rotation
* Matrix.CreateRotationY(Rotation.Y)
* Matrix.CreateRotationZ(Rotation.Z)
* Matrix.CreateScale(Scale) //Applys the scale
* Matrix.CreateWorld(Translation, Vector3.Forward, Vector3.Up); //Move the models position
}
float aspectRatio = (float)device.Viewport.Width /
(float)device.Viewport.Height;
// Compute camera matrices.
Matrix view = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Right);
//Create the 3D projection for this model
Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio,
1.0f, farPlaneDistance);
// Render the skinned mesh.
foreach (ModelMesh mesh in currentModel.Meshes)
{
foreach (Effect effect in mesh.Effects)
{
effect.Parameters["Bones"].SetValue(bones);
effect.Parameters["View"].SetValue(view);
effect.Parameters["Projection"].SetValue(projection);
}
mesh.Draw();
}
}
为了本教程的需要,我们不必太担心这一点。
添加一个新方法,该方法将从父文件调用,该方法将调用预加载的“SkinnedModel”的元素,并播放动画。
public void PlayAnimation(String Animation)
{
clip = skinningData.AnimationClips[Animation];
if (clip != animationPlayer.CurrentClip)
animationPlayer.StartClip(clip);
}
当我们扩展实际游戏玩法的逻辑时,我们将向这段代码添加内容(因为它是一个非常方便的地方来存储我们将使用的鱼的实例变量),但目前,这足以涵盖系统所需的基础知识,接下来我们可以关注使用它来渲染模型。
在项目中的“Content”下创建一个名为“Models”的新文件夹,并将您的鱼模型和所有 .tga 纹理文件添加到其中。现在右键单击“引用”文件夹,并添加“SkinnedModelPipeline”。这将允许您通过进入模型的属性并将渲染器更改为新的“SkinnedModelProcessor”来选择正确的渲染器。如果无法选择它,请确保通过右键单击它们并选择“生成”来生成两个“SkinnedModel”项目。
现在回到您的父文件。添加一些新的类变量;
ModelRenderer FishMen; //Your new Fish model
Vector3 cameraPosition; //Defines the position of the camera in the 3D space
Vector3 cameraTarget; //Defines your camera target
float farPlaneDistance = 400f; //Defines your plane distance, the higher, the less 3D 'fog' and the more is displayed
并通过进入更新方法并添加以下行来使用它
FishMen.Update(gameTime);
cameraPosition = cameraTarget = FishMen.Translation;
cameraPosition.Z += 20.0f;
在方法的开头,并在绘制方法中添加
FishMen.ModelDraw(device, cameraPosition, cameraTarget, farPlaneDistance);
在您的
GraphicsDevice.Clear(Color.CornflowerBlue);
行之后。
最后,在“LoadContent”方法的开头添加以下内容。
Model currentModel; //Temporary storage for your new model
Content.RootDirectory = "Content";
currentModel = Content.Load<Model>("Models\\FishModel"); //Loads your new model, point it towards your model
FishMen = new ModelRenderer(currentModel);
FishMen.Translation = new Vector3(0f);//Move it to the centre
FishMen.PlayAnimation("Swim");//Play the default swimming animation
现在,运行您的应用程序,一切应该正常工作。