⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 maxmesh.cpp

📁 liu7788414
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		pMesh->m_FrameCount = itr->second.m_transList.size();
	else
		pMesh->m_FrameCount = 0;
	for (i=0; i<m_Bones.size(); i++, itr++)
	{
		bone.trans.clear();
		bone.vertexIndics.clear();
		if (itr->second.bUse)
		{
			strcpy(bone.name, itr->second.name);
			for (int j=0; j<itr->second.m_transList.size(); j++)
			{
				bmat = itr->second.m_transList[j].mat;
				bpt = bmat.GetRow(3);
				bpt*=16;
				bmat.SetRow(3, bpt);
				bone.trans.push_back(bmat);
			}
			bone.nodeId = itr->first;
			pMesh->m_Bones.push_back(bone);
		}
	}
	
	
	//this section get the most weightest bone of every vertex. And record the vertex index to bone's
	//info. It "only" useful for only One Bone per-vertex.
	//we use other two struct to record max two bone information for one vertex. 
	int bonecount;
	BoneInfo bitemp;
	for (m=0; m<m_Vertics.size(); m++)
	{		
		bonecount = m_Vertics[m].boneInfo.size();
		if (bonecount > 0)
		{
			//rearrange the bones sequence for a vertex acoording to weight
			for (int i=0; i<bonecount; i++)
			{
				bitemp = m_Vertics[m].boneInfo[i];
				for (int j=i+1; j<bonecount; j++)
				{
					if (m_Vertics[m].boneInfo[i].weight < m_Vertics[m].boneInfo[j].weight )
					{
						bitemp = m_Vertics[m].boneInfo[i];
						m_Vertics[m].boneInfo[i] = m_Vertics[m].boneInfo[j];
						m_Vertics[m].boneInfo[j] = bitemp;
					}
				}
			}
		}
		
		if (m_Vertics[m].boneInfo.size() > 0)
		{
			int index = FindBoneIndex(m_Vertics[m].boneInfo[0].boneIndex, pMesh->m_Bones);
			if (index != -1)				
				pMesh->m_Bones[index].vertexIndics.push_back(m);
		}
	}

	//remove bone not used for one bone and two bone.
	
	for (m=0; m<pMesh->m_Bones.size(); m++)
		pMesh->m_Bones[m].bUsed = false;
	
	int boneidx;
	for (m=0; m<m_Vertics.size(); m++)
	{
		int bonecount = m_Vertics[m].boneInfo.size();
		if (bonecount == 1)
		{
			boneidx = FindBoneIndex(m_Vertics[m].boneInfo[0].boneIndex, pMesh->m_Bones);
			if (boneidx >= 0)
				pMesh->m_Bones[boneidx].bUsed = true;
		}
		if (bonecount >= 2)
		{
			boneidx = FindBoneIndex(m_Vertics[m].boneInfo[0].boneIndex, pMesh->m_Bones);
			if (boneidx >= 0)
				pMesh->m_Bones[boneidx].bUsed = true;
			boneidx = FindBoneIndex(m_Vertics[m].boneInfo[1].boneIndex, pMesh->m_Bones);
			if (boneidx >= 0)
				pMesh->m_Bones[boneidx].bUsed = true;
		}
	}
	
	vector<Bone>::iterator bitr = pMesh->m_Bones.begin();
	while (bitr != pMesh->m_Bones.end())
	{
		if (!bitr->bUsed)
			bitr = pMesh->m_Bones.erase(bitr);
		else
			bitr++;
	}
	
	//get one bone and two bones for every vertex
	OneBoneVertex onebone;
	TwoBoneVertex twoBone;
	for (m=0; m<m_Vertics.size(); m++)
	{		
		int bonecount = m_Vertics[m].boneInfo.size();
		if (bonecount == 1)
		{
			onebone.boneIndex = FindBoneIndex(m_Vertics[m].boneInfo[0].boneIndex, pMesh->m_Bones);
			onebone.vertexIndex = m;
			pMesh->m_oneBoneVertex.push_back(onebone);
		}
		if (bonecount >= 2)
		{
			twoBone.vertexIndex = m;
			twoBone.boneIndex1 =  FindBoneIndex(m_Vertics[m].boneInfo[0].boneIndex, pMesh->m_Bones);
			assert(m_Vertics[m].boneInfo[0].weight >= 0 && m_Vertics[m].boneInfo[0].weight<=1);
			twoBone.boneWeight1 = m_Vertics[m].boneInfo[0].weight*128;
			twoBone.boneIndex2 =  FindBoneIndex(m_Vertics[m].boneInfo[1].boneIndex, pMesh->m_Bones);
			assert(m_Vertics[m].boneInfo[1].weight >= 0 && m_Vertics[m].boneInfo[1].weight<=1);
			twoBone.boneWeight2 = m_Vertics[m].boneInfo[1].weight*128;
			if (m_Vertics[m].boneInfo[0].weight+m_Vertics[m].boneInfo[1].weight<0.99f)
					twoBone.boneWeight2 = twoBone.boneWeight2;			
				
			twoBone.boneWeight1 = twoBone.boneWeight1*128/(twoBone.boneWeight1+twoBone.boneWeight2);
			twoBone.boneWeight2 = 128 - twoBone.boneWeight1;
			pMesh->m_twoBoneVertex.push_back(twoBone);
		}
	}

	//we do need erase the bone not use when one bone per vertex. But when for two bones per vertex
	//some bones shouldn't be removed any more.  so we comment it. It will not effect the compatiblity
	//with the old one bone file format. We just have some bones without vertex list.

	/*
	vector<Bone>::iterator bitr = pMesh->m_Bones.begin();
	while (bitr != pMesh->m_Bones.end())
	{
		if (bitr->vertexIndics.size() == 0)
			bitr = pMesh->m_Bones.erase(bitr);
		else
			bitr++;
	}
	*/
}

