Loading an .X File导入.X格式的文件
这个是微软格式的模型文件。存储各种任务,树木,花草等模型信息的文件,可以导入并显示与程序屏幕中,导入函数:
HRESULT D3DXLoadMeshFromX(
LPCSTR pFilename,
DWORD Options,
LPDIRECT3DDEVICE9 pDevice,
LPD3DXBUFFER *ppAdjacency,
LPD3DXBUFFER *ppMaterials,
LPD3DXBUFFER* ppEffectInstances,
PDWORD pNumMaterials,
LPD3DXMESH *ppMesh
);
例子:
// Step 1: Load the .X file from file into a system memory mesh.
ID3DXMesh* meshSys = 0;
ID3DXBuffer* adjBuffer = 0;
ID3DXBuffer* mtrlBuffer = 0;
DWORD numMtrls = 0;
HR(D3DXLoadMeshFromX(filename.c_str(), D3DXMESH_SYSTEMMEM,
gd3dDevice, &adjBuffer, &mtrlBuffer, 0, &numMtrls, &meshSys));
测试顶点单位法向量 Vertex Normals
当一个.X 文件导入之后,ID3DXMesh的顶点属性一定有位置,但是不一定有单位向量,纹理坐标,我们可以手动地添加这些信息。可以colone到一个新的ID3DXMesh中,指定格式为我们想要的格式,就可以添加相应的属性了。
也可以把拥有不同属性的.x文件统一格式化成有相同格式属性的Mesh,然后统一渲染,可以加快渲染速度。
如下面代码检查是否有单位化向量,没有就才加,以免覆盖:
// Step 2: Find out if the mesh already has normal info.
D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
HR(meshSys->GetDeclaration(elems));
bool hasNormals = false;
for(int i = 0; i < MAX_FVF_DECL_SIZE; ++i)
{
// Did we reach D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED, 0,0,0}?
if(elems[i].Stream == 0xff)
break;
if( elems[i].Type == D3DDECLTYPE_FLOAT3 &&
elems[i].Usage == D3DDECLUSAGE_NORMAL &&//如果我们找到一个3D顶点有normal usage
elems[i].UsageIndex == 0 )//且其索引为0,那么就可以判定单位化向量存在。
{
hasNormals = true;
break;
}
}
该表顶点格式
colone mesh,然后格式化为VertexPNT (position, normal, 2D texture coordinates) 格式,就可以采用我们自己写的shader来处理,当然这个shader是自己写的,格式也随自己需要而定。例如:
// Step 3: Change vertex format to VertexPNT.
D3DVERTEXELEMENT9 elements[64];
UINT numElements = 0;
VertexPNT::Decl->GetDeclaration(elements, &numElements);
ID3DXMesh* temp = 0;
HR(meshSys->CloneMesh(D3DXMESH_SYSTEMMEM,//这里一个函数就可以clone并格式化,非常方便,就是不太好理解。
elements, gd3dDevice, &temp));
ReleaseCOM(meshSys);
meshSys = temp;
创造单位法向量信息Generating Normals
函数自动为新的增加的信息增加空间的,所以也不用我们自己管理其内存。:
// Step 4: If the mesh did not have normals, generate them.
if( hasNormals == false)
HR(D3DXComputeNormals(meshSys, 0));//自动计算新的单位化信息
的函数
第二个参数可以为零,是输入mesh的邻接矩阵的信息。
优化Optimizing
可以提高渲染速度.
// Step 5: Optimize the mesh.
HR(meshSys->Optimize(D3DXMESH_MANAGED | D3DXMESHOPT_COMPACT |//一个优化函数就搞定了
D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
(DWORD*)adjBuffer->GetBufferPointer(), 0, 0, 0, meshOut));
ReleaseCOM(meshSys); // Done w/ system mesh.
ReleaseCOM(adjBuffer); // Done with buffer.
X 文件材质
D3DXLoadMeshFromX第七个参数是包含在mesh中的材质数量,第五个参数是一个D3DXMATERIAL数组:
typedef struct D3DXMATERIAL {
D3DMATERIAL9 MatD3D;//各种材质,如下结构体
LPSTR pTextureFilename;//自己指定的指向需要文件纹理图像
} D3DXMATERIAL;
typedef struct _D3DMATERIAL9 {
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Ambient;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Emissive;//自发射光
float Power;
} D3DMATERIAL9;
.x文件的可以通过循环子网subset来渲染。
如下面例子:
void LoadXFile(
const std::string& filename,
ID3DXMesh** meshOut,
std::vector<Mtrl>& mtrls,
std::vector<IDirect3DTexture9*>& texs);
设置材质和纹理:
// Step 6: Extract the materials and load the textures.
if( mtrlBuffer != 0 && numMtrls != 0 )
{
D3DXMATERIAL* d3dxmtrls =
(D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();
for(DWORD i = 0; i < numMtrls; ++i)
{
// Save the ith material. Note that the MatD3D property
// does not have an ambient value set when it's loaded, so
// just set it to the diffuse value.
Mtrl m;
m.ambient = d3dxmtrls[i].MatD3D.Diffuse;
m.diffuse = d3dxmtrls[i].MatD3D.Diffuse;
m.spec = d3dxmtrls[i].MatD3D.Specular;
m.specPower = d3dxmtrls[i].MatD3D.Power;
mtrls.push_back( m );
// Check if the ith material has an associative texture
if( d3dxmtrls[i].pTextureFilename != 0 )
{
// Yes, load the texture for the ith subset
IDirect3DTexture9* tex = 0;
char* texFN = d3dxmtrls[i].pTextureFilename;
HR(D3DXCreateTextureFromFile(gd3dDevice,
texFN, &tex));
// Save the loaded texture
texs.push_back( tex );
}
else
{
// No texture for the ith subset
texs.push_back( 0 );
}
}
}
ReleaseCOM(mtrlBuffer); // done w/ buffer
渲染:
// Application data members.
ID3DXMesh* mMesh;
std::vector<Mtrl> mMtrl;
std::vector<IDirect3DTexture9*> mTex;
// In application constructor:
LoadXFile("skullocc.x", &mMesh, mMtrl, mTex);
// Rendering code:
HR(mFX->BeginPass(0));
for(int j = 0; j < mMtrl.size(); ++j)
{
HR(mFX->SetValue(mhMtrl, &mMtrl[j], sizeof(Mtrl)));
// If there is a texture, then use.
if(mTex[j] != 0)
{
HR(mFX->SetTexture(mhTex, mTex[j]));
}
// But if not, then set a pure white texture.
else
{
HR(mFX->SetTexture(mhTex, mWhiteTex));
}
HR(mFX->CommitChanges());
HR(mMesh->DrawSubset(j));
}
HR(mFX->EndPass());
清理代码:
ReleaseCOM(mMesh);
for(int i = 0; i < mTex.size(); ++i)
ReleaseCOM(mTex[i]);
本文介绍了如何使用D3DXLoadMeshFromX函数加载.X模型文件,并详细解释了如何检查和生成顶点单位法向量,优化网格以提高渲染效率,以及如何从.X文件中提取材质和纹理。
3718

被折叠的 条评论
为什么被折叠?



