// Load the mesh.
ID3DXBuffer *materialBuffer, *adjacencyBuffer;
D3DXLoadMeshFromX( GetFilename(), D3DXMESH_MANAGED, g_engine->GetDevice(), &adjacencyBuffer, &materialBuffer, NULL, &m_staticMesh->NumMaterials, &tempMesh );
// Get the vertex declaration for the NMapVertex.
D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
UINT numElems = 0;
NMapVertex::Decl->GetDeclaration(elems, &numElems);
// Clone the mesh to the NMapVertex format.
ID3DXMesh* clonedTempMesh = 0;
tempMesh->CloneMesh(D3DXMESH_MANAGED, elems, g_engine->GetDevice(), &clonedTempMesh);
// Now use D3DXComputeTangentFrameEx to build the TNB-basis for each vertex
// in the mesh.
D3DXComputeTangentFrameEx(
clonedTempMesh, // Input mesh
D3DDECLUSAGE_TEXCOORD, 0, // Vertex element of input tex-coords.
D3DDECLUSAGE_BINORMAL, 0, // Vertex element to output binormal.
D3DDECLUSAGE_TANGENT, 0, // Vertex element to output tangent.
D3DDECLUSAGE_NORMAL, 0, // Vertex element to output normal.
0, // Options
0, // Adjacency
0.01f, 0.25f, 0.01f, // Thresholds for handling errors
m_staticMesh->originalMesh, // Output mesh
0); // Vertex Remapping
SAFE_RELEASE( tempMesh );
SAFE_RELEASE( clonedTempMesh );
// Optimise the mesh for better rendering performance.
m_staticMesh->originalMesh->OptimizeInplace( D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)adjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL );
struct NMapVertex
{
D3DXVECTOR3 pos;
D3DXVECTOR3 tangent;
D3DXVECTOR3 binormal;
D3DXVECTOR3 normal;
D3DXVECTOR2 tex0;
static IDirect3DVertexDeclaration9* Decl;
};