在前文中,我们初步了解了在Windows Phone 7的XNA框架下实现3D场景的基础知识,能够进行3D空间下物体的变换,并且增加了纹理贴图和光照用于表现更加真实的世界。通过这些操作,我们已经进入了3D的世界。接下来,我们将使用真实的3D物体模型来进行复杂的场景实现,形成一个飞船在天空中飞行的效果。现在,让我们开始吧。
任何复杂的3D物体模型都是由若干个三角形组成,无论是一个立方体,还是一艘宇宙飞船。此前用到的三角形,需要定义它的三个顶点。如果是一个立方体,每个面由两个三角形拼成,6个面共需要12个三角形,即需要36个顶点。假如是更复杂的物体,需要几万甚至更多的三角形才能表示的话,那么开发人员定义顶点的工作量肯定是巨大的。
为了解决这一问题,通常在团队开发中,会有负责3D建模的同事,利用专业的3D建模工具如Autodesk公司的3DS Max、Maya等制作复杂的3D物体模型,制作好后导出为.x或.fbx格式的3D模型文件可供开发时使用。
下面,我们就借用一个经过这样制作现成的宇宙飞船模型文件来开始一个复杂场景的制作。
首先,也是最重要的,就是需要把这种模型文件渲染出来。为此,需要先在Content项目中增加一个新的文件夹,不妨就命名为Models,专门用于存放模型文件及其关的贴图等。然后将wedge_player1.x和wedge_p1_diff_v1.tga两个文件复制到该文件夹下,并将wedge_player1.x文件添加到Content项目中。这两个文件前者是模型文件,后者是该模型对应的贴图,由于在加载模型时会自动处理贴图,所以贴图文件无需添加到Content项目中。
在完成了模型资源的添加以后,就可以写代码进行渲染的工作。XNA中提供了Model类用于处理这种3D模型,用法如下:
model =Content.Load<Model>(@"Models/wedge_player1");
这样,在LoadContent()方法中就可以进行模型的加载了。
接下来,在进入Draw()方法之前,思考一个问题,那就是坐标怎么办?试想,一个大量三角形组成的模型文件,如何把它的坐标正确的映射到我们自己的坐标系中?这里其实是用到了骨骼的形象表示。
在3D模型文件中存在着骨骼数据,就像人体的骨骼一样,只要骨骼被确定,附着于骨骼之上的关联部分的坐标也就确定了。如果对骨骼坐标进行变换,则对应的关联部分也会做出变换。因此,在绘制模型之前,需要一个矩阵数组,用于保存模型的骨骼坐标信息。
下面,为类添加一个成员变量用于保存骨骼坐标:
Matrix[] modelTransforms;
在model加载之后,对该变量进行构造:
modelTransforms=newMatrix[model.Bones.Count];
接下来,该到Draw()方法了,是渲染输出的时候了。
~~~
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
model.CopyAbsoluteBoneTransformsTo(modelTransforms);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.World = modelTransforms[mesh.ParentBone.Index] * scaleMatrix * translateMatrix * rotateMatrix;
effect.View = camera.view;
effect.Projection = camera.projection;
}
mesh.Draw();
}
base.Draw(gameTime);
}
~~~
在这段代码中,首先通过Model.CopyAbsoluteBoneTransformsTo()方法将模型的骨骼数据复制到我们的数组中,然后对模型中的每一个网格区域的每一个渲染效果进行应用,为其指定世界坐标、视图变换和投影变换,从而将模型按照我们的摄像机参数进行渲染输出。
在这里,使用了如下的LoadContent()方法,以取得较好的输出效果。
~~~
protected override void LoadContent()
{
rotateMatrix = Matrix.Identity;
translateMatrix = Matrix.CreateTranslation(10, 0, 0);
scaleMatrix = Matrix.CreateScale(0.01f, 0.01f, 0.01f);
camera = new Camera(this, new Vector3(0, 30, 30), Vector3.Zero, Vector3.Up, MathHelper.PiOver4, (float)GraphicsDevice.Viewport.Width / (float)GraphicsDevice.Viewport.Height, 1.0f, 50.0f);
basicEffect = new BasicEffect(GraphicsDevice);
model = Content.Load<Model>(@"Models/wedge_player1");
modelTransforms=new Matrix[model.Bones.Count];
}
~~~
即向x轴正方向移动了10个坐标单位,缩放0.01倍。
运行结果如图所示。
![](https://box.kancloud.cn/2016-04-08_570727fb3f8af.gif)
由于在Update()函数中加入了点击屏幕时调整rotateMatrix的代码,因此当点击屏幕时会发现模型可以正确的旋转。
怎么样,是不是很兴奋呢?一个如此复杂的3D物体就这样出现了。通过上述的代码可以发现,加载并渲染一个3D模型在XNA框架下还是很容易实现的,我们尽可以把前文中对三角形的所有操作都搬到这里,还有更多的惊喜在等着我们创造。
——欢迎转载,请注明出处 [http://blog.csdn.net/caowenbin](http://blog.csdn.net/caowenbin) ——
- 前言
- Windows Phone 7开发环境初体验
- Windows Phone 7 3D开发中使用纹理贴图
- 在Windows Phone中进行3D开发之一坐标系
- 在Windows Phone中进行3D开发之二摄像机
- 在Windows Phone中进行3D开发之三空间
- 在Windows Phone中进行3D开发之四三角形
- 在Windows Phone中进行3D开发之五平移缩放
- 在Windows Phone中进行3D开发之六旋转
- 在Windows Phone中进行3D开发之七纹理
- 在Windows Phone中进行3D开发之八光照
- 在Windows Phone中进行3D开发之九模型
- 在Windows Phone中进行3D开发之十组件
- 在Windows Phone中进行3D开发之十一天空
- 在Windows Phone中进行3D开发之十二飞行
- 在Windows Phone中进行3D开发之十三阳光
- 在Windows Phone中进行3D开发之后记(附源码)