void CMaxMesh::AddAnimationData(MaxSubMesh *pSubMesh, IGameNode *pGameNode)
{
	//in pSubMesh, we already have all vertex data in it.

	//animation data. we should get every bone for every submesh in a max file.
	//bone will have transform data for every frame
	//for every vertex, it may be bonded to one than one bone with different weight

	//step 1: get all bones of one submesh, and get it key frame transform data: position,
	//        rotation, scale.
	//step 2: for every vertex for this submesh, get its related bones and weight;


// get weights ,CFace is a class that hold face info,i0,i1,i2 is face's vertexes id
// find skin modifier 
	Matrix3 mat;
	AffineParts affp;
	MaxBone bone;
	FrameTransform trans;
	BoneInfo binfo;
  
	TSTR buf;
	IGameObject * obj = pGameNode->GetIGameObject();
	
	switch(obj->GetIGameType())
	{
		case IGameObject::IGAME_MESH:

			IGameMesh * gM = (IGameMesh*)obj;
			if(gM->InitializeData())
			{
				int numMod = obj->GetNumModifiers();
				if(numMod > 0)
				{
					for(int i=0;i<numMod;++i)
					{
						IGameModifier * m = obj->GetIGameModifier(i);
						if(m->IsSkin())
						{
							IGameSkin * skin = (IGameSkin*)m;
							for(int vertexId=0; vertexId<skin->GetNumOfSkinnedVerts(); ++vertexId)
							{
								Matrix3 matrix;
								const int numBones = skin->GetNumberOfBones(vertexId);
								int i;
								for(i=0;i<numBones; ++i)
								{
									ULONG boneId = skin->GetBoneID(vertexId,i);
									float weight = skin->GetWeight(vertexId,i);
									int intWeight = (int)(weight*256);

									//if we already have the same bone. we only need to add weight to it
									for (int j=0; j<pSubMesh->Vertics[vertexId].boneInfo.size(); j++)
									{
										if (boneId == pSubMesh->Vertics[vertexId].boneInfo[j].boneIndex)
										{
											pSubMesh->Vertics[vertexId].boneInfo[j].weight += weight;
											break;
										}
									}

									if (j < pSubMesh->Vertics[vertexId].boneInfo.size())
										continue; //the bone was add, continue to next bone

									if (intWeight <= 0)
									{										
										intWeight = 1;
										continue;
									}

									if (m_Bones.find(boneId) == m_Bones.end()) //we don't have this bone
									{
										IGameNode *pkBone = skin->GetIGameBone(vertexId, i);
										AddBone(pkBone);
										//continue;							
									}
									m_Bones[boneId].bUse = TRUE;
									binfo.boneIndex = boneId;
									binfo.weight = weight;
									pSubMesh->Vertics[vertexId].boneInfo.push_back(binfo);
								}
							}
						}
					}
				}
			}
			break;
	}
	

	/* 
	Object *pObject = pNode->GetObjectRef(); 
	if (pObject->SuperClassID() == GEN_DERIVOB_CLASS_ID) 
	{ 
		IDerivedObject *pDerivedObject = (IDerivedObject *)pObject; 
		int nMod = pDerivedObject->NumModifiers(); 
		for(i = 0; i < nMod; i++) 
		{ 
			Modifier *pModifier = pDerivedObject->GetModifier(i); 
			Class_ID cid= pModifier->ClassID();
			if (pModifier->ClassID() == SKIN_CLASSID) 
			{ 
				ISkin *pSkin = (ISkin*)pModifier->GetInterface(I_SKIN);             // get ISkin interface 
				if(pSkin) 
				{ 
					bonecount = pSkin->GetNumBones();
					for (m=0; m<bonecount; m++)
					{
						//get every bone
						pBone = pSkin->GetBone(m);
						//get every frame data
						cpt = 0;
						for (n=m_startTime; n<=m_endTime; n+=m_interval)
						{
							mat = pBone->GetNodeTM(n);
							decomp_affine(mat, &affp);
							trans.frameNo = cpt++;
							trans.mat = mat;
							bone.m_transList.push_back(trans);
						}
						m_Bones.push_back(bone);
					}

					//for every vertex in a submesh, find it's bones and weight;
					ISkinContextData* pSkinContext = pSkin->GetContextInterface(pNode);  // get context interface 
					if (pSkinContext != NULL && bonecount>0)
					{
						for (j=0; j<pSubMesh->Vertics.size(); j++)
						{
							n = pSkinContext->GetNumAssignedBones(j);
							for (m=0; m<n; m++)
							{				
								binfo.boneIndex = pSkinContext->GetAssignedBone(j,m); 
								binfo.weight = pSkinContext->GetBoneWeight(j, m);
								pSubMesh->Vertics[j].boneInfo.push_back(binfo);
							}
						}
					}
				}
			}
		}	
	}
	*/
}

