这时就会弹出一个【选择要导出的文件】对话框。在弹出的这个对话框的【保存类型】中选择【Panda DirectX(*.X)】,然后自己取一个文件名(这里我们取名Warden,魔兽3中幻影刺客模型所对应的人物名称——守望者),设定好保存的路径,点【保存】。如图。
然后会弹出一个名为【PandaSoft DirectX Exporter】的窗口,在里面我们可以进行一些导出模型参数的设定和修改。如下:
如果没有什么需要特殊设置的,点【确定】就行了。
然后经过3ds Max的处理,我们就发现在我们设定的保存路径下多了.X文件以及配套的纹理了。
这样,如果我们想要在我们写的游戏程序中使用这个幻影刺客(守望者)的三维模型,把这两个文件一起放到我们工程中相应的地方就可以了。
另外提一点,Maya中可以用cvXporter插件来导出X文件,对应于3ds Max中的Panda插件。
之前讲了那么多无非是在为.X文件的诞生造势,下面就开始隆重介绍如何在Direct3D程序中载入X文件的具体知识吧~
而想利用.X文件来在游戏程序中载入三维模型的话,首先就需要将.X文件中的各种数据分别加载到内存中,而这些数据主要包括顶点数据、材质数据和纹理数据等等。首先,我们需要介绍一下与网格模型相关的一个重要的接口——ID3DXMESH。
五、网格模型接口ID3DXMESH
在Direct3D中,微软为我们提供了ID3DXMesh接口表示网格,这个接口继承自
ID3DXBaseMesh接口。网格模型接口ID3DXMesh实际上是三维物体的顶点缓存的集合,他将为我们创建顶点缓存、定义灵活顶点格式和绘制顶点缓冲区等功能封装在一个COM对象中,这样复杂三维物体的绘制就显得非常简便了。
其中,ID3DXMESH接口中的D3DXCreateMesh()可用于创建一个Direct3D网格模型对象,我们可以在MSDN中查到该函数声明是这样的:
[cpp] view plaincopyprint?
1. HRESULT D3DXCreateMesh( 2. _In_ DWORD NumFaces, 3. _In_ DWORD NumVertices, 4. _In_ DWORD Options,
5. _In_ const LPD3DVERTEXELEMENT9*pDeclaration, 6. _In_ LPDIRECT3DDEVICE9pD3DDevice, 7. _Out_ LPD3DXMESH *ppMesh 8. );
然后开始介绍一下这个函数。
■ 第一个参数, DWORD类型的NumFaces,表示创建网格模型的多边形数目。 ■ 第二个参数, DWORD类型的NumVertices,表示创建网格的顶点数目。 ■ 第三个参数, DWORD类型的Options,表示创建网格时的附加选项,他的取值为D3DXMESH枚举体中的一个或者多个值。这个枚举体定义如下:
[cpp] view plaincopyprint?
1. typedef enum D3DXMESH {
2. D3DXMESH_32BIT = 0x001, 3. D3DXMESH_DONOTCLIP = 0x002, 4. D3DXMESH_POINTS = 0x004, 5. D3DXMESH_RTPATCHES = 0x008, 6. D3DXMESH_NPATCHES = 0x4000, 7. D3DXMESH_VB_SYSTEMMEM = 0x010, 8. D3DXMESH_VB_MANAGED = 0x020, 9. D3DXMESH_VB_WRITEONLY = 0x040, 10. D3DXMESH_VB_DYNAMIC = 0x080, 11. D3DXMESH_VB_SOFTWAREPROCESSING =0x8000, 12. D3DXMESH_IB_SYSTEMMEM = 0x100, 13. D3DXMESH_IB_MANAGED = 0x200, 14. D3DXMESH_IB_WRITEONLY = 0x400, 15. D3DXMESH_IB_DYNAMIC = 0x800, 16. D3DXMESH_IB_SOFTWAREPROCESSING =0x10000, 17. D3DXMESH_VB_SHARE = 0x1000, 18. D3DXMESH_USEHWONLY = 0x2000, 19. D3DXMESH_SYSTEMMEM = 0x110, 20. D3DXMESH_MANAGED = 0x220, 21. D3DXMESH_WRITEONLY = 0x440, 22. D3DXMESH_DYNAMIC = 0x880, 23. D3DXMESH_SOFTWAREPROCESSING =0x18000 24. } D3DXMESH, *LPD3DXMESH;
一般情况下,我们都把这个Options取为D3DXMESH_SYSTEMMEM或者D3DXMESH_MANAGED,表示对Direct3D顶点缓冲区和索引缓冲区使用D3DPOOL_SYSTEMMEM或者D3DPOOL_MANAGED内存。
■ 第四个参数, const LPD3DVERTEXELEMENT9类型的*pDeclaration,表示顶点包含哪些信息。这个参数的作用类似于我们之间一直在用的灵活顶点格式(FVF),表示顶点包含了哪些具体数据,但是它却高于灵活顶点格式。它的类型LPD3DVERTEXELEMENT9表示顶点元素,主要用于我们来没讲到的可编程渲染流水线之中,在此我们暂且不用去多做考虑。 ■ 第五个参数, LPDIRECT3DDEVICE9类型的pD3DDevice,就是我们的金钥匙,Direct3D设备的指针了。
■ 第六个参数, LPD3DXMESH类型的*ppMesh,指向我们创建好的网格模型对象指针的地址,用于返回创建好的网格模型对象。可以说我们调用D3DXCreateMesh就是为了创建并得到这个指针地址。后面关于我们创建好的网格模型的访问,都靠这个ppMesh参数了。 需要注意的是,这个创建好网格模型对象的D3DXCreateMesh函数我们通常很少直接去用它,而且直接用它往往也意义不大。它总是“真人不露相”,被封装在了其他Direct3D函数之中,默默地为我们服务。
介绍完网格模型接口ID3DXMESH相关的知识,下面就来看看从X文件载入模型的具体步骤。
六、X文件模型载入三步曲
Ⅰ.三步曲之一:通过.X文件加载网格模型
上面讲到了D3DXCreateMesh函数很少去直接应用,因为我们常常都是通过载入.X文件来生成网格模型的,用到的函数是D3DXLoadMeshFromX。我们可以在MSDN中查到这个函数的声明如下:
[cpp] view plaincopyprint?
1. HRESULT D3DXLoadMeshFromX( 2. _In_ LPCTSTR pFilename, 3. _In_ DWORD Options,
4. _In_ LPDIRECT3DDEVICE9 pD3DDevice, 5. _Out_ LPD3DXBUFFER *ppAdjacency, 6. _Out_ LPD3DXBUFFER *ppMaterials, 7. _Out_ LPD3DXBUFFER *ppEffectInstances, 8. _Out_ DWORD *pNumMaterials, 9. _Out_ LPD3DXMESH *ppMesh 10. );
■ 第一个参数, LPCTSTR类型的pFilename,显然就是一个指向我们需要加载的.X文件的磁盘路径和文件名的字符串了。
■ 第二个参数, DWORD类型的Options,表示创建网格时的附加选项,他的取值为D3DXMESH枚举体中的一个或者多个值。这个参数我们刚才在讲D3DXCreateMesh时已经讲过了,具体参看D3DXCreateMesh的第三个参数,在这里就不赘述了。