您的位置:首页 > 其它

XNA学习(二) 载入3D模型

2008-08-05 14:39 656 查看
今天,我会在昨天的基础上,在那个单调的蓝色屏幕上显示一个3D模型。这是XNA Game 3.0 帮助文档上的示例,我要照葫芦画一遍,并尽力读懂它。

首先,右击解决方案资源管理器中的Content节点,添加两个文件夹,分别命名为Models和Textures。接着在Models文件夹中导入一现有项p1_wedge.fbx(即待会要添加的3D模型,先下载一个工程,里面Models文件夹里可找到。地址:http://go.microsoft.com/fwlink/?LinkId=103987&clcid=0x409),在Textures文件夹中导入一现有项wedge_p1_diff_v1.tga(和前面3D模型相关的纹理材质,获得方法同上)。

现在写代码。加入两个变量:

Model myModel;

float aspectRatio;

第一行,定义一个Model。aspectRatio表示纵横比,将3D世界的视图转换成屏幕上的2D图象(投射)会用到,结合下面的代码会渐渐看得明白点。在LoadContent()中添加以下代码

myModel = Content.Load<Model>("Models//p1_wedge");

aspectRatio = (float)graphics.GraphicsDevice.Viewport.Width /

(float)graphics.GraphicsDevice.Viewport.Height;

Content.Load<Model>("Models//p1_wedge"),是载入Models文件夹中的3D模型。这里的Content.Load<T>()方法可以载入 Model(模型),Effect(特效),Texture(纹理),Texture2D,Texture3D 和TextureCube等类型的素材。值得注意的是,这里载入指定位置模型时,是不需要写扩展名的(是p1_wedge而不是p1_wedge.fbx)。aspectRatio的值为设备视口的纵横比,根据具体情况可以是如:1024/768,800/600等,也可直接写成aspectRatio = 640.0f / 480.0f。

下面将刚才载入的模型显示在屏幕上。再加入几个变量:

Vector3 modelPosition = Vector3.Zero;

float modelRotation = 0.0f;

Vector3 cameraPosition = new Vector3(0.0f, 0.0f, 5000.0f);

第一个是3D模型在屏幕上的显示位置,Vector3.Zero将三维坐标的x,y,z分量设为0,即原点,表示屏幕中心。modelRotation是3D模型一次旋转的弧度,初始为0,即不旋转。cameraPosition 是摄影机的位置,也就是我们眼睛的位置。3D模型在坐标原点,Vector3(0.0f, 0.0f, 5000.0f)就表示我们在正Z轴上距离5000的地方看它。如果这样看到的它的正面,把5000改成-5000,看到的将是它的尾部;把第一个0改成1000,我们就在它的左前方;第二个0改成1000,我们就是在俯视它......

再在Draw()函数里加入以下代码:

Matrix[] transforms = new Matrix[myModel.Bones.Count];

myModel.CopyAbsoluteBoneTransformsTo(transforms);

foreach (ModelMesh mesh in myModel.Meshes)

{

foreach (BasicEffect effect in mesh.Effects)

{

effect.EnableDefaultLighting();

effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateRotationY(modelRotation)

* Matrix.CreateTranslation(modelPosition);

effect.View = Matrix.CreateLookAt(cameraPosition, Vector3.Zero, Vector3.Up);

effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f),

aspectRatio, 1.0f, 10000.0f);

}

mesh.Draw();

}

前面两句是获得3D模型bones的位置矩阵,ModelMesh 是3D Model的组成成分,Modelbone用来描述Model中每个mesh与其parent mesh的关系,Bones是ModelBone的集合。CopyAbsoluteBoneTransformsTo(参数)方法将Model中每个bone与其parent bone的关系变换矩阵赋给参数(这里是个矩阵组)。

然后遍历Model的每个ModelMesh,设置与它们相关的参数,再画出来。只要画出了每个mesh,自然也就画出了Model。

关于BasicEffect,网上说:“XNA为那些要使用光照,材质,纹理和变换功能,但又不想自己编写特效的用户们提供了BasicEffect 类。也就是不使用Shader的Render方式。”“BasicEffect类可以简单的通过设置属性,包含光照、纹理等等就可以在“五分钟”内实现对一个物体的呈现。”于是,第7行代码表示使用默认光照。

BasicEffect的World属性:设置World矩阵。通过World 矩阵变换,将3D坐标系转化为世界坐标系。在这里对它设置,以确定Model的最终位置(不一定是我们看到的位置,比如摄像机(眼睛)位置变换后),其原理就是对当前对象进行移动、缩放和旋转,实现方法是矩阵相乘。Matrix.CreateRotationY(modelRotation)是生成绕Y轴旋转的矩阵,参数是旋转角度。既然可以绕Y轴旋转,当然也可以绕其它轴旋转(不止是X,Z轴呢)。Matrix.CreateTranslation(modelPosition)是创建当前位置的转换矩阵。

BasicEffect的View属性:设置View矩阵。改变摄像机(眼睛)的位置和方向。Matrix.CreateLookAt( Vector3 cameraPosition,Vector3 cameraTarget,Vector3 cameraUpVector)方法用来创建一个观测矩阵。第一个参数是摄像机位置,前面有提到。第二个参数表现观察方向,比如以上代码中这个参数是Vector3.Zero,即模型位置,那我们的眼睛就向这个位置望过去,表现出来就是正视它。第三个参数表示向上的位置,值Vector3.Up(0,1,0)是我们看物体的最常规方向,如果改成Vector3.Down(0,-1,0),则变成倒立着看物体了,表现为那个模型倒过来。

BasicEffect的Projection属性:设置Projection矩阵。通过矩阵变换,将3D坐标系投影到2D屏幕上。CreatePerspectiveFieldOfView(float fieldOfView,float aspectRatio,float nearPlaneDistance,float farPlaneDistance)方法建立一个基于视野的投影矩阵,第一个参数表示观察的视野角度,如下图中角MON,这里是45度角,MathHelper.ToRadians()方法将45度转化为弧度,也可写成(float)Math.PI/4;第二个参数是宽高比;第三个参数是近平面(图中平面1)与眼睛距离;第四个参数是远平面(图中平面2)与眼睛距离。显然,第一个参数在0和PI这间,第三个参数要小于第四个参数。



最后,在Update()函数中加入以下代码,实现模型的旋转。

modelRotation += (float)gameTime.ElapsedGameTime.TotalMilliseconds *

MathHelper.ToRadians(0.1f);

gameTime.ElapsedGameTime是最后一次刷新到现在逝去的时间,在这里表现为两次调用Update()函数的时间间隔,TotalMilliseconds是以整毫秒和毫秒的小数部分表示时间间隔方式,为double型。

现在,运行一下,就可以看到蓝色背景的屏幕上多了一个旋转的战斗机了。

我的程序下载地址:http://download.csdn.net/source/571754
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: