HRESULT CXMesh::LoadFromXData(char* Filename, LPDIRECTXFILEDATA XObj) { HRESULT res = S_OK; CBRenderD3D* Rend = (CBRenderD3D*)Game->m_Renderer; // get name res = CXModel::LoadName(this, XObj); if(FAILED(res)) { Game->LOG(res, "Error loading mesh name"); return res; } // load mesh LPD3DXBUFFER BufMaterials = NULL; LPD3DXBUFFER BufAdjacency = NULL; LPD3DXBUFFER BufBoneOffset = NULL; UINT NumFaces; DWORD NumMaterials; #ifdef WME_D3D9 LPD3DXMESH Mesh; LPD3DXSKININFO SkinInfo; res = D3DXLoadSkinMeshFromXof(XObj, D3DXMESH_MANAGED, Rend->m_Device, &BufAdjacency, &BufMaterials, NULL, &NumMaterials, &SkinInfo, &Mesh); if(SUCCEEDED(res)) m_SkinMesh = new CSkinMeshHelper(Mesh, SkinInfo); #else LPD3DXBUFFER BufBoneNames = NULL; LPD3DXSKINMESH SkinMesh; res = D3DXLoadSkinMeshFromXof(XObj, D3DXMESH_MANAGED, Rend->m_Device, &BufAdjacency, &BufMaterials, &NumMaterials, &BufBoneNames, &BufBoneOffset, &SkinMesh); if(SUCCEEDED(res)) m_SkinMesh = new CSkinMeshHelper(SkinMesh, BufBoneOffset, BufBoneNames); #endif if(FAILED(res)) { Game->LOG(res, "Error loading skin mesh"); return res; } NumFaces = m_SkinMesh->GetNumFaces(); DWORD NumBones = m_SkinMesh->GetNumBones(); // Process skinning data if(NumBones) { // bones are available m_BoneMatrices = new D3DXMATRIX*[NumBones]; DWORD* Adjacency = (DWORD*)(BufAdjacency->GetBufferPointer()); m_SkinAdjacency = new DWORD[NumFaces * 3]; memcpy(m_SkinAdjacency, Adjacency, NumFaces * 3 * sizeof(DWORD)); GenerateMesh(); } else { // no bones are found, blend the mesh and use it as a static mesh m_SkinMesh->GetOriginalMesh(&m_StaticMesh); m_StaticMesh->CloneMeshFVF(m_StaticMesh->GetOptions(), m_StaticMesh->GetFVF(), Rend->m_Device, &m_BlendedMesh); SAFE_DELETE(m_SkinMesh); m_NumAttrs = NumMaterials; if(m_BlendedMesh) { NumFaces = m_BlendedMesh->GetNumFaces(); m_Adjacency = new DWORD[NumFaces * 3]; m_BlendedMesh->GenerateAdjacency(0, m_Adjacency); } } // check for materials if((BufMaterials == NULL) || (NumMaterials == 0)) { // no materials are found, create default material C3DMaterial* Mat = new C3DMaterial(Game); Mat->m_Material.Diffuse.r = 0.5f; Mat->m_Material.Diffuse.g = 0.5f; Mat->m_Material.Diffuse.b = 0.5f; Mat->m_Material.Specular = Mat->m_Material.Diffuse; Mat->m_Material.Ambient = Mat->m_Material.Diffuse; m_Materials.Add(Mat); m_NumAttrs = 1; } else { // texture relative path base char PathTemp[MAX_PATH+1]; int PathLength; for (PathLength = strlen(Filename); PathLength--;) { if(Filename[PathLength] == '/' || Filename[PathLength] == '\\' ) { PathLength++; break; } } strncpy(PathTemp, Filename, PathLength); // load the materials D3DXMATERIAL* FileMats = (D3DXMATERIAL*)BufMaterials->GetBufferPointer(); for(int i = 0; i < (int)NumMaterials; i++) { C3DMaterial* Mat = new C3DMaterial(Game); Mat->m_Material = FileMats[i].MatD3D; Mat->m_Material.Ambient = Mat->m_Material.Diffuse; if(FileMats[i].pTextureFilename != NULL) { strcpy(PathTemp + PathLength, FileMats[i].pTextureFilename); Mat->SetTexture(PathTemp, true); } m_Materials.Add(Mat); } m_NumAttrs = m_Materials.GetSize(); } RELEASE(BufAdjacency); RELEASE(BufMaterials); RELEASE(BufBoneOffset); return S_OK; }
void cMesh::ParseXFileData(ID3DXFileData *pDataObj, sFrame *ParentFrame, char *TexturePath) { ID3DXFileData *pSubObj = NULL; ID3DXFileData *pSubData = NULL; IDirectXFileDataReference *pDataRef = NULL; GUID Type = GUID_NULL; char *Name = NULL; DWORD Size; sFrame *SubFrame = NULL; char Path[MAX_PATH]; sFrame *Frame = NULL; //D3DXMATRIX *FrameMatrix = NULL; sMesh *Mesh = NULL; ID3DXBuffer *MaterialBuffer = NULL; D3DXMATERIAL *Materials = NULL; ID3DXBuffer *Adjacency = NULL; DWORD *AdjacencyIn = NULL; DWORD *AdjacencyOut = NULL; DWORD i; BYTE **Ptr; // Get the template type if(FAILED(pDataObj->GetType((&Type)))) return; // Get the template name (if any) if(FAILED(pDataObj->GetName(NULL, &Size))) return; if(Size) { if((Name = new char[Size]) != NULL) pDataObj->GetName(Name, &Size); } // Give template a default name if none found if(Name == NULL) { if((Name = new char[9]) == NULL) return; strcpy(Name, "$NoName$"); } // Set sub frame SubFrame = ParentFrame; // Process the templates // Frame if(IsEqualGUID(Type, TID_D3DRMFrame)) { // Create a new frame structure Frame = new sFrame(); // Store the name Frame->m_Name = Name; Name = NULL; // Add to parent frame Frame->m_Parent = ParentFrame; Frame->m_Sibling = ParentFrame->m_Child; ParentFrame->m_Child = Frame; // Increase frame count m_NumFrames++; // Set sub frame parent SubFrame = Frame; } // Frame transformation matrix if(Type == TID_D3DRMFrameTransformMatrix) { BYTE** DataPtr = NULL; if(FAILED(pDataObj->Lock(&Size, (LPCVOID*)&DataPtr))) return; memcpy(&ParentFrame->m_matOriginal, (void*)DataPtr, Size); pDataObj->Unlock(); } // Mesh if(Type == TID_D3DRMMesh) { // See if mesh already loaded if(m_Meshes == NULL || m_Meshes->FindMesh(Name) == NULL) { // Create a new mesh structure Mesh = new sMesh(); // Store the name Mesh->m_Name = Name; Name = NULL; // Load mesh data if(FAILED(D3DXLoadSkinMeshFromXof(pDataObj, 0, m_Graphics->GetDeviceCOM(), &Adjacency, &MaterialBuffer, NULL, &Mesh->m_NumMaterials, &Mesh->m_SkinInfo, &Mesh->m_Mesh))) { delete Mesh; return; } // Calculate the bounding box and sphere if(SUCCEEDED(Mesh->m_Mesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&Ptr))) { D3DXComputeBoundingBox((D3DXVECTOR3*)Ptr, Mesh->m_Mesh->GetNumVertices(), Mesh->m_Mesh->GetNumBytesPerVertex(), &Mesh->m_Min, &Mesh->m_Max); D3DXComputeBoundingSphere((D3DXVECTOR3*)Ptr, Mesh->m_Mesh->GetNumVertices(), Mesh->m_Mesh->GetNumBytesPerVertex(), &D3DXVECTOR3(0.0f,0.0f,0.0f), &Mesh->m_Radius); Mesh->m_Mesh->UnlockVertexBuffer(); } // Store # of bones (if any) if(Mesh->m_SkinInfo) Mesh->m_NumBones = Mesh->m_SkinInfo->GetNumBones(); // Create a matching skinned mesh if bone exist if(Mesh->m_SkinInfo != NULL && Mesh->m_NumBones != 0) { if(FAILED(Mesh->m_Mesh->CloneMeshFVF(0, Mesh->m_Mesh->GetFVF(), m_Graphics->GetDeviceCOM(), &Mesh->m_SkinMesh))) ReleaseCOM(Mesh->m_SkinInfo); } // Create an array of matrices to store bone transformations if(Mesh->m_SkinInfo != NULL && Mesh->m_NumBones != 0) { // Create the bone matrix array and clear it out Mesh->m_Matrices = new D3DXMATRIX[Mesh->m_NumBones]; for(i=0;i<Mesh->m_NumBones;i++) D3DXMatrixIdentity(&Mesh->m_Matrices[i]); // Create the frame mapping matrix array and clear out Mesh->m_FrameMatrices = new D3DXMATRIX*[Mesh->m_NumBones]; for(i=0;i<Mesh->m_NumBones;i++) Mesh->m_FrameMatrices[i] = NULL; } // Load materials or create a default one if none if(!Mesh->m_NumMaterials) { // Create a default one Mesh->m_Materials = new D3DMATERIAL9[1]; Mesh->m_Textures = new LPDIRECT3DTEXTURE9[1]; ZeroMemory(Mesh->m_Materials, sizeof(D3DMATERIAL9)); Mesh->m_Materials[0].Diffuse.r = 1.0f; Mesh->m_Materials[0].Diffuse.g = 1.0f; Mesh->m_Materials[0].Diffuse.b = 1.0f; Mesh->m_Materials[0].Diffuse.a = 1.0f; Mesh->m_Materials[0].Ambient = Mesh->m_Materials[0].Diffuse; Mesh->m_Materials[0].Specular = Mesh->m_Materials[0].Diffuse; Mesh->m_Textures[0] = NULL; Mesh->m_NumMaterials = 1; } else { // Load the materials Materials = (D3DXMATERIAL*)MaterialBuffer->GetBufferPointer(); Mesh->m_Materials = new D3DMATERIAL9[Mesh->m_NumMaterials]; Mesh->m_Textures = new LPDIRECT3DTEXTURE9[Mesh->m_NumMaterials]; for(i=0;i<Mesh->m_NumMaterials;i++) { Mesh->m_Materials[i] = Materials[i].MatD3D; Mesh->m_Materials[i].Ambient = Mesh->m_Materials[i].Diffuse; // Build a texture path and load it sprintf(Path, "%s%s", TexturePath, Materials[i].pTextureFilename); if(FAILED(D3DXCreateTextureFromFile(m_Graphics->GetDeviceCOM(), Path, &Mesh->m_Textures[i]))) { Mesh->m_Textures[i] = NULL; } } } ReleaseCOM(MaterialBuffer); // link in mesh Mesh->m_Next = m_Meshes; m_Meshes = Mesh; m_NumMeshes++; } else { // Find mesh in list Mesh = m_Meshes->FindMesh(Name); } // Add mesh to frame if(Mesh != NULL) ParentFrame->AddMesh(Mesh); } // Skip animation sets and animations if(Type == TID_D3DRMAnimationSet || Type == TID_D3DRMAnimation || Type == TID_D3DRMAnimationKey) { delete [] Name; return; } // Release name buffer delete [] Name; SIZE_T count; if (FAILED(pDataObj->GetChildren(&count))) return; SIZE_T c = 0; // Scan for embedded templates while(c < count) { if (FAILED(pDataObj->GetChild(c, &pSubObj))) break; c++; // Process embedded references if (pSubObj->IsReference()) { if (SUCCEEDED(pSubObj->GetChild(0, &pSubData))) { ParseXFileData(pSubData, SubFrame, TexturePath); ReleaseCOM(pSubData); } } /*if(SUCCEEDED(pSubObj->QueryInterface(IID_IDirectXFileDataReference, (void**)&pDataRef))) { if(SUCCEEDED(pDataRef->Resolve(&pSubData))) { ParseXFileData(pSubData, SubFrame, TexturePath); ReleaseCOM(pSubData); } ReleaseCOM(pDataRef); }*/ // Process non-referenced embedded templates if(SUCCEEDED(pSubObj->QueryInterface(IID_ID3DXFileData, (void**)&pSubData))) { ParseXFileData(pSubData, SubFrame, TexturePath); ReleaseCOM(pSubData); } ReleaseCOM(pSubObj); } return; }