www.pudn.com > notWow.rar > Bone.cpp


#include "Bone.h" 
#include  
void 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; 
	} 
	*/ 
}