www.pudn.com > notWow.rar > Bone.cpp
#include "Bone.h" #includevoid Bone::Init(char* f, ModelBoneDef &b, int *global,bool bBlend,D3DXMATRIX* pAMat) { m_bCalc = false; m_bBlend = bBlend; if(m_bBlend) { pmat = pAMat; } else { pmat = new D3DXMATRIX; } parent = b.parent; pivot = fixCoordSystem(b.pivot); billboard = (b.flags & 8) != 0; //billboard = false; boneDef = b; trans.init(b.translation, f, global); rot.init(b.rotation, f, global); scale.init(b.scaling, f, global); trans.fix(fixCoordSystem); rot.fix(fixCoordSystemQuat); scale.fix(fixCoordSystem2); } void Bone::Free() { if(!m_bBlend) { SAFE_DELETE(pmat); } } void Bone::CalcMatrix(Bone *allbones, int anim, int time, bool rotate) { if (m_bCalc) return; D3DXMATRIX m; D3DXMatrixIdentity(&m); D3DXMATRIX tm; D3DXQUATERNION q; bool tr = rot.used || scale.used || trans.used || billboard; if (tr) { // ... //D3DXMatrixTranslation(&tm,-pivot.x,-pivot.y,-pivot.z); //m *= tm; m._41 -= pivot.x; m._42 -= pivot.y; m._43 -= pivot.z; if (scale.used) { D3DXVECTOR3 sc = scale.getValue(anim, time); D3DXMatrixScaling(&tm,sc.x,sc.y,sc.z); m *= tm; } if (rot.used && rotate) { q = rot.getValue(anim, time); D3DXMatrixRotationQuaternion(&tm,&q); m *= tm; } if (trans.used) { D3DXVECTOR3 tr = trans.getValue(anim, time); D3DXMatrixTranslation(&tm,tr.x,tr.y,tr.z); m *= tm; } /// !!!!! if (billboard && 0) { //D3DXMATRIX mtrans; //glGetFloatv(GL_MODELVIEW_MATRIX, &(mtrans.m[0][0])); //mtrans.transpose(); //mtrans.invert(); //D3DXVECTOR3 camera = mtrans * D3DXVECTOR3(0.0f,0.0f,0.0f); //D3DXVECTOR3 look = (camera - pivot).normalize(); //D3DXVECTOR3 up = ((mtrans * D3DXVECTOR3(0.0f,1.0f,0.0f)) - camera).normalize(); // these should be normalized by default but fp inaccuracy kicks in when looking down :( //D3DXVECTOR3 right = (up % look).normalize(); //up = (look % right).normalize(); // calculate a billboard matrix //D3DXMATRIX mbb; //mbb.unit(); //mbb.m[0][2] = right.x; //mbb.m[1][2] = right.y; //mbb.m[2][2] = right.z; //mbb.m[3][2] = 0.0f; //mbb.m[0][1] = up.x; //mbb.m[1][1] = up.y; ///mbb.m[2][1] = up.z; //mbb.m[3][1] = 0.0f; //mbb.m[0][0] = look.x; //mbb.m[1][0] = look.y; //mbb.m[2][0] = look.z; //mbb.m[3][0] = 0.0f; /* mbb.m[0][2] = right.x; mbb.m[1][2] = right.y; mbb.m[2][2] = right.z; mbb.m[0][1] = up.x; mbb.m[1][1] = up.y; mbb.m[2][1] = up.z; mbb.m[0][0] = look.x; mbb.m[1][0] = look.y; mbb.m[2][0] = look.z; */ //m *= mbb; } D3DXMatrixTranslation(&tm,pivot.x,pivot.y,pivot.z); m *= tm; } else { D3DXMatrixIdentity(&m); } if (parent > -1) { allbones[parent].CalcMatrix(allbones, anim, time, rotate); *pmat = m *( *(allbones[parent].pmat)); } else { *pmat = m; } //transPivot = VxM(&pivot,&m); m_bCalc = true; } void BonesContainer::Init(int nBones,int nMatrices,char* pIndices, char *pFile,ModelHeader &Header,int *global) { int i; m_nBones = nBones; m_nMatrices = nMatrices; assert(m_nMatrices != 0 && m_nBones != 0); m_pMatrices = new D3DXMATRIX [m_nMatrices]; m_pBlendIndex = new char [m_nBones]; m_pBones = new Bone[m_nBones]; memcpy(m_pBlendIndex,pIndices,sizeof(char)*m_nBones); ModelBoneDef *mb = (ModelBoneDef*)(pFile + Header.ofsBones); for (i = 0; i < m_nBones; ++ i) { if(m_pBlendIndex[i] >= 0) m_pBones[i].Init(pFile, mb[i], global,true,m_pMatrices+(int)m_pBlendIndex[i]); else m_pBones[i].Init(pFile, mb[i], global,false); } // Block F is a lookup table for Key Skeletal Bones, hands, arms, legs, etc. int16 *p = (int16*)(pFile + Header.ofsF); for (i = 0; i < Header.nF; ++ i) { m_BonesLookup[i] = p[i]; // m_pBones[m_BonesLookup[i]].m_bKey = true; } // Get Animations if (Header.nAnimations > 0) { m_nAnimations = Header.nAnimations; m_pAnimations = new ModelAnimation[m_nAnimations]; memcpy(m_pAnimations, pFile + Header.ofsAnimations, m_nAnimations * sizeof(ModelAnimation)); // 一个AnimID (或叫做Act) 可能有几个对应的Animation for( i = 0 ; i < m_nAnimations ; ++ i) { assert(m_pAnimations[i].animID <= 255); m_AnimLookup[m_pAnimations[i].animID].push_back(i); } //FILE* fp = fopen("act.txt","w"); //for( i = 0 ; i < m_nAnimations ; ++ i) // fprintf(fp,"%d : %d : %d\n",i,m_pAnimations[i].animID); //fclose(fp); m_pAnimMgr = new AnimManager(m_pAnimations); } } void BonesContainer::Free() { if(m_pBones != NULL) { for(int i = 0 ; i < m_nBones ; ++ i) { m_pBones[i].Free(); } } SAFE_DELETE_A(m_pBlendIndex); SAFE_DELETE_A(m_pBones); SAFE_DELETE_A(m_pAnimations); SAFE_DELETE_A(m_pMatrices); SAFE_DELETE(m_pAnimMgr); } void BonesContainer::SetupBoneMatrices(int Anim, int Time) { Time += GetAnimations()[Anim].timeStart; int i; for (i =0; i < m_nBones; ++ i) { m_pBones[i].m_bCalc = false; } // Character specific bone animation calculations. //if (charModelDetails.isChar) if(0) { // Animate transformations for the rest of the model to adopt into their transformations if (m_BonesLookup[BONE_ROOT] > -1) { for (i = 0; i <= m_BonesLookup[BONE_ROOT]; ++ i) { m_pBones[i].CalcMatrix(m_pBones, Anim, Time); } } // Find the close hands animation id int closeFistID = 0; for (i = 0; i < m_nAnimations; ++ i) { if (m_pAnimations[i].animID==15) { // closed fist closeFistID = i; break; } } // Animate key skeletal bones except the fingers which we do later. // ----- int a, t; // if we have a "secondary animation" selected, animate upper body using that. if (m_pAnimMgr->GetSecondaryID() > -1) { a = m_pAnimMgr->GetSecondaryID(); t = m_pAnimMgr->GetSecondaryFrame(); } else { a = Anim; t = Time; } for (i = 0; i < 5; ++ i) { // only goto 5, otherwise it affects the hip/waist rotation for the lower-body. if (m_BonesLookup[i] > -1) m_pBones[m_BonesLookup[i]].CalcMatrix(m_pBones, a, t); } if (m_pAnimMgr->GetMouthID() > -1) { // Animate the head and jaw if (m_BonesLookup[BONE_HEAD] > -1) m_pBones[m_BonesLookup[BONE_HEAD]].CalcMatrix(m_pBones, m_pAnimMgr->GetMouthID(), m_pAnimMgr->GetMouthFrame()); if (m_BonesLookup[BONE_JAW] > -1) m_pBones[m_BonesLookup[BONE_JAW]].CalcMatrix(m_pBones, m_pAnimMgr->GetMouthID(), m_pAnimMgr->GetMouthFrame()); } else { // Animate the head and jaw if (m_BonesLookup[BONE_HEAD] > -1) m_pBones[m_BonesLookup[BONE_HEAD]].CalcMatrix(m_pBones, a, t); if (m_BonesLookup[BONE_JAW] > -1) m_pBones[m_BonesLookup[BONE_JAW]].CalcMatrix(m_pBones, a, t); } // still not sure what 18-26 bone lookups are but I think its more for things like wrist, etc which are not as visually obvious. for ( i = 18; i < 27; ++ i) { if (m_BonesLookup[i] > -1) m_pBones[m_BonesLookup[i]].CalcMatrix(m_pBones, a, t); } // ===== //if (charModelDetails.closeRHand) if(1) { a = closeFistID; t = m_pAnimations[closeFistID].timeStart+1; } else { a = Anim; t = Time; } for (i = 0; i < 5; ++ i) { if (m_BonesLookup[BONE_RFINGER1 + i] > -1) m_pBones[m_BonesLookup[BONE_RFINGER1 + i]].CalcMatrix(m_pBones, a, t); } //if (charModelDetails.closeLHand) if(1) { a = closeFistID; t = m_pAnimations[closeFistID].timeStart+1; } else { a = Anim; t = Time; } for (i = 0; i < 5; ++ i) { if (m_BonesLookup[BONE_LFINGER1 + i] > -1) m_pBones[m_BonesLookup[BONE_LFINGER1 + i]].CalcMatrix(m_pBones, a, t); } } else { for (i = 0; i < m_BonesLookup[BONE_ROOT]; ++ i) { m_pBones[i].CalcMatrix(m_pBones, Anim, Time); } // The following line fixes 'mounts' in that the character doesn't get rotated, but it also screws up the rotation for the entire model :( //bones[18].CalcMatrix(bones, Anim, Time, false); } // Animate everything thats left with the 'default' animation for (i = 0; i< m_nBones; ++ i) { m_pBones[i].CalcMatrix(m_pBones, Anim, Time); } /* D3DXMATRIX* pMat = Bone::GetMatrices(); for(i = 0 ; i < Bone::GetBlendMatricesCount() ; ++ i) { pMat[i]._41 = pMat[i]._14; pMat[i]._42 = pMat[i]._24; pMat[i]._43 = pMat[i]._34; pMat[i]._14 = 0.0f; pMat[i]._24 = 0.0f; pMat[i]._34 = 0.0f; } */ }