【阅读笔记之十二】《DIRECTX.9.0.3D游戏开发编程基础》:网格(二)浅话X文件和渐进网格

网格(二)

 

       这里我们学习的关于网格部分是以上一章内容为基础的,这里给出链接:   http://blog.csdn.net/chenwu_843402773/article/details/8238314

 

     在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日



 


 

        

 

         

       

     

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值