void CMaxMesh::MergeSubmesh()
{
	int vcount = 0, bcount = 0;
	int tcount = 0;
	int mcount = 0;

	MaxFace face;
	MaxVertex vertex;
	int i,j;
	for (i=0; i<m_meshs.size(); i++)
	{
		/*
		
		for (j=0; j<m_meshs[i].m_Bones.size(); j++)
		{
			m_Bones.push_back(m_meshs[i].m_Bones[j]);
		}		*/

		for (j=0; j<m_meshs[i].Vertics.size(); j++)
		{
			vertex = m_meshs[i].Vertics[j];
			m_Vertics.push_back(vertex);
		}

		for (j=0; j<m_meshs[i].TexCoord.size(); j++)
		{
			m_TexCoord.push_back(m_meshs[i].TexCoord[j]);
		}

		for (j=0; j<m_meshs[i].Mtrl.size(); j++)
		{
			m_Matrials.push_back(m_meshs[i].Mtrl[j]);
		}
		
		for (j=0; j<m_meshs[i].Faces.size(); j++)
		{
			face = m_meshs[i].Faces[j];
			face.matid += mcount;
			face.t1 += tcount;
			face.t2 += tcount;
			face.t3 += tcount;
			face.v1 += vcount;
			face.v2 += vcount;
			face.v3 += vcount;
			m_Faces.push_back(face);
		}
		
		mcount += m_meshs[i].Mtrl.size();
		tcount += m_meshs[i].TexCoord.size();
		vcount += m_meshs[i].Vertics.size();
	}
	m_numFaces = m_Faces.size();
	m_numTexCoords = m_TexCoord.size();
	m_numVertics = m_Vertics.size();
	m_numMatrials = m_Matrials.size();
}


