跳转到内容

使用 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

现在,运行您的应用程序,一切应该正常工作。

华夏公益教科书