模型基础

来源:互联网 发布:首金网官网下载软件 编辑:程序博客网 时间:2024/05/29 16:55
ID3DXMesh接口基础 
几何信息的获取 
//获取顶点缓冲
HRESULT 
ID3DXMesh::GetVertexBuffer(LPDIRECT3DVERTEXBUFFER9* ppVB); 
//获取索引缓冲 
HRESULT   ID3DXMesh::GetIndexBuffer(LPDIRECT3DVERTEXBUFFER9* 
ppVB); 
例: 
//获取顶点缓冲,获取索引缓冲 
LPD3DXMESH  Mesh; 
IDirect3DvertexBuffer9* pVB = NULL; 
IDirect3DvertexBuffer9* pIB = NULL; 
Mesh-> GetVertexBuffer(&pVB); 
Mesh-> GetVertexBuffer(&pIB); 
填充顶点与索引缓冲 
HRESULT  ID3DXMesh::LockVertexBuffer( 
DWORD   Flags,         //加锁的方式 
LPVOID*   ppData           //返回被锁定的顶点缓冲区指针 
HRESULT  ID3DXMesh::LockIndexBuffer( 
DWORD   Flags,         //加锁的方式 
LPVOID*   ppData           //返回被锁定的顶点缓冲区指针 
HRESULT  ID3DXMesh::UnlockVertexBuffer();          //解锁的方式 
HRESULT  ID3DXMesh::UnlockIndexBuffer();           //解锁的方式 
//与Mesh的几何结构有关的ID3DXMesh接口的方法: 
DWORD  GetFVF()                 -------返回顶点的格式 
DWORD  GetNumVertices()           --------返回顶点缓冲中的顶点数 
DWORD  GetNumBytesPerVertex()      --------返回一个顶点所占的字节数 
DWORD  GetNumFaces()             --------返回Mesh的面数,也就是三角形数 
子集与属性缓冲 
一个Mesh由数个子集组成,子集是Mesh中的一组使用相同属性渲染的三角形,这里 
的属性指的是材质,纹理,渲染状态。每一个子集使用唯一的非负整数表示其ID; 
获取属性缓冲 
DWORD* buffer   =  NULL; 
                                     
Mesh->LockAttributeBuffer(lockingFlags,&buffer); 
//对属性缓冲区进行操作 
Mesh->UnlockAttributeBuffer(); 
渲染 
HRESULT  DrawSubset( 
DWORD   AttribId   //属性ID指示Mesh中的子集,按照子集的ID渲染哪 
个图形 
); 
例: 
1.Mesh->DrawSubset(0); 
2.for(int  i  =0;i<numSubsets;i++) 
Device->SetMaterial(mtrls[i]); 
Device->SetTexture(0,textures[i]); 
Mesh->DrawSubset(i); 
}
================================================================= 
============== 
DirectX 
================================================================= 
============== 
ID3DXMesh接口相关 
       
优化Mesh 
HRESULT  OptimizeInplace( 
DWORD  Flags,                         //执行优化的类型 
CONSTDWORD *pAdjacencyIn,            //没有优化的Mesh的临接数组 
DWORD  *pAdjacencyOut,                //输出优化的Mesh的临接数组 
DWORD  *pFaceRemap,           //接受面重射信息 
LPD3DXBUFFER  *ppVertexRemap          //返回顶点重影射信息 
); 
参数Flags可取值以下一值或几种值的组合: 
D3DXMESHOPT_COMPACT                  //删除没有用的顶点和索引项 
D3DXMESHOPT_ATTRSORT         //根据属性给三角形排列顺序并调整属性表,这将使 
DrawSubset方法更有效的执行 
D3DXMESHOPT_VERTEXCACHE              //增加顶点缓冲的命中率 
D3DXMESHOPT_STRIPREORDER     //重组顶点索引使三角形带尽量长 
D3DXMESHOPT_IGNOREVERTS              //只优化索引,忽略顶点 
注意:       D3DXMESHOPT_VERTEXCACHE和D3DXMESHOPT_STRIPREORDER不能同时使用; 
下面是对一个网格进行优化的片段 
DWORD  adjacencyInfo[Mesh->GetNumFaces()*3]; 
Mesh->GenerateAdjacency(0.0f,adjacencyInfo); 
//用于保存优化的Mesh的数组 
DWORD   optimizedAdjacencyInfo[Mesh->GetNumFaces()*3]; 
                                     
Mesh->OptimizeInplace( 
D3DXMESHOPT_ATTRSORT| 
D3DXMESHOPT_COMPACT| 
D3DXMESHOPT_VERTEXCACHE, 
adjacencyInfo, 
optimizedAdjacencyInfo, 
0
0); 
还有一种方法是输出一个优化后的Mesh而不是在原来的基础上修改; 
HRESULT  Optimize( 
DWORD  Flags,                         //执行优化的类型 
CONSTDWORD *pAdjacencyIn,           //没有优化的MESH临近数组 
DWORD  *pAdjacencyOut,                //输出优化的MESH临近数组 
DWORD  *pFaceRemap,          //接受面重射信息 
LPD3DXBUFFER  *ppVertexRemap,         //返回顶点重影射信息 
LPD3DXMESH  *ppOptMesh                //返回新的网格 
); 
属性表 
如果一个 MESH 使用 D3DXMESHOPT_ATTRSORT 进行优化,那么将创建一个 
D3DXATTRIBUTERANGE结构的属性表数组: 
typedef  struct _D3DXATTRIBUTERANGE
DWORD  AttribId;       //子集的ID 
DWORD  FaceStart;      //该自己的面的起始值 
// FaceStart*3就是起始三角形在索引缓冲的序号 
DWORD  FaceCount;      //子集的面数,也就是三角形数 
DWORD  VertexStart;  //该子集的起始顶点在顶点缓冲中的序号 
DWORD  VertexCount;  //该子集包含的顶点数 
}D3DXATTRIBUTERANGE; 
访问MESH的属性表 
HRESULT  GetAttributeTable( 
D3DXATTRIBUTERANGE  *pAttribTable,//获取属性表的指针 
DWORD  *pAttribTableSize                       //属性表的大小,即属性的数量 
); 
此方法可以完成两个功能:返回属性表的属性数,返回完整的属性表返回属性表的元素个数: 
DWORD  num  = 0
Mesh->GetAttributeTable(0,&num);         //要得到属性表的元素个数可以给第一个参 
数传NULL 
然后就可以得到属性表了 
D3DXATTRIBUTERANGE table = new D3DXATTRIBUTERANGE[num]; 
Mesh-> GetAttributeTable(table,&num); 
还可以使用ID3DXMesh::SetAttribute Table方法直接修改属性表。 
                                    
