【Directx3D游戏开发】——网格模型(mesh .x)

这次的笔记包含两个内容:1:简单介绍网格模型 和 .x文件;2、优化Mesh模型已取得更高的渲染效率,用Direct3D去加载一个.X文件。


游戏中的场景和角色都非常复杂,想要手工去填充这些模型的每一个顶点几乎是个不可能的事情。一般是用建模工具去完成,然后导出一个程序可以识别的网格模型。最常用的是3DMax,和Maya。

1:.X模型

X格式是微软提供的一种开放的数据存储格式。.X支持自定义模版结构,可以通过它存储自己的任何一种数据,并不一定使我们的模型数据。当然现在要讨论的是.X格式在Direct3D的应用,DirectX的D3DX库提供丰富的支持函数,使得用户可以轻松的使用.X文件。并且.X文件还支持动画。DirectX Viewer 是一个.X文件的查看器,用于查看模型:

【Directx3D游戏开发】——网格模型(mesh .x)_第1张图片

 唔之艾瑞莉娅:艾欧尼亚不会灭亡。

.X文件可以用文本格式存储,可以用记事本打开一看究竟,详细参考《Direct3D 游戏看法详解 》,同样可以采用二进制格式存储,并支持自定义文件结构。

2:D3DX库中一些相关接口

a)、ID3DXMesh 派生自ID3DXBaseMesh,包含了网格(Mesh)模型的集合信息,顶点缓存和索引缓存(描述顶点以何种方式组织成三角形)。相关函数:

	//获得顶点缓冲区和索引缓冲区的指针
	HRESULT ID3DXMesh::GetVertexBuffer( LPDIRECT3DVERTEXBUFFER* ppVB ); 
	HRESULT ID3DXMesh::GetIndexBuffer( LPDIRECT3DVERTEXBUFFER* ppVB );
	//锁定缓冲区,一遍进行读写操作
	HRESULT ID3DXMesh::LockVertexBuffer( DWORD Flags, BYTE** ppData );
	HRESULT ID3DXMesh::LockIndexBuffer( DWORD Flags, BYTE** ppData );
	//完成了相应操作,必须解锁
	HRESULT ID3DXMesh::UnlockVertexBuffer();
	HRESULT ID3DXMesh::UnlockIndexBuffer();

	//更多获取几何信息的方法
	DWORD GetFVF(); //返回顶点格式
	DWORD GetNumVertices() //返回顶点缓存中的定点数
	DWORD GetNumBytesPerVertex(); //返回每个顶点所占的字节数
	DWORD GetNumFaces(); //返回网格中(三角形)片面的个数。

3、网格(Mesh)结构

一个网格由一个或多个子集组成。一个子集是网格中一组可用相同属性进行绘制的三角形单元。实行指的是材质,纹理,绘制状态。

为了区分不同子集,给每个子集分配了不同的DWORD类型的ID.这些ID被存放在一个DWORD数组里面,也就是属性缓存。属性缓存的第i行与索引缓存中的第i个三角形单元。

【Directx3D游戏开发】——网格模型(mesh .x)_第2张图片

访问索引缓存的接口:

DWORD* buffer = NULL;
Mesh->LockAttributeBuffer( lockFlags, &buffer );//读写操作Mesh->UnlockAttributeBuffer();
 
  

4、绘制整个网格(mesh)模型

只需要简单的去遍历绘制每一个子集:DrawSubset( i );

	for(int i = 0; i < numSubsets;i++)
	{
		//设置材质纹理
		Device->SetMaterial( Mtrl[i] );
		Device->SetTexture( 0, textuer[i] );
		Mesh->DrawSubset( i );
	}

