SkinMesh.cpp /////////////////////////////////////////////////////////////////////////////////////////// #include "StdAfx.h" #include ".\skinmesh.h" SkinMesh::SkinMesh(LPDIRECT3DDEVICE9 g_pd3dDevice) : pAnimSetHead(NULL) , pFrameRoot(NULL) , pMeshHead(NULL) , Options(0) , CurTime(0) , pAnimSetCur(NULL) { pd3dDevice = g_pd3dDevice; Options = 0; pFrameRoot = new Frame(); pAnimSetHead = NULL; pMeshHead = NULL; CurTime = 0; pAnimSetCur = pAnimSetHead; } SkinMesh::~SkinMesh(void) { } Frame* SkinMesh::FindFrame(Frame* frame, char* Name) { Frame *pFrame; if((frame->Name != NULL)&&strcmp(frame->Name, Name) == 0) return frame; if(frame->pFrameChild != NULL) { pFrame = FindFrame(frame->pFrameChild, Name); if(pFrame != NULL) return pFrame; } if(frame->pFrameSibling != NULL) { pFrame = FindFrame(frame->pFrameSibling, Name); if(pFrame != NULL) return pFrame; } return NULL; } void SkinMesh::AddFrame(Frame* parentFrame, Frame* pFrame) { if (parentFrame->pFrameChild == NULL) { parentFrame->pFrameChild = pFrame; }else { Frame* frame = parentFrame->pFrameChild; while (frame->pFrameSibling != NULL) { frame = frame->pFrameSibling; } frame->pFrameSibling = pFrame; } } void SkinMesh::AddMesh(Frame* frame, MeshContainer* pMeshContainer) { pMeshContainer->pMeshContainerNext = pMeshHead; pMeshHead = pMeshContainer; pMeshContainer = NULL; if(frame) { pMeshHead->pFrame = frame; } } HRESULT SkinMesh::FindBones(void) { MeshContainer *pMeshContainer; pMeshContainer = pMeshHead; while(NULL != pMeshContainer) { if(pMeshContainer->pSkinInfo) { for( DWORD i = 0; i<pMeshContainer->pSkinInfo->GetNumBones(); i++) { Frame *frame = FindFrame(pFrameRoot, (char*)pMeshContainer->pSkinInfo->GetBoneName(i)); pMeshContainer->pBoneMatrix = &(frame->matCombined); } } pMeshContainer = pMeshContainer->pMeshContainerNext; } return E_NOTIMPL; } HRESULT SkinMesh::FrameMove(void) { CurTime = CurTime+100; if(CurTime>1.0e15f) CurTime = 0; Animation *pAnimCur = pAnimSetCur->pAnimation; while (pAnimCur != NULL) { SetTime(pAnimCur, CurTime); pAnimCur = pAnimCur->pAnimationNext; } return E_NOTIMPL; } HRESULT SkinMesh: rawFrames(void) { MeshContainer *pmc = pMeshHead; while (pmc != NULL) { pd3dDevice->SetTransform(D3DTS_WORLD, &pmc->pFrame->matCombined); DrawMeshContainer(pmc); pmc = pmc->pMeshContainerNext; } return E_NOTIMPL; } void SkinMesh::SetTime(Animation* pAnim, float fGlobalTime) { UINT iKey; UINT dwp2; UINT dwp3; D3DXMATRIX matResult; D3DXMATRIX matTemp; float fTime1; float fTime2; float fLerpvalue; D3DXVECTOR3 vScale; D3DXVECTOR3 vPos; D3DXQUATERNION quat; float fTime; if (pAnim->pMatrixKeys ) { fTime = (float)fmod(fGlobalTime, pAnim->pMatrixKeys[pAnim->nMatrixKeys-1].dwTime); for (iKey = 0 ;iKey < pAnim->nMatrixKeys ; iKey++) { if ((float)pAnim->pMatrixKeys[iKey].dwTime > fTime) { dwp3 = iKey; if (iKey > 0) dwp2= iKey - 1; else dwp2 = iKey; break; } } fTime1 = (float)pAnim->pMatrixKeys[dwp2].dwTime; fTime2 = (float)pAnim->pMatrixKeys[dwp3].dwTime; if ((fTime2 - fTime1) ==0) fLerpvalue = 0; else fLerpvalue = (fTime - fTime1) / (fTime2 - fTime1); if (fLerpvalue > 0.5) iKey = dwp3; else iKey = dwp2; pAnim->pFrame->matRot = pAnim->pMatrixKeys[iKey].mat; } else { D3DXMatrixIdentity(&matResult); if (pAnim->pScaleKeys) { dwp2 = dwp3 = 0; fTime = (float)fmod(fGlobalTime, pAnim->pScaleKeys[pAnim->nScaleKeys-1].dwTime); for (iKey = 0 ;iKey < pAnim->nScaleKeys ; iKey++) { if ((float)pAnim->pScaleKeys[iKey].dwTime > fTime) { dwp3 = iKey; if (iKey > 0) dwp2= iKey - 1; else dwp2 = iKey; break; } } fTime1 = (float)pAnim->pScaleKeys[dwp2].dwTime; fTime2 = (float)pAnim->pScaleKeys[dwp3].dwTime; if ((fTime2 - fTime1) ==0) fLerpvalue = 0; else fLerpvalue = (fTime - fTime1) / (fTime2 - fTime1); D3DXVec3Lerp(&vScale, &pAnim->pScaleKeys[dwp2].vScale, &pAnim->pScaleKeys[dwp3].vScale, fLerpvalue); D3DXMatrixScaling(&matTemp, vScale.x, vScale.y, vScale.z); D3DXMatrixMultiply(&matResult, &matResult, &matTemp); pAnim->pFrame->matRot = matResult; } else if (pAnim->pRotateKeys ) { dwp2 = dwp3 = 0; fTime = (float)fmod(fGlobalTime, pAnim->pRotateKeys[pAnim->nRotateKeys-1].dwTime); for (iKey = 0 ;iKey < pAnim->nRotateKeys ; iKey++) { if ((float)pAnim->pRotateKeys[iKey].dwTime > fTime) { dwp3 = iKey; if (iKey > 0) dwp2= iKey - 1; else dwp2 = iKey; break; } } fTime1 = (float)pAnim->pRotateKeys[dwp2].dwTime; fTime2 = (float)pAnim->pRotateKeys[dwp3].dwTime; if ((fTime2 - fTime1) ==0) fLerpvalue = 0; else fLerpvalue = (fTime - fTime1) / (fTime2 - fTime1); D3DXQUATERNION q1,q2; q1.x =-pAnim->pRotateKeys[dwp2].quatRotate.x; q1.y =-pAnim->pRotateKeys[dwp2].quatRotate.y; q1.z =-pAnim->pRotateKeys[dwp2].quatRotate.z; q1.w =pAnim->pRotateKeys[dwp2].quatRotate.w; q2.x =-pAnim->pRotateKeys[dwp3].quatRotate.x; q2.y =-pAnim->pRotateKeys[dwp3].quatRotate.y; q2.z =-pAnim->pRotateKeys[dwp3].quatRotate.z; q2.w =pAnim->pRotateKeys[dwp3].quatRotate.w; D3DXQuaternionSlerp(&quat, &q1, &q2, fLerpvalue); D3DXMatrixRotationQuaternion(&matTemp, &quat); D3DXMatrixMultiply(&matResult, &matResult, &matTemp); pAnim->pFrame->matRot = matResult; } else if (pAnim->pPositionKeys) { dwp2=dwp3=0; fTime = (float)fmod(fGlobalTime, pAnim->pPositionKeys[pAnim->nRotateKeys-1].dwTime); for (iKey = 0 ;iKey < pAnim->nPositionKeys ; iKey++) { if ((float)pAnim->pPositionKeys[iKey].dwTime > fTime) { dwp3 = iKey; if (iKey > 0) dwp2= iKey - 1; else dwp2 = iKey; break; } } fTime1 = (float)pAnim->pPositionKeys[dwp2].dwTime; fTime2 = (float)pAnim->pPositionKeys[dwp3].dwTime; if ((fTime2 - fTime1) ==0) fLerpvalue = 0; else fLerpvalue = (fTime - fTime1) / (fTime2 - fTime1); D3DXVec3Lerp((D3DXVECTOR3*)&vPos, &pAnim->pPositionKeys[dwp2].vPos, &pAnim->pPositionKeys[dwp3].vPos, fLerpvalue); D3DXMatrixTranslation(&matTemp, vPos.x, vPos.y, vPos.z); D3DXMatrixMultiply(&matResult, &matResult, &matTemp); pAnim->pFrame->matRot = matResult; } } } HRESULT SkinMesh: rawMeshContainer(MeshContainer* pmcMesh) { UINT ipattr; PBYTE pbVerticesSrc; PBYTE pbVerticesDest; if( pmcMesh->pSkinInfo && pmcMesh->pSkinInfo->GetNumBones()) { D3DCAPS9 caps; pd3dDevice->GetDeviceCaps(&caps); DWORD cBones = pmcMesh->pSkinInfo->GetNumBones(); D3DXMATRIX* BoneMatrices = NULL; BoneMatrices = new D3DXMATRIX[cBones]; for(DWORD iBone = 0; iBone<cBones; iBone++) D3DXMatrixMultiply(&BoneMatrices[iBone], &pmcMesh->pBoneOffsetMat[iBone], pmcMesh->pBoneMatrix[iBone]); D3DXMATRIX Indentity; D3DXMatrixIdentity(&Indentity); pd3dDevice->SetTransform(D3DTS_WORLD, &Indentity); pmcMesh->pMesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&pbVerticesDest); pmcMesh->pSkinMesh->LockVertexBuffer(0, (LPVOID*)&pbVerticesSrc); pmcMesh->pSkinInfo->UpdateSkinnedMesh(BoneMatrices, NULL, pbVerticesSrc, pbVerticesDest); pmcMesh->pSkinMesh->UnlockVertexBuffer(); pmcMesh->pMesh->UnlockVertexBuffer(); for(ipattr = 0; ipattr<pmcMesh->NumMaterials; ipattr++) { pd3dDevice->SetMaterial(&(pmcMesh->pMaterials[ipattr])); pd3dDevice->SetTexture(0, pmcMesh->pTextures[ipattr]); pmcMesh->pMesh->DrawSubset(ipattr); } }else { for(ipattr = 0; ipattr<pmcMesh->NumMaterials; ipattr++) { pd3dDevice->SetMaterial(&(pmcMesh->pMaterials[ipattr])); pd3dDevice->SetTexture(0, pmcMesh->pTextures[ipattr]); pmcMesh->pMesh->DrawSubset(ipattr); } } return E_NOTIMPL; } HRESULT SkinMesh::Render() { D3DXMatrixIdentity(&pFrameRoot->matRot) ; D3DXMATRIX mat; D3DXMatrixIdentity(&mat); FrameMove(); UpdateFrames(pFrameRoot, mat); DrawFrames(); return E_NOTIMPL; } HRESULT SkinMesh: oadFromXFile(TCHAR* pFileName) { HRESULT hr = S_OK; LPD3DXFILE pFile = NULL; LPD3DXFILEENUMOBJECT pFileEnumObject = NULL; LPD3DXFILEDATA pFileData = NULL; GUID type; hr = D3DXFileCreate(&pFile); if (FAILED(hr)) return hr; hr = pFile->RegisterTemplates((LPVOID)D3DRM_XTEMPLATES ,D3DRM_XTEMPLATE_BYTES); if(FAILED(hr)) return hr; hr = pFile->CreateEnumObject((LPVOID)pFileName, DXFILELOAD_FROMFILE , &pFileEnumObject); if(FAILED(hr)) return hr; DWORD Size; pFileEnumObject->GetChildren(&Size); for(DWORD i = 0 ; i < Size ; i++) { pFileEnumObject->GetChild(i, &pFileData); pFileData->GetType(&type); if (type == TID_D3DRMFrame) { LoadFrame(pFileData, pFrameRoot); } if (type == TID_D3DRMAnimationSet) { LoadAnimationSet(pFileData); } GXRELEASE(pFileData); } FindBones(); pFrameRoot->matRotOrig = pFrameRoot->matRot; GXRELEASE(pFileEnumObject); GXRELEASE(pFile); return E_NOTIMPL; } HRESULT SkinMesh: oadMesh(LPD3DXFILEDATA pFileData, Frame* pFrameParent) { HRESULT hr = S_OK; MeshContainer *pmcMesh = NULL; LPD3DXBUFFER pMaterialsbuf = NULL; LPD3DXBUFFER pAdjacencybuf = NULL; DWORD NumName; UINT cFaces; UINT iMaterial; pmcMesh = new MeshContainer(); pFileData->GetName(NULL, &NumName); if(NumName>0) { pmcMesh->Name = new char[NumName]; pFileData->GetName(pmcMesh->Name, &NumName); }else pmcMesh->Name = "NoNameMesh"; D3DXLoadSkinMeshFromXof(pFileData, Options, pd3dDevice, &pAdjacencybuf, &pMaterialsbuf, NULL, &pmcMesh->NumMaterials, &pmcMesh->pSkinInfo, &pmcMesh->pSkinMesh); pmcMesh->pSkinMesh->CloneMeshFVF(Options, pmcMesh->pSkinMesh->GetFVF(),pd3dDevice, &pmcMesh->pMesh); DWORD NumBones = pmcMesh->pSkinInfo->GetNumBones(); if(NumBones>0) { pmcMesh->pBoneMatrix = new D3DXMATRIX*[NumBones]; pmcMesh->pBoneOffsetMat = new D3DXMATRIX[NumBones]; for(DWORD i = 0; i < NumBones; i++) pmcMesh->pBoneOffsetMat = (*pmcMesh->pSkinInfo->GetBoneOffsetMatrix(i)); LPDWORD pAdjacency = static_cast<LPDWORD>(pAdjacencybuf->GetBufferPointer()); cFaces = pmcMesh->pSkinMesh->GetNumFaces(); pmcMesh->pAdjacency = new DWORD[cFaces*3]; memcpy(pmcMesh->pAdjacency, pAdjacency, cFaces*3*sizeof(DWORD)); }else { pmcMesh->pSkinInfo = NULL; } |