D3DXATTRIBUTERANGE attributeTable[12]; 
//填充属性表的值 
Mesh->SetAttributeTable(attributeTable,12); 
================================================================= 
============== 
.X 
应用..XX文件 
1.提取多边形网格信息: 
HRESULT  WINAPI D3DXLoadMeshFromX( 
LPCTSTR  pFilename,                   //X文件路径和文件名 
DWORD  Options,                       //指定生成多边形网格属性 
LPDIRECT3DDEVICE9  pD3DDevice,        //D3D设备指针 
LPD3DXBUFFER  *ppAdjacency,           //存储多边形临接信息 
LPD3DXBUFFER  *ppMaterials,           //存储材质的内存地址 
LPD3DXBUFFER  *ppEffectInstances,     //存储模型特殊效果的内存地址 
DWORD  *pNumMaterials,                //存储材质数目的内存指针 
LPD3DXMESH  *ppMesh           //存储生成的多边形网格的内存地址 
); 
下面函数片段从名为game.x的文件里读取3D模型: 
if(FAILED(D3DXLoadMeshFromX(L"game.x",         //X文件名 
D3DXMESH_MANAGED,  //保存在系统管理内存中 
g_pd3dDevice,          //D3D设备 
NULL,                         / /无需返回临接信息 
&pD3DXMtrlBuffer,//返回材质信息 
NULL,                        //无需返回 
&g_dwNumMaterials,//返回材质的数目,即MESH的子集 
&g_pMesh         //返回的MESH接口对象 
) ) ) 
MessageBox(NULL,L"Couldnot findgame.x",L"Mesh",MB_OK); 
returnE_FAIL; 
}
2.ID3DXBuffer 接口:
GetBufferPointer();//返回指向数据块首地址的指针 
GetBufferSize(); //返回数据块中的大小 
      
注意:ID3DXBuffer 指向的数据块本身是没有数据类型的,所以需要强制转换, 同时 
ID3DXBuffer本身也是一个COM对象,所以使用完之后需要调用Release方法释放. 
例如: 
D3DXMATERIAL*d3dxMaterials=  (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer(); 
pD3DXMtrlBuffer->Release(); 
3.载入纹理和材质: 
                                   
typedef  struct D3DXMATERIAL
D3DMATERIAL9  MatD3D;           //物体的材质信息 
LPSTR  pTextureFilename;        //物体的纹理文件名称 
}D3DXMATERIAL; 
下面程序片断用于获取3D模型的材质和纹理信息: 
//从材质集合中把材质和纹理信息解压读取出来 
D3DXMATERIAL*d3dxMaterials=  (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer(); 
g_pMeshMaterials= newD3DMATERIAL9[g_dwNumMaterials]; 
g_pMeshTextures = newLPDIRECT3DTEXTURE9[g_dwNumMaterials]; 
注意:函数D3DXLoadMeshFromX调用成功后返回的是一个材质结构体数组,第i个材质信息 
对应的第i个网格模型的子集,因此可以使用简单的循环来对整个网格进行渲染; 
for(DWORDi=0;  i<g_dwNumMaterials;i++ ) 
//拷贝材质 
g_pMeshMaterials[i]= d3dxMaterials[i].MatD3D; 
//设置材质漫反射的颜色 
g_pMeshMaterials[i].Ambient=  g_pMeshMaterials[i].Diffuse; 
//创建纹理 
if(FAILED(D3DXCreateTextureFromFile(g_pd3dDevice, 
d3dxMaterials[i].pTextureFilename,& g_pMeshTextures[i]))) 
g_pMeshTextures[i]=NULL; 
}
//释放材质缓冲区的内容; 
pD3DXMtrlBuffer->Release(); 
4.绘制网格模型 
下面代码片断就是一个网格模型的渲染函数: 
//逐块渲染网格模型 
for(  DWORDi=0;i<g_dwNumMaterials;i++ ) 
//设置材料和纹理 
g_pd3dDevice->SetMaterial(&g_pMeshMaterials[i]); 
g_pd3dDevice->SetTexture(0, g_pMeshTextures[i]); 
//渲染模型 
g_pMesh->DrawSubset(i ); 
}
================================================================= 
原创粉丝点击