void Model::CreateFromSDKMeshFile(ID3D11Device* device, LPCWSTR fileName) { _ASSERT(FileExists(fileName)); // Use the SDKMesh class to load in the data SDKMesh sdkMesh; sdkMesh.Create(fileName); wstring directory = GetDirectoryFromFileName(fileName); // Make materials UINT numMaterials = sdkMesh.GetNumMaterials(); for (UINT i = 0; i < numMaterials; ++i) { MeshMaterial material; SDKMESH_MATERIAL* mat = sdkMesh.GetMaterial(i); memcpy(&material.AmbientAlbedo, &mat->Ambient, sizeof(D3DXVECTOR4)); memcpy(&material.DiffuseAlbedo, &mat->Diffuse, sizeof(D3DXVECTOR4)); memcpy(&material.SpecularAlbedo, &mat->Specular, sizeof(D3DXVECTOR4)); memcpy(&material.Emissive, &mat->Emissive, sizeof(D3DXVECTOR4)); material.Alpha = mat->Diffuse.w; material.SpecularPower = mat->Power; material.DiffuseMapName = AnsiToWString(mat->DiffuseTexture); material.NormalMapName = AnsiToWString(mat->NormalTexture); LoadMaterialResources(material, directory, device); meshMaterials.push_back(material); } // Make a D3D9 device IDirect3DDevice9Ptr d3d9Device = CreateD3D9Device(); UINT numMeshes = sdkMesh.GetNumMeshes(); for (UINT meshIdx = 0; meshIdx < numMeshes; ++meshIdx) { // Figure out the index type UINT ops = D3DXMESH_MANAGED; UINT indexSize = 2; Mesh::IndexType indexType = Mesh::Index16Bit; if (sdkMesh.GetIndexType(meshIdx) == IT_32BIT) { ops |= D3DXMESH_32BIT; indexSize = 4; indexType = Mesh::Index32Bit; } // Make a D3DX mesh ID3DXMesh* d3dxMesh = NULL; UINT numPrims = static_cast<UINT>(sdkMesh.GetNumIndices(meshIdx) / 3); UINT numVerts = static_cast<UINT>(sdkMesh.GetNumVertices(meshIdx, 0)); UINT vbIndex = sdkMesh.GetMesh(meshIdx)->VertexBuffers[0]; UINT ibIndex = sdkMesh.GetMesh(meshIdx)->IndexBuffer; const D3DVERTEXELEMENT9* vbElements = sdkMesh.VBElements(vbIndex); DXCall(D3DXCreateMesh(numPrims, numVerts, ops, vbElements, d3d9Device, &d3dxMesh)); IUnknownReleaser<ID3DXMesh> meshReleaser(d3dxMesh); // Copy in vertex data BYTE* verts = NULL; BYTE* srcVerts = reinterpret_cast<BYTE*>(sdkMesh.GetRawVerticesAt(vbIndex)); UINT vbStride = sdkMesh.GetVertexStride(meshIdx, 0); UINT declStride = D3DXGetDeclVertexSize(vbElements, 0); DXCall(d3dxMesh->LockVertexBuffer(0, reinterpret_cast<void**>(&verts))); for (UINT vertIdx = 0; vertIdx < numVerts; ++vertIdx) { memcpy(verts, srcVerts, declStride); verts += declStride; srcVerts += vbStride; } DXCall(d3dxMesh->UnlockVertexBuffer()); // Copy in index data void* indices = NULL; void* srcIndices = sdkMesh.GetRawIndicesAt(ibIndex); DXCall(d3dxMesh->LockIndexBuffer(0, &indices)); memcpy(indices, srcIndices, numPrims * 3 * indexSize); DXCall(d3dxMesh->UnlockIndexBuffer()); // Set up the attribute table DWORD* attributeBuffer = NULL; DXCall(d3dxMesh->LockAttributeBuffer(0, &attributeBuffer)); UINT numSubsets = sdkMesh.GetNumSubsets(meshIdx); D3DXATTRIBUTERANGE* attributes = new D3DXATTRIBUTERANGE[numSubsets]; ArrayDeleter<D3DXATTRIBUTERANGE> attributeDeleter(attributes); for (UINT i = 0; i < numSubsets; ++i) { SDKMESH_SUBSET* subset = sdkMesh.GetSubset(meshIdx, i); attributes[i].AttribId = subset->MaterialID; attributes[i].FaceStart = static_cast<DWORD>(subset->IndexStart / 3); attributes[i].FaceCount = static_cast<DWORD>(subset->IndexCount / 3); attributes[i].VertexStart = static_cast<DWORD>(subset->VertexStart); // attributes[i].VertexCount = static_cast<DWORD>(subset->VertexCount); attributes[i].VertexCount = numVerts; for (UINT faceIdx = attributes[i].FaceStart; faceIdx < attributes[i].FaceStart + attributes[i].FaceCount; ++faceIdx) attributeBuffer[faceIdx] = subset->MaterialID; } DXCall(d3dxMesh->UnlockAttributeBuffer()); d3dxMesh->SetAttributeTable(attributes, numSubsets); // Generate initial adjacency vector<DWORD> initialAdjacency; initialAdjacency.resize(d3dxMesh->GetNumFaces() * 3); DXCall(d3dxMesh->GenerateAdjacency(0.0001f, &initialAdjacency[0])); // Make the mesh Mesh mesh; mesh.CreateFromD3DXMesh(directory, device, d3d9Device, d3dxMesh, false, false, &initialAdjacency[0], indexType); meshes.push_back(mesh); } }