【阅读笔记之十二】《DIRECTX.9.0.3D游戏开发编程基础》:网格(二)浅话X文件和渐进网格
2012-12-10 23:48
411 查看
网格(二)
这里我们学习的关于网格部分是以上一章内容为基础的,这里给出链接: /article/11437162.html
在D3DX库中,Microsoft提供很多与网格相关的接口、结构和函数。这里我们主要学习X文件的相关操作和渐进网格。
1. XFile
到目前为止,我们已经能够使用D3DXCreate*函数创建一些简单的几何体,例如球体、圆柱体等。但是,我们需要明白的是,Microsoft不可能把所有我们想要绘制的3D物体都做好供给我们使用。Microsoft只是提供了几个常用的简单的几何体的信息,然后通过简单的函数接口(D3DXCreate*函数)供给我们用户来绘制这些非常常用的几何体。但是,假如我们想要绘制一条小狗(自己家养的旺财~),就必须依赖于自己对于狗的几何信息(顶点数据)以及毛色(材质)有足够充分的了解。这样,我们就能够在一个唤作X文件里面写出我们要绘制的狗的所有信息。设想一下,这是一件非常繁杂的工作。万幸的是,我们有建模软件诸如3DS
Max、Maya等,这样,我们就可以通过可视化的方法描述绘制的对象,最后在导出XFile。
X文件是微软捣鼓出来的,它是在DirectX中定义的一种特殊的网格格式(这种网格格式理所当然地包含了几何信息,属性信息等)。正是因为XFile是微软的儿子,所以其在Windows下面的支持是木有任何问题的。废话不多说了,我们直接来学习怎么样使用XFile。
1)加载XFile
需要说明的是,XFile只是描述了我们将要绘制的几何体的信息(包括几何信息,属性等信息),这个我们可以从X文件的命名上看得出来。例如我们定义一个关于旺财的XFile为 dogWangCai.x 。利用3D建模软件创建好XFile之后,我们利用一个函数将这个XFile和它的上线(ID3DXMesh对象)接头。这个函数就是D3DXLoadMeshFromX,其原型如下:
这里我们需要解释一下ID3DXBuffer接口。在这之前,我们已经接触过很多缓存结构,如顶点缓存,索引缓存,属性缓存等等。而ID3DXBuffer接口就是作为一种缓存接口。该接口是一种泛型数据结构,存储在一个连续的内存块中。该接口只有两个方法:
LPVOID GetBufferPointer(); 返回指向缓存中数据起始位置的指针
DWORD GetBufferSize(); 返回缓存的大小,单位为字节
该接口之所用void类型的指针,是为了保持其通用性,但是使用时需要强制类型转换成我们使用的缓存结构类型。例如我们需要一个表示网格邻接信息的缓存时,因为表示邻接信息的是一个DWORD类型的数组,因此我们强制类型转换,可以这样写:
DWORD *pAdjacencyInfo = (DWORD *)adjacencyInfo->GetBufferPointer();
惯例,最后需要说明的是,ID3DXBuffer是一个COM对象,接口使用完毕之后必须将其释放,以防内存泄露。
2)XFile材质
现实中的一个几何体有几何信息,也有材质等信息。这也就是说XFile中也必然包含这些信息。上面的D3DXLoadMeshFromX函数的参数中,有描述几何信息的邻接信息的参数,当然还有材质信息的ppMaterials的参数。然而,材质信息是被存储在一个被称作D3DXMATERIAL类型的结构数组中。值得一提的是,D3DXMATERIAL结构数组的第i项与第i个子集(子集就是一系列用相同绘制属性绘制三角形图元的组合,在上一章中有讲述)相对应,绘制时候循环遍历即可。该结构定义如下:
其中,字符串指针pTextureFilename指定了与网格相关的纹理文件名。需要说明的是,XFile文件中并未存储纹理数据,它只包含了纹理图像文件名,该文件名是对包含了实际纹理数据的纹理图像的引用。当用函数D3DXLoadMeshFromX加载XFile文件之后需要根据指定的纹理文件名加载纹理数据。
2. 渐进网格
首先,我们需要明白为什么需要渐进网格这个东西。在游戏中,我们绘制的场景中是尽可能地模拟现实世界的一切。自然地,所有物体对于观察者都会有远景之分。当你距离某物体很远时,你看到的就会比较模糊,而这种模糊和粗糙在Direct3D中就是通过减少物体的面元个数来实现的。事实上,这也是必须的。对于一个大型游戏而言,如果所有的物体都按照最原始的网格面片个数来绘制的,那么这样做的话是和游戏对速度的要求是矛盾的。渐进网格就是在这样的情况下应运而生的。
废话就不多了,我们来了解一下渐进网格的具体用法。渐进网格类似于多级渐进纹理。在代码中我们用ID3DXPMesh接口来使用渐进纹理。
1)生成渐进网格
和前面一样,我们需要先弄出个具体的ID3DXPMesh对象并用对应的信息填充。在Direct3D中,我们用如下函数创建ID3DXPMesh对象。
2)顶点属性权值
在前面学习顶点我们知道,我们定义的顶点结构体都有自己的属性,这些属性包括了顶点的位置、颜色等等。渐进网格就是要根据实际情况来移除一些不必要的顶点。这样说来,到底应该移除顶点呢?计算机并不是我们想象中那么智能,相反,他是很笨,聪明的是人。我们需要为顶点每一个可能的分量指定一个权值,以指定它被移除的概率大小。权值越大,被移除的概率越大。在代码中,我们用一个唤作D3DXATTRIBUTEWEIRHTS的结构体来描述顶点属性权值。该结构定义如下:
在Direct3D中,D3DXATTRIBUTEWEIGHTS都有默认值,如下。一般情况,除非特别需要,一般使用默认值。
关于渐进网格的学习就到这里了。兴许这个时候对渐进网格的感觉还是很模糊,这个是正常的。我们下面的学习还会再接触渐进网格。
理论的学习是枯燥的,大家加油,共勉!
本章完~
——Josh 2012年12月10日
这里我们学习的关于网格部分是以上一章内容为基础的,这里给出链接: /article/11437162.html
在D3DX库中,Microsoft提供很多与网格相关的接口、结构和函数。这里我们主要学习X文件的相关操作和渐进网格。
1. XFile
到目前为止,我们已经能够使用D3DXCreate*函数创建一些简单的几何体,例如球体、圆柱体等。但是,我们需要明白的是,Microsoft不可能把所有我们想要绘制的3D物体都做好供给我们使用。Microsoft只是提供了几个常用的简单的几何体的信息,然后通过简单的函数接口(D3DXCreate*函数)供给我们用户来绘制这些非常常用的几何体。但是,假如我们想要绘制一条小狗(自己家养的旺财~),就必须依赖于自己对于狗的几何信息(顶点数据)以及毛色(材质)有足够充分的了解。这样,我们就能够在一个唤作X文件里面写出我们要绘制的狗的所有信息。设想一下,这是一件非常繁杂的工作。万幸的是,我们有建模软件诸如3DS
Max、Maya等,这样,我们就可以通过可视化的方法描述绘制的对象,最后在导出XFile。
X文件是微软捣鼓出来的,它是在DirectX中定义的一种特殊的网格格式(这种网格格式理所当然地包含了几何信息,属性信息等)。正是因为XFile是微软的儿子,所以其在Windows下面的支持是木有任何问题的。废话不多说了,我们直接来学习怎么样使用XFile。
1)加载XFile
需要说明的是,XFile只是描述了我们将要绘制的几何体的信息(包括几何信息,属性等信息),这个我们可以从X文件的命名上看得出来。例如我们定义一个关于旺财的XFile为 dogWangCai.x 。利用3D建模软件创建好XFile之后,我们利用一个函数将这个XFile和它的上线(ID3DXMesh对象)接头。这个函数就是D3DXLoadMeshFromX,其原型如下:
HRESULT D3DXLoadMeshFromX( LPCSTR pFilename, //所要加载的XFile文件名 DWORD Options, //创建网格时所使用的创建标记 LPDIRECT3DDEVICE9 pDevice, //相关设备指针 LPD3DXBUFFER *ppAdjacency, //返回一个ID3DXBuffer对象,其中包含了网格对象的邻接信息 LPD3DXBUFFER *ppMaterials, //返回一个ID3DXBuffer对象,其中包含了网格对象的材质数据 //材质数据由D3DXMATERIAL类型的结构数组描述 LPD3DXBUFFER *ppEffectInstances,//返回一个ID3DXBuffer对象,通常为0 PDWORD pNumMaterials, //网格中的材质数目 LPD3DXMESH *ppMesh //【out】返回所创建的并以填充了XFile几何数据的ID3DXMesh对象 );
这里我们需要解释一下ID3DXBuffer接口。在这之前,我们已经接触过很多缓存结构,如顶点缓存,索引缓存,属性缓存等等。而ID3DXBuffer接口就是作为一种缓存接口。该接口是一种泛型数据结构,存储在一个连续的内存块中。该接口只有两个方法:
LPVOID GetBufferPointer(); 返回指向缓存中数据起始位置的指针
DWORD GetBufferSize(); 返回缓存的大小,单位为字节
该接口之所用void类型的指针,是为了保持其通用性,但是使用时需要强制类型转换成我们使用的缓存结构类型。例如我们需要一个表示网格邻接信息的缓存时,因为表示邻接信息的是一个DWORD类型的数组,因此我们强制类型转换,可以这样写:
DWORD *pAdjacencyInfo = (DWORD *)adjacencyInfo->GetBufferPointer();
惯例,最后需要说明的是,ID3DXBuffer是一个COM对象,接口使用完毕之后必须将其释放,以防内存泄露。
2)XFile材质
现实中的一个几何体有几何信息,也有材质等信息。这也就是说XFile中也必然包含这些信息。上面的D3DXLoadMeshFromX函数的参数中,有描述几何信息的邻接信息的参数,当然还有材质信息的ppMaterials的参数。然而,材质信息是被存储在一个被称作D3DXMATERIAL类型的结构数组中。值得一提的是,D3DXMATERIAL结构数组的第i项与第i个子集(子集就是一系列用相同绘制属性绘制三角形图元的组合,在上一章中有讲述)相对应,绘制时候循环遍历即可。该结构定义如下:
typedef struct D3DXMATERIAL{ D3DMATERIAL9 MatD3D; LPSTR pTextureFilename; } D3DXMATERIAL;
其中,字符串指针pTextureFilename指定了与网格相关的纹理文件名。需要说明的是,XFile文件中并未存储纹理数据,它只包含了纹理图像文件名,该文件名是对包含了实际纹理数据的纹理图像的引用。当用函数D3DXLoadMeshFromX加载XFile文件之后需要根据指定的纹理文件名加载纹理数据。
2. 渐进网格
首先,我们需要明白为什么需要渐进网格这个东西。在游戏中,我们绘制的场景中是尽可能地模拟现实世界的一切。自然地,所有物体对于观察者都会有远景之分。当你距离某物体很远时,你看到的就会比较模糊,而这种模糊和粗糙在Direct3D中就是通过减少物体的面元个数来实现的。事实上,这也是必须的。对于一个大型游戏而言,如果所有的物体都按照最原始的网格面片个数来绘制的,那么这样做的话是和游戏对速度的要求是矛盾的。渐进网格就是在这样的情况下应运而生的。
废话就不多了,我们来了解一下渐进网格的具体用法。渐进网格类似于多级渐进纹理。在代码中我们用ID3DXPMesh接口来使用渐进纹理。
1)生成渐进网格
和前面一样,我们需要先弄出个具体的ID3DXPMesh对象并用对应的信息填充。在Direct3D中,我们用如下函数创建ID3DXPMesh对象。
HRESULT D3DXGeneratePMesh( LPD3DXMESH pMesh, // 渐进网格信息根据这个网格信息产生 CONST DWORD *pAdjacency, //pMesh的邻接信息 CONST D3DXATTRIBUTEWEIGHTS *pVertexAttributeWeights, //解释如下 CONST FLOAT *pVertexWeights, //顶点权值 DWORD MinValue, //网格中的顶点数或面片数可被简化的下限 DWORD Options, LPD3DXPMESH *ppPMesh //输出的渐进网格 );
2)顶点属性权值
在前面学习顶点我们知道,我们定义的顶点结构体都有自己的属性,这些属性包括了顶点的位置、颜色等等。渐进网格就是要根据实际情况来移除一些不必要的顶点。这样说来,到底应该移除顶点呢?计算机并不是我们想象中那么智能,相反,他是很笨,聪明的是人。我们需要为顶点每一个可能的分量指定一个权值,以指定它被移除的概率大小。权值越大,被移除的概率越大。在代码中,我们用一个唤作D3DXATTRIBUTEWEIRHTS的结构体来描述顶点属性权值。该结构定义如下:
typedef struct D3DXATTRIBUTEWEIGHTS{ FLOAT Position; FLOAT Boundary; FLOAT Normal; FLOAT Diffuse; FLOAT Specular; FLOAT Texcoord[8]; FLOAT Tangent; FLOAT Binormal; } D3DXATTRIBUTEWEIGHTS,*LPD3DXATTRIBUTEWEIGHTS;
在Direct3D中,D3DXATTRIBUTEWEIGHTS都有默认值,如下。一般情况,除非特别需要,一般使用默认值。
D3DXATTRIBUTEWEIGHTS AttributeWeights; AttributeWeights.Position = 1.0; AttributeWeights.Boundary = 1.0; AttributeWeights.Normal = 1.0; AttributeWeights.Diffuse = 0.0; AttributeWeights.Specular = 0.0; AttributeWeights.Tex[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,};
关于渐进网格的学习就到这里了。兴许这个时候对渐进网格的感觉还是很模糊,这个是正常的。我们下面的学习还会再接触渐进网格。
理论的学习是枯燥的,大家加油,共勉!
本章完~
——Josh 2012年12月10日
相关文章推荐
- 【阅读笔记之十三】《DIRECTX.9.0.3D游戏开发编程基础》 网格(三)加载小汽车的XFile的demo
- 【阅读笔记之十一】《DIRECTX.9.0.3D游戏开发编程基础》:网格(一)闲话ID3DXMesh接口
- 【阅读笔记之八】《DIRECTX.9.0.3D游戏开发编程基础》:Direct3D中的纹理与映射
- 【阅读笔记之九】《DIRECTX.9.0.3D游戏开发编程基础》:Direct3D中的融合技术
- 【阅读笔记之一】《DIRECTX.9.0.3D游戏开发编程基础》:DirectX概略
- 【阅读笔记之五】《DIRECTX.9.0.3D游戏开发编程基础》Direct3D中的绘制
- 【阅读笔记之七】《DIRECTX.9.0.3D游戏开发编程基础》:Direct3D中的光照
- 【阅读笔记之三】《DIRECTX.9.0.3D游戏开发编程基础》:Direct3D初始化
- 【阅读笔记之十】《DIRECTX.9.0.3D游戏开发编程基础》:Direc3D中的字体
- 【阅读笔记之六】《DIRECTX.9.0.3D游戏开发编程基础》:Direct3D中的颜色
- 【阅读笔记之二】《DIRECTX.9.0.3D游戏开发编程基础》:基础数学知识
- 【阅读笔记之四】《DIRECTX.9.0.3D游戏开发编程基础》绘制流水线
- 【Visual C++】游戏开发笔记四十四 浅墨DirectX教程十二 网格模型和X文件使用面面观
- 【Visual C++】游戏开发笔记四十四 浅墨DirectX教程十二 网格模型和X文件使用面面观
- 【Visual C++】游戏开发笔记四十四 浅墨DirectX教程十二 网格模型和X文件使用面面观
- 【Visual C++】游戏开发笔记四十四 浅墨DirectX教程十二 网格模型和X文件使用面面观
- 关于阅读《DIRECTX.9.0.3D游戏开发编程基础》的计划
- 【图形学与游戏编程】开发笔记-基础篇7:纹理映射
- Cocos2d-x手机游戏开发C编程基础---笔记一
- 【图形学与游戏编程】开发笔记-入门篇2:一些需要的基础知识