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

📄 mrchelper.cpp

📁 游戏编程精粹2第一章源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		Matrix3 tm = GetBoneTM(pNode, 0);
		tm.Invert();
		MAXtoGL(tm, bHdr.inverseOrientationTM);
		bHdr.parentIdx = parentIdx;
		bHdr.childCnt = GetChildBoneCount(pNode);

		//set child's index vector
		if(bHdr.childCnt > 0)
		{
			BD[currIdx].childsVect.reserve(bHdr.childCnt);
			for (int i=0; i<pNode->NumberOfChildren(); ++i)
			{
				int chIdx = ProcessBoneStruct(pNode->GetChildNode(i),pRoot,currIdx, BD);		
				if (0<=chIdx)
					BD[currIdx].childsVect.push_back(chIdx);
			}
		}
		assert (BD[currIdx].childsVect.size() == BD[currIdx].Hdr.childCnt);
		return currIdx;
	}
	else 
	{
		for (int i=0; i<pNode->NumberOfChildren(); ++i)
			ProcessBoneStruct(pNode->GetChildNode(i),pRoot,-1, BD);
		return -1;
	}
}	

// ============================================================================
int ProcessBoneAnim (INode *pRoot, Interval range, ULONG sampleD, BoneData_t* BD)
{
	int keyCnt=0;
	int totbones = CountBones(pRoot);
	const ULONG start = TicksToMilliSec(range.Start());
	const ULONG end   = TicksToMilliSec(range.End());
		
	if (!totbones) return 0;

	// cycle throught every bone
	for (int idx=0; idx<totbones; ++idx) {
		// get bone node pointer
		INode* pBone = GetBoneByIndex(pRoot, idx);
			assert (IsBone(pBone));

		ULONG msec=0;
		//BD[idx].keysVect.reserve(end/sampleD);
		// grab keys for this bone
		for(msec = start; msec < end+sampleD; msec += sampleD)
		{	
			MRCbonekey_hdr KeyHdr;
			memset(&KeyHdr, 0, sizeof(MRCbonekey_hdr));
			
			//grab key time (in millisecs)
			if(msec > end) KeyHdr.time = end;
			else KeyHdr.time = msec;

			//grab bone animation matrix at time t
			Matrix3 tm;
			TimeValue t;
			t = MilliSecToTicks(msec);
			tm = GetBoneTM(pBone, t);		
			MAXtoGL(tm);

			// grab translation
			Point3 pos = tm.GetTrans();		
			KeyHdr.pos[0] = pos.x;
			KeyHdr.pos[1] = pos.y;
			KeyHdr.pos[2] = pos.z;

			// grab rotation union quaternion
			Quat quat(tm);
			quat.Normalize();
			KeyHdr.quat[0] = quat.x;
			KeyHdr.quat[1] = quat.y;
			KeyHdr.quat[2] = quat.z;
			KeyHdr.quat[3] = quat.w;

			BD[idx].keysVect.push_back(KeyHdr);
		}
	}
	keyCnt = BD[0].keysVect.size();
	return keyCnt;
}


// ============================================================================
// ============================================================================
bool GetPhysiqueWeights(INode *pNode, INode *pRoot, Modifier *pMod, BoneData_t *BD)
{
	// create a Physique Export Interface for the given Physique Modifier
	IPhysiqueExport *phyInterface = (IPhysiqueExport*)pMod->GetInterface(I_PHYINTERFACE);
	if(phyInterface)
	{
		// create a ModContext Export Interface for the specific node of the Physique Modifier
		IPhyContextExport *modContextInt = (IPhyContextExport*)phyInterface->GetContextInterface(pNode);
		// needed by vertex interface (only Rigid one supported for now)
		modContextInt->ConvertToRigid(TRUE);
		// more than a single bone per vertex
		modContextInt->AllowBlending(TRUE);

		if(modContextInt)
		{
			int totalVtx = modContextInt->GetNumberVertices();
			for(int i = 0; i < totalVtx; i++)
			{
				//get i-th vertex
				IPhyVertexExport *vtxInterface = (IPhyVertexExport*)modContextInt->GetVertexInterface(i);
				if(vtxInterface)
				{
					int vtxType = vtxInterface->GetVertexType();
					if(vtxType == RIGID_TYPE)
					{
						//get bone
						INode *boneNode = ((IPhyRigidVertex*)vtxInterface)->GetNode();
						int boneIdx = GetBoneIndex(pRoot, boneNode);

						//Build vertex data
						MRCweight_hdr wdata;
						wdata.vertIdx = i;
						wdata.weight = 1.0f;
						//Insert into proper bonedata
						BD[boneIdx].weightsVect.push_back(wdata);
						//update vertexWeightCnt for that bone
						BD[boneIdx].Hdr.vertexCnt = BD[boneIdx].weightsVect.size();
					}
					else if(vtxType == RIGID_BLENDED_TYPE)
					{
						IPhyBlendedRigidVertex *vtxBlendedInt = (IPhyBlendedRigidVertex*)vtxInterface;
						for(int j = 0; j < vtxBlendedInt->GetNumberNodes(); j++)
						{
							//get j-th bone
							INode *boneNode = vtxBlendedInt->GetNode(j);
							//whose index is boneIdx
							int boneIdx = GetBoneIndex(pRoot, boneNode);
	
							//Build vertex data
							MRCweight_hdr wdata;
							wdata.vertIdx = i;
							wdata.weight = vtxBlendedInt->GetWeight(j);
							
							//check vertex existence for this bone
							bool notfound = true;
							for (int v=0; notfound && v<BD[boneIdx].weightsVect.size();v++)
							{
								//update found vertex weight data for that bone
								if (BD[boneIdx].weightsVect[v].vertIdx == wdata.vertIdx)
									{
										BD[boneIdx].weightsVect[v].weight += wdata.weight;
										notfound = false;
									}
							}

							if (notfound)
							{
								//Add a new vertex weight data into proper bonedata
								BD[boneIdx].weightsVect.push_back(wdata);
								//update vertexWeightCnt for that bone
								BD[boneIdx].Hdr.vertexCnt = BD[boneIdx].weightsVect.size();
							}
						}
					}
				}
			}
			phyInterface->ReleaseContextInterface(modContextInt);
		}
		pMod->ReleaseInterface(I_PHYINTERFACE, phyInterface);
	}
	return true;
}