5、优化:为了可以更加高效的绘制一个网格,需要对网格中的顶点和索引进行重组。有两个有优化函数,只有微小的区别。

	HRESULT ID3DXMesh::OptimizeInplace
	(
	DWORD Flags, 
	CONST DWORD* pAdjacencyIn,
	DWORD* pAdjacencyOut,
	DWORD* pFaceRemap,
	LPD3DXBUFFER* ppVertexRemap
	);
	HRESULT ID3DXMesh::Optimize(
	DWORD Flags, 
	CONST DWORD* pAdjacencyIn,
	DWORD* pAdjacencyOut,
	DWORD* pFaceRemap,
	LPD3DXBUFFER* ppVertexRemap
	LPD3DXMESH* ppOptMesh
	);

 
  

从其中的函数名也可以知道它们之间的差别,OptimizeInplace()就在原Mesh模型上优化,Optimize()是输出一个新的模型,源模型并不会改变。

Flag:优化选项,可以是以下常量的组合

D3DXMESHOPT_COMPACT:从网格中移除那些无用的顶点和索引。

D3DXMESHOPT_ATTSORT:依据属性对个三角形进行排序,并生成一个属性表。这样可使DrawSubset更有效率

D3DXMESHOPT_VERTEXCACHE:提供顶点高速缓存的命中率

D3DXMESHOPT_STRIPORDER:对索引进行重组,以使三角形单元链尽可能长

D3DXMESHOPT_IGNOREVERTS:仅对索引进行优化,忽略顶点。

其中D3DXMESHOPT_VERTEXCACHE不能与D3DXMESHOPT_STRIPORDER同时使用。

pAdjacencyIn:输入的未经优化的链接数组指针

pAdjacencyOut:输出的优化后的链接数组指针,大小为ID3DXMesh::GetNumFaces()*3

6、关于IDXBuffer

这是一个COM接口,一种泛型的数据结构,作用是将数据存储在一个连续的内存块中。相关的两个方法:

LPVOID GetBufferPointer(); 返回缓存中的数据起始指针,需要进行指针类型转换。

DWORD GetBufferSize();返回缓存大小,单位为字节。

7、加载Mesh模型(.x文件)四步曲:

一、重文件中加载数据:

//从文件中加载Mesh模型
	hr = D3DXLoadMeshFromX( XFILE_NAME, D3DXMESH_MANAGED, g_pD3DDevice,
							&pAdjacentBuffer, &pMaterialBuffer,
							0, &numMaterials, &g_pMesh );
二、读取模型材质,纹理信息:

if( pMaterialBuffer != NULL && numMaterials != NULL )
	{
		//获取缓冲区地址
		D3DXMATERIAL* pMaterials = ( D3DXMATERIAL* )pMaterialBuffer->GetBufferPointer();

		//复制材质,和加载纹理
		for(DWORD i = 0;i < numMaterials; i++)
		{
			pMaterials[i].MatD3D.Ambient = pMaterials[i].MatD3D.Diffuse;

			//复制材质用于Render()
			materials.push_back( pMaterials[i].MatD3D );

			//从文件中加载纹理
			if( pMaterials[i].pTextureFilename != NULL)
			{
				IDirect3DTexture9* tex = NULL;
				hr = D3DXCreateTextureFromFileA( g_pD3DDevice, 
												pMaterials[i].pTextureFilename,
												&tex );
				if( FAILED( hr ) )
				{
					MessageBox( 0, L"D3DXCreateTextureFromFile() - FAILED ", 0, MB_OK );
					return E_FAIL;
				}

				textures.push_back( tex );
			}
			else
			{
				//没有材质
				textures.push_back( NULL );
			}
		}
	}

三、优化网格:

//优化Mesh
	hr = g_pMesh->OptimizeInplace(
					D3DXMESHOPT_ATTRSORT |
					D3DXMESHOPT_COMPACT |
					D3DXMESHOPT_VERTEXCACHE,
					(DWORD*)pAdjacentBuffer->GetBufferPointer(),
					0, 0, 0 );

四、设置相关变换(代码略)


这里!!!完整代码


圣斗士也有倒下的时候


但至少他为我们制造了无数经典的回忆


——致科比布莱恩特,希望早日回归

【Directx3D游戏开发】——网格模型(mesh .x)_第3张图片

你可能感兴趣的:(Game,Programing,——Direct3D游戏开发)