void CMaxMesh::GetBones()
{	
	for(int loop = 0; loop<m_pScene->GetTopLevelNodeCount();++loop)
	{
		IGameNode * pGameNode = m_pScene->GetTopLevelNode(loop);
		//check for selected state - we deal with targets in the light/camera section
		if(pGameNode->IsTarget())
			continue;
		RetrieveInverseMatrices(pGameNode);		
	}
}

void CMaxMesh::AddBone(IGameNode * node)
{	
	MaxBone bone;
	Matrix3 matrix;	
	FrameTransform trans;

	INode *onode = node->GetMaxNode();
	strcpy(bone.name, onode->GetName());
	int nodeid = node->GetNodeID();
	bone.boneIndex = m_Bones.size();
	
	Matrix3 nodematInv = node->GetWorldTM().ExtractMatrix3();
	nodematInv.Invert();
	
	int n=0;
	for (int time=m_startTime; time<=m_endTime; time+=m_interval, n++)
	{
		trans.frameNo = n;
		onode->EvalWorldState(time);
		matrix = onode->GetNodeTM(time);
		trans.mat = nodematInv*matrix;
		bone.m_transList.push_back(trans);
	}
	m_Bones[nodeid] = bone;
}

void CMaxMesh::RetrieveInverseMatrices(IGameNode * node)
{
	MaxBone bone;
	FrameTransform trans;
	int nodid = node->GetNodeID();
	bool temp = node->IsGroupOwner();
	int count = node->GetChildCount();
	IGameNode *par = node->GetNodeParent();

	if(!node->IsGroupOwner()
	   && (node->GetChildCount() > 0 || node->GetNodeParent() != 0))
	{
		IGameObject * obj = node->GetIGameObject();
		
		int nid = node->GetNodeID();
		switch(obj->GetIGameType())
		{
			case IGameObject::IGAME_BONE:
			case IGameObject::IGAME_HELPER:
			case IGameObject::IGAME_MESH:
				{
					Matrix3 nodematInv = node->GetWorldTM(m_startTime).ExtractMatrix3();
					nodematInv.Invert();
					IGameControl * pGameControl = node->GetIGameControl();
					IGameKeyTab Key;
					if(pGameControl->GetFullSampledKeys(Key,1,IGAME_TM, false))
					{
						if (Key.Count() > 0)
						{
							strcpy(bone.name, node->GetName());
							bone.m_transList.clear();
							int nodeid = node->GetNodeID();
							bone.boneIndex = m_Bones.size();
						
							for (int m=0; m<Key.Count(); m++)
							{
								trans.frameNo = m;
								
								trans.mat = Key[m].sampleKey.gval.ExtractMatrix3();
								trans.mat = nodematInv*Key[m].sampleKey.gval.ExtractMatrix3();
//								trans.mat = nodematInv*Key[m].sampleKey.gval.ExtractMatrix3();
								bone.m_transList.push_back(trans);
							}
							m_Bones[nodeid] = bone;
						}
					}
					break;
				}
		}
	}

	for(int i=0;i<node->GetChildCount();++i)
	{
		IGameNode * child = node->GetNodeChild(i);

		// we deal with targets in the light/camera section
		if(child->IsTarget())
			continue;

		RetrieveInverseMatrices(child);
	}

	node->ReleaseIGameObject();
}

int CMaxMesh::FindBoneIndex(int BoneID, vector<Bone> &bones)
{	
	for (int x=0; x<bones.size(); x++)
	{
				if (BoneID == bones[x].nodeId)
				{
					return x;
				}
	}
	return -1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -