使用 XNA 创建简单 3D 游戏/添加天空球体
为了渲染天空球体,我们将创建一个新的渲染类,类似于用于渲染鱼类的类,但经过修改以允许模型在没有骨骼结构的情况下渲染。首先,通过右键单击项目,选择“添加”/“新建项”并选择“类”来创建一个新的类文件。将类和文件名更改为“GenericModelRenderer”。
将默认的 using 语句更改为以下内容。
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using SkinnedModel;
并确保该类使用 XNA 命名空间,方法是在类名后加上
: Microsoft.Xna.Framework.Game
.
添加以下类变量和构造函数。public Model currentModel; public Vector3 Translation = new Vector3(0, 0, 0); public Vector3 Rotation = new Vector3(0, 0, 0); public float Scale = 1.0f;
public GenericModelRenderer(Model currentModelInput)
{
currentModel = currentModelInput;
}
与之前的代码不同,我们不需要初始化动画播放器,因此需要更少的初始化。你会看到这个类与“ModelDraw”方法等效的部分也具有类似的趋势。
public void ModelDraw(GraphicsDevice device, Vector3 cameraPosition, Vector3 cameraTarget, float farPlaneDistance)
{
Matrix[] transforms = new Matrix[currentModel.Bones.Count];
currentModel.CopyAbsoluteBoneTransformsTo(transforms);
// Compute camera matrices.
Matrix view = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Right);
//Calculate the aspect ratio, set the aspect axis and screen zoom.
int aspectConstraint = 1; /* 0 = Maintain Vertical FOV, 1 = Conditional Aspect Ratio, 2 = Maintain Horizontal FOV */
float aspectRatio = (float)device.Viewport.Width / (float)device.Viewport.Height;
float aspectOrigin = 16.0f / 9.0f; /* Aspect ratio condition in which changes axis direction if the current display is below this. Default is 1. */
float zoomFactor = 1.0f;
switch (aspectConstraint)
{
case 1:
if (aspectRatio < aspectOrigin)
{
zoomFactor = zoomFactor * (aspectRatio / aspectOrigin);
}
break;
case 2:
zoomFactor = zoomFactor * (aspectRatio / aspectOrigin);
break;
}
Matrix projection = Matrix.CreatePerspectiveFieldOfView(2.0f * Math.Atan(Math.Tan(MathHelper.ToRadians(45.0f / 2.0f) / zoomFactor), aspectRatio, 1.0f, farPlaneDistance);
// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in currentModel.Meshes)
{
// This is where the mesh orientation is set, as well as our camera and projection.
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = transforms[mesh.ParentBone.Index] *
Matrix.CreateRotationX(Rotation.X) *
Matrix.CreateRotationY(Rotation.Y) *
Matrix.CreateRotationZ(Rotation.Z) *
Matrix.CreateScale(Scale) *
Matrix.CreateWorld(Translation, Vector3.Forward, Vector3.Up);
effect.View = view;
effect.Projection = projection;
}
mesh.Draw();
}
}
请注意,绘制方法使用与其他鱼类代码相同的参数,可以在或多或少相同的方式使用。
在你的模型文件夹中创建一个名为“SkySphere”的新文件夹,并将你的模型和纹理添加到其中。返回到你的主“Game1”文件,并添加新的类变量
GenericModelRenderer SkySphere; //Your SkySphere model
.
进入你的 LoadContent 文件,并添加以下几行来初始化该类并设置模型以进行渲染。
currentModel = Content.Load<Model>("Models\\SkySphere\\SkyModel");
SkySphere = new GenericModelRenderer(currentModel);//Add the skysphere
在绘制方法中,在鱼类模型绘制方法的相同位置添加以下一行。
SkySphere.ModelDraw(GraphicsDevice, cameraPosition, cameraTarget, farPlaneDistance);
渲染代码,如果你与我的设置相同,你应该会看到一个这样的屏幕。
你可能会注意到这不是我们需要的。我们可以通过调整 SkySphere 类中的公共变量来调整位置和比例。在我的例子中,我在 LoadContent() 方法中的类初始化之后添加了以下更改。
SkySphere.Translation.X = 120.0f;
SkySphere.Translation.Z = 15.0f;
SkySphere.Scale = 30.0f;
根据你的喜好进行调整,你应该会看到一个类似于我在这里的屏幕。