DirectX9 3D 快速上手 4

** DirectX9 3D ** ** 快速上手 ** ** 4

**

** By sssa2000

**

** 4/17/2005 ** **

**

接下来我们要使用 Mesh 读入 .X 文件,关于 .X 文件,其实可以说很多,我们可以用外部的工具例如 3DS MAX 来建立 .3ds 文件,然后利用微软提供给我们的工具转换成 .X 文件,如果你同时会用 3DS 你也许会问,那材质怎么办? 你不用担心, .X 文件能自动的包含材质,和动画,所以利用 Mesh 我们可以方便的八我们在 3DS MAX 的做品用在游戏中。

.X 文件允许自定义的扩展,当然这个我们在以后的内容也会讲到,我们先看怎么使用,顺便提一句,还有一种用得比较多的文件格式 .Md3 格式的文件,也就是 Quake3 使用的文件,如果有机会我也会讲到。

关于 3DS 文件和 .X 转换可以参看 GameRes 网站的文章 http://www.gameres.com/Articles/Program/Visual/3D/3DinApp.htm

接下来的过程简单的让你无法相信,请看:

private Mesh mesh = null ; // 建立 Mesh 对象

private Material[] meshMaterials; // 用于保存材质

private Texture[] meshTextures; // 用于保存纹理

private void LoadMesh( string file)

{

ExtendedMaterial[] mtrl; // 保存 Mesh 子集信息,保存 Material 信息

// Load our mesh

mesh = Mesh.FromFile(file, MeshFlags.Managed, device, out mtrl);

// If we have any materials, store them

if ((mtrl != null ) && (mtrl.Length > 0))

{

meshMaterials = new Material[mtrl.Length];

meshTextures = new Texture[mtrl.Length];

// Store each material and texture

for ( int i = 0; i < mtrl.Length; i++)

{

meshMaterials[i] = mtrl[i].Material3D;

if ((mtrl[i].TextureFilename != null ) && (mtrl[i].TextureFilename != string .Empty))

{

// We have a texture, try to load it

meshTextures[i] = TextureLoader.FromFile(device, @"..\.." + mtrl[i].TextureFilename);

}

}

}

}

如果你觉得这里代码比较混乱,没有关系,我们来理一理,首先要说的是 Mesh 类还有两个主要的静态方法可以加载外部模型。这两个方法分别是 Mesh.FormFile 和 Mesh.FromStream 。两个方法本质上来说都是一样的, stream 方法有更多的重载以适应不同大小的流。 Mesh.FormFile 最简单,我们就先只介绍这个,这个方法有很多重载的版本,我们用的是参数最多的一个,这样其他的也都好理解了:

public static Mesh FromFile (
string filename , // 文件名
MeshFlags options ,// 控制着去哪里以及如何加载数据
Device device ,// 渲染 mesh 的 device
out GraphicsStream adjacency ,// 保存每个面相邻的 3 个面
out ExtendedMaterial materials ,// 保存了普通的 Direct3D 材质和一个加载为纹理的字符串, 常是使用的纹理或资源文件名
out EffectInstance effects // 描述了用于 mesh 的 HLSL 材质文件和值。
);

我们使用的是一个有 4 参数的方法:

public static Mesh FromFile (
string filename ,
MeshFlags options ,
Device device ,
out ExtendedMaterial materials
);

接下来,如果读入的这个 .X 文件有材质或者纹理,就根据材质和纹理的大小建立数组以保存这些纹理和材质。 因为 mesh 中可能有许多不同的子集,所以需要分别创建一个材质和纹理的数组以满足每一个子集的需要。 Mesh 会自动地把每一个子集和这些子集的材质纹理一一对座。

这样我们就完成了一个 LoadMesh 函数,这个函数我们可以用在以后任何需要读入 .X 文件的地方,十分的方便。

下面我们来看看我们的成果,当然我们还需要在绘图的地方加几句:

for ( int i = 0; i < meshMaterials.Length; i++)

{

device.Material = meshMaterials[i];// 把保存的材质赋予 device ;

device.SetTexture(0, meshTextures[i]);// 把纹理赋予 device ,如果没有就为 Null

mesh.DrawSubset(i);// 根据子集的 ID 调用 DrawSubset 方法

}

好了,现在我们可以在以往的框架的基础上编译一下了,我们可以看到已经读入了一个 .X 文件,不管怎么样 都是值得庆贺的。我们再看看 SDK Tutorial6 的例子后, 发现这个程序的结果可以旋转,其实也很好实现,我们只需要设置一下旋转矩阵就可以了,就像上一张我们讲的那样,在上面那段 for 前面加上一句就可以了:

device.Transform.World = Matrix.RotationYawPitchRoll(yaw, pitch, roll) * Matrix.Translation(x, y, z);

好了这样我们也就达到目的了,你也可以随自己的意思设置变换矩阵,很 COOL 吧?

好了,下面是完整的代码,如果大家有什么意见,发到我的 blog 上吧。大家一起进步。

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using Microsoft.DirectX;

using Microsoft.DirectX.Direct3D;

namespace Chapter5Code

{

///

1<summary>
2
3///  Summary description for Form1. 
4
5///  </summary>

public class Form1 : System.Windows.Forms.Form

{

private Device device = null ;

private Mesh mesh = null ;

private Material[] meshMaterials;

private Texture[] meshTextures;

///

1<summary>
2
3///  Required designer variable. 
4
5///  </summary>

private System.ComponentModel.Container components = null ;

private float angle = 0.0f ;

public Form1()

{

//

// Required for Windows Form Designer support

//

InitializeComponent();

this .SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true );

}

///

1<summary>
2
3///  We will initialize our graphics device here 
4
5///  </summary>

public void InitializeGraphics()

{

// Set our presentation parameters

&

Published At
Categories with Web编程
Tagged with
comments powered by Disqus