模型基础

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,                          //执行优化的类型 
CONST DWORD *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,                          //执行优化的类型 
CONST DWORD *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 ); 
}
================================================================= 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值