/** * \brief we need to go through the hierarchy and set the combined matrices * calls itself recursively as it tareverses the hierarchy * \param device - the Direct3D device object * \param pFrame - current frame * \param pParentMatrix - the parent frame matrix * \author Keith Ditchburn \date 18 July 2005 */ void CXFileEntity::SetupBoneMatrices(D3DXFRAME_EXTENDED *pFrame, LPD3DXMATRIX pParentMatrix) { // Cast to our extended structure first D3DXMESHCONTAINER_EXTENDED* pMesh = (D3DXMESHCONTAINER_EXTENDED*)pFrame->pMeshContainer; // If this frame has a mesh if(pMesh) { // We need to remember which is the first mesh in the hierarchy for later when we // update (FrameMove) if(!m_firstMesh) m_firstMesh = pMesh; // if there is skin info, then setup the bone matrices if(pMesh->pSkinInfo && pMesh->MeshData.pMesh) { // Create a copy of the mesh to skin into later D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]; if (FAILED(pMesh->MeshData.pMesh->GetDeclaration(Declaration))) return; pMesh->MeshData.pMesh->CloneMesh(D3DXMESH_MANAGED, Declaration, m_d3dDevice, &pMesh->exSkinMesh); // Max bones is calculated for later use (to know how big to make the bone matrices array) m_maxBones=max(m_maxBones,(int)pMesh->pSkinInfo->GetNumBones()); // For each bone work out its matrix for (unsigned int i = 0; i < pMesh->pSkinInfo->GetNumBones(); i++) { // Find the frame containing the bone D3DXFRAME_EXTENDED* pTempFrame = (D3DXFRAME_EXTENDED*)D3DXFrameFind(m_frameRoot, pMesh->pSkinInfo->GetBoneName(i)); // set the bone part - point it at the transformation matrix pMesh->exFrameCombinedMatrixPointer[i] = &pTempFrame->exCombinedTransformationMatrix; } } } // Pass on to sibblings if(pFrame->pFrameSibling) SetupBoneMatrices((D3DXFRAME_EXTENDED*)pFrame->pFrameSibling, pParentMatrix); // Pass on to children if(pFrame->pFrameFirstChild) SetupBoneMatrices((D3DXFRAME_EXTENDED*)pFrame->pFrameFirstChild, &pFrame->exCombinedTransformationMatrix); }
bool XEnitity::Load(const std::string FileName) { m_FileName = FileName; MeshAllocation* pMeshAlloc = new MeshAllocation; HRESULT hr = D3DXLoadMeshHierarchyFromX(m_FileName.c_str(), D3DXMESH_MANAGED, m_d3ddev, pMeshAlloc, NULL, &m_pTopFrame, &m_pAnimCtrl); SAFE_DELETE(pMeshAlloc); if(FAILED(hr)) return false; m_NumAnimationSets = m_pAnimCtrl->GetNumAnimationSets(); if(m_pTopFrame) { SetupBoneMatrices((CUSTOM_FRAME*) m_pTopFrame); m_pBoneMatrices = new D3DXMATRIX[m_MaxBones]; memset(m_pBoneMatrices, 0, sizeof(D3DXMATRIX)*m_MaxBones); } return true; }
bool CXFileEntity::Load(const std::string &filename) { // Create our mesh hierarchy class to control the allocation of memory - only used temporarily CMeshHierarchy *memoryAllocator=new CMeshHierarchy; // To make it easier to find the textures change the current directory to the one containing the .x file // First though remember the current one to put it back afterwards std::string currentDirectory=CUtility::GetTheCurrentDirectory(); std::string xfilePath; CUtility::SplitPath(filename,&xfilePath,&m_filename); SetCurrentDirectory(xfilePath.c_str()); // This is the function that does all the .x file loading. We provide a pointer to an instance of our // memory allocator class to handle memory allocationm during the frame and mesh loading HRESULT hr = D3DXLoadMeshHierarchyFromX(filename.c_str(), D3DXMESH_MANAGED, m_d3dDevice, memoryAllocator, NULL, &m_frameRoot, &m_animController); delete memoryAllocator; memoryAllocator=0; SetCurrentDirectory(currentDirectory.c_str()); if (FAILED(hr)) return false; // if the x file contains any animation remember how many sets there are if(m_animController) m_numAnimationSets = m_animController->GetMaxNumAnimationSets(); // Bones for skining if(m_frameRoot) { // Set the bones up SetupBoneMatrices((D3DXFRAME_EXTENDED*)m_frameRoot, NULL); // Create the bone matrices array for use during FrameMove to hold the final transform m_boneMatrices = new D3DXMATRIX[m_maxBones]; ZeroMemory(m_boneMatrices, sizeof(D3DXMATRIX)*m_maxBones); // Calculate the Bounding Sphere for this model (used in CalculateInitialViewMatrix to position camera correctly) D3DXFrameCalculateBoundingSphere(m_frameRoot, &m_sphereCentre, &m_sphereRadius); } m_firstMesh->MeshData.pMesh->GetVertexBuffer(&vb.vb); m_firstMesh->MeshData.pMesh->GetIndexBuffer(&ib.ib); D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE]; m_firstMesh->MeshData.pMesh->GetDeclaration(pDecl); renderSystem->CreateVertexDeclaration(&pDecl[0],&vb.declaration); // Получение данных о количестве вершин, индексов и полигонов dwNumVerticies = m_firstMesh->MeshData.pMesh->GetNumVertices(); dwNumIndecies = m_firstMesh->MeshData.pMesh->GetNumFaces()*3; dwNumFaces = m_firstMesh->MeshData.pMesh->GetNumFaces(); vb.vertexSize = (short)m_firstMesh->MeshData.pMesh->GetNumBytesPerVertex(); return true; }
void XEnitity::SetupBoneMatrices(CUSTOM_FRAME *pFrame) { CUSTOM_MESHCONTAINER* pMeshContainer = (CUSTOM_MESHCONTAINER*) pFrame->pMeshContainer; while(pMeshContainer && pMeshContainer->pSkinInfo){ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]; if( FAILED( pMeshContainer->MeshData.pMesh->GetDeclaration(Declaration) ) ) return; //clone the mesh pMeshContainer->MeshData.pMesh->CloneMesh(D3DXMESH_MANAGED, Declaration, m_d3ddev, &pMeshContainer->pExSkinMesh); //calc the max bones DWORD NumBones = pMeshContainer->pSkinInfo->GetNumBones(); m_MaxBones = max(m_MaxBones, (unsigned int)NumBones); for(unsigned int i = 0; i < NumBones; ++i){ CUSTOM_FRAME* pTmpFrame = (CUSTOM_FRAME*) D3DXFrameFind(m_pTopFrame, pMeshContainer->pSkinInfo->GetBoneName(i)); pMeshContainer->pExFrameCombinedMatrixPointer[i] = &pTmpFrame->exCombTransformationMatrix; } //loop for all meshes pMeshContainer = (CUSTOM_MESHCONTAINER*)pMeshContainer->pNextMeshContainer; }//end while //pass to siblings if(pFrame->pFrameSibling) SetupBoneMatrices((CUSTOM_FRAME*)pFrame->pFrameSibling); //pass to children if(pFrame->pFrameFirstChild) SetupBoneMatrices((CUSTOM_FRAME*)pFrame->pFrameFirstChild); return; }
//================================================================================================= // Wczytywanie modelu z pliku //================================================================================================= void Mesh::Load(StreamReader& stream, IDirect3DDevice9* device) { assert(device); LoadHeader(stream); SetVertexSizeDecl(); // ------ vertices // ensure size uint size = vertex_size * head.n_verts; if(!stream.Ensure(size)) throw "Failed to read vertex buffer."; // create vertex buffer HRESULT hr = device->CreateVertexBuffer(size, 0, 0, D3DPOOL_MANAGED, &vb, nullptr); if(FAILED(hr)) throw Format("Failed to create vertex buffer (%d).", hr); // read void* ptr; V(vb->Lock(0, size, &ptr, 0)); stream.Read(ptr, size); V(vb->Unlock()); // ----- triangles // ensure size size = sizeof(word) * head.n_tris * 3; if(!stream.Ensure(size)) throw "Failed to read index buffer."; // create index buffer hr = device->CreateIndexBuffer(size, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ib, nullptr); if(FAILED(hr)) throw Format("Failed to create index buffer (%d).", hr); // read V(ib->Lock(0, size, &ptr, 0)); stream.Read(ptr, size); V(ib->Unlock()); // ----- submeshes size = Submesh::MIN_SIZE * head.n_subs; if(!stream.Ensure(size)) throw "Failed to read submesh data."; subs.resize(head.n_subs); for(word i = 0; i < head.n_subs; ++i) { Submesh& sub = subs[i]; stream.Read(sub.first); stream.Read(sub.tris); stream.Read(sub.min_ind); stream.Read(sub.n_ind); stream.Read(sub.name); stream.ReadString1(); if(BUF[0]) sub.tex = ResourceManager::Get<Texture>().GetLoaded(BUF); else sub.tex = nullptr; // specular value stream.Read(sub.specular_color); stream.Read(sub.specular_intensity); stream.Read(sub.specular_hardness); // normalmap if(IS_SET(head.flags, F_TANGENTS)) { stream.ReadString1(); if(BUF[0]) { sub.tex_normal = ResourceManager::Get<Texture>().GetLoaded(BUF); stream.Read(sub.normal_factor); } else sub.tex_normal = nullptr; } else sub.tex_normal = nullptr; // specular map stream.ReadString1(); if(BUF[0]) { sub.tex_specular = ResourceManager::Get<Texture>().GetLoaded(BUF); stream.Read(sub.specular_factor); stream.Read(sub.specular_color_factor); } else sub.tex_specular = nullptr; if(!stream) throw Format("Failed to read submesh %u.", i); } // animation data if(IS_SET(head.flags, F_ANIMATED) && !IS_SET(head.flags, F_STATIC)) { // bones size = Bone::MIN_SIZE * head.n_bones; if(!stream.Ensure(size)) throw "Failed to read bones."; bones.resize(head.n_bones + 1); // zero bone Bone& zero_bone = bones[0]; zero_bone.parent = 0; zero_bone.name = "zero"; zero_bone.id = 0; zero_bone.mat = Matrix::IdentityMatrix; for(byte i = 1; i <= head.n_bones; ++i) { Bone& bone = bones[i]; bone.id = i; stream.Read(bone.parent); stream.Read(bone.mat._11); stream.Read(bone.mat._12); stream.Read(bone.mat._13); bone.mat._14 = 0; stream.Read(bone.mat._21); stream.Read(bone.mat._22); stream.Read(bone.mat._23); bone.mat._24 = 0; stream.Read(bone.mat._31); stream.Read(bone.mat._32); stream.Read(bone.mat._33); bone.mat._34 = 0; stream.Read(bone.mat._41); stream.Read(bone.mat._42); stream.Read(bone.mat._43); bone.mat._44 = 1; stream.Read(bone.name); bones[bone.parent].childs.push_back(i); } if(!stream) throw "Failed to read bones data."; // animations size = Animation::MIN_SIZE * head.n_anims; if(!stream.Ensure(size)) throw "Failed to read animations."; anims.resize(head.n_anims); for(byte i = 0; i < head.n_anims; ++i) { Animation& anim = anims[i]; stream.Read(anim.name); stream.Read(anim.length); stream.Read(anim.n_frames); size = anim.n_frames * (4 + sizeof(KeyframeBone) * head.n_bones); if(!stream.Ensure(size)) throw Format("Failed to read animation %u data.", i); anim.frames.resize(anim.n_frames); for(word j = 0; j < anim.n_frames; ++j) { stream.Read(anim.frames[j].time); anim.frames[j].bones.resize(head.n_bones); stream.Read(anim.frames[j].bones.data(), sizeof(KeyframeBone) * head.n_bones); } } // add zero bone to count ++head.n_bones; } LoadPoints(stream); // bone groups if(IS_SET(head.flags, F_ANIMATED) && !IS_SET(head.flags, F_STATIC)) { if(!stream.Ensure(BoneGroup::MIN_SIZE * head.n_groups)) throw "Failed to read bone groups."; groups.resize(head.n_groups); for(word i = 0; i < head.n_groups; ++i) { BoneGroup& gr = groups[i]; stream.Read(gr.name); // parent group stream.Read(gr.parent); assert(gr.parent < head.n_groups); assert(gr.parent != i || i == 0); // bone indexes byte count; stream.Read(count); gr.bones.resize(count); stream.Read(gr.bones.data(), gr.bones.size()); } if(!stream) throw "Failed to read bone groups data."; SetupBoneMatrices(); } // splits if(IS_SET(head.flags, F_SPLIT)) { size = sizeof(Split) * head.n_subs; if(!stream.Ensure(size)) throw "Failed to read mesh splits."; splits.resize(head.n_subs); stream.Read(splits.data(), size); } }