// ============================================================================
// ============================================================================
// export to MRC file every BoneData entry
bool ExportBoneData(BoneData_t *BD,int boneCnt, int keyCnt, FILE *out)
{	
// write weights in bone major format
	//i-th bone
	for(int i = 0; i < boneCnt; i++)
	{
		long BoneHdrPos = ftell(out);

		fseek(out, sizeof(MRCbone_hdr), SEEK_CUR);
		
		// write the child bone index list
		for (int j=0; j<BD[i].Hdr.childCnt; j++)
		{			
			fwrite(&BD[i].childsVect[j], sizeof(int), 1, out);
		}			
		BD[i].Hdr.boneWeightsOfs = ftell(out);

		//BoneWeight data export
		int weightCnt = BD[i].Hdr.vertexCnt;
		
		//write data for j.th vertex who belongs to i-th bone
		for( j = 0; j < weightCnt; j++)
		{
			MRCweight_hdr &vertWeight = BD[i].weightsVect[j];
			fwrite(&vertWeight, sizeof(MRCweight_hdr), 1, out);
		}
		BD[i].Hdr.boneKeysOfs = ftell(out);
				
		//BoneANIMATION data export
		for( j = 0; j < keyCnt; j++)
		{
			MRCbonekey_hdr &boneKey = BD[i].keysVect[j];
			fwrite(&boneKey, sizeof(MRCbonekey_hdr), 1, out);
		}

		long endPos = ftell(out);
		// write down bone header
		fseek(out, BoneHdrPos, SEEK_SET);
		fwrite(&BD[i].Hdr, sizeof(MRCbone_hdr), 1, out);
		fseek(out, endPos, SEEK_SET);
	}
	return true;
}

// ============================================================================
// dummy view used internally by WriteMesh
class NullView : public View {
public:
	Point2 ViewToScreen(Point3 p)
	{ 
		return Point2(p.x,p.y); 
	}

	NullView() {
		worldToView.IdentityMatrix();
		screenW=800.0f; screenH = 600.0f;
	}

};

static NullView nullView;
// ============================================================================
// get and export mesh data to file
bool ExportMesh (INode* pNode, FILE *out)
{
	if ((!pNode)||(!IsMesh(pNode))) return false;

	MRCmesh_hdr mHdr;
	memset(&mHdr, 0, sizeof(MRCmesh_hdr));

	Matrix3 tm = pNode->GetObjectTM(0);
	ObjectState os = pNode->EvalWorldState(0);
	int needDelete;
	Mesh& mesh = *(( (GeomObject*) os.obj)->GetRenderMesh(0,pNode,nullView,needDelete));
	
	long startPos = ftell(out);
	fseek(out, sizeof(MRCmesh_hdr), SEEK_CUR);

	// write the mesh vertices
	mHdr.vertCnt = mesh.getNumVerts();
	mHdr.vertOfs = ftell(out);
	for(int i = 0; i < mHdr.vertCnt; i++)
	{
		Point3 pnt = mesh.getVert(i) * tm;			//premultiply in MAX
		MAXtoGL(pnt);								//useful coordinate transformation
		fwrite(&pnt.x, sizeof(float), 3, out);
	}

	// write vertex normals
	mesh.buildNormals();
	mHdr.normCnt = mesh.getNumVerts();
	mHdr.normOfs = ftell(out);
	for(i = 0; i < mHdr.normCnt; i++)
	{ 
		// normals are taken from a unique smoothing group
		Point3 norm = Normalize(mesh.getNormal(i));
		MAXtoGL(norm);
		fwrite(&norm.x, sizeof(float), 3, out);
	}

	// build and write faces
	mHdr.faceCnt = mesh.getNumFaces();
	mHdr.faceOfs = ftell(out);
	for(i = 0; i < mHdr.faceCnt; i++)
	{
		MRCface_hdr fHdr;
		memset(&fHdr, 0, sizeof(MRCface_hdr));

		fHdr.vert[0] = mesh.faces[i].v[0];
		fHdr.vert[1] = mesh.faces[i].v[1];
		fHdr.vert[2] = mesh.faces[i].v[2];
		// TODO: insert normals
		fwrite(&fHdr, sizeof(MRCface_hdr), 1, out);
	}

	long endPos = ftell(out);
	fseek(out, startPos, SEEK_SET);
	fwrite(&mHdr, sizeof(MRCmesh_hdr), 1, out);
	fseek(out, endPos, SEEK_SET);
	return true;
}
// ============================================================================
// ============================================================================

⌨️ 快捷键说明

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