예제 #1
0
void Array::Load(
	lpxmlnode						 pNode)
{
	m_id		= GetAttributeStringValue("id", pNode);
	m_count		= GetAttributeIntegerValue("count", pNode);

	printf("Loading %s\n", m_id.c_str());

	std::string type = pNode->name();
	if(type == "float_array") {
		GetFloatArray(m_floats,	GetSubnodeStringValue("float_array", pNode));
	} else if(type == "Name_array") {
		GetNameArray(m_names, GetSubnodeStringValue("Name_array", pNode));
	}
}
예제 #2
0
const char *ParseFrame(const char *pText, const MFMatrix &mat, int parentID)
{
	char frameName[64];
	const char *pName = GetNextToken(pText, &pText, frameName);

	MFMatrix worldMatrix = mat;

	F3DBone *pBone = NULL;

	if(!MFString_CaseCmpN(pName, "bn_", 3) || !MFString_CaseCmpN(pName, "z_", 2))
	{
		int boneID = pModel->GetSkeletonChunk()->bones.size();
		pBone = &pModel->GetSkeletonChunk()->bones[boneID];

		F3DBone *pParent = parentID == -1 ? NULL : &pModel->GetSkeletonChunk()->bones[parentID];
		parentID = boneID;

		MFString_Copy(pBone->name, pName);
		MFString_Copy(pBone->parentName, pParent ? pParent->name : "");

		pBone->worldMatrix = mat;
	}

	if(MFString_Compare(pName, "{"))
		SkipToken(pText, "{");

	const char *pTok = GetNextToken(pText, &pText);

	while(MFString_Compare(pTok, "}"))
	{
		if(!MFString_Compare(pTok, "Frame"))
		{
			pText = ParseFrame(pText, worldMatrix, parentID);
		}
		else if(!MFString_Compare(pTok, "FrameTransformMatrix"))
		{
			SkipToken(pText, "{");

			MFMatrix localMatrix;
			GetFloatArray(pText, (float*)&localMatrix, 16, &pText);

			worldMatrix.Multiply(localMatrix, worldMatrix);

			if(pBone)
			{
				pBone->boneMatrix = localMatrix;
				pBone->worldMatrix = worldMatrix;
			}

			SkipToken(pText, ";");
			SkipToken(pText, "}");
		}
		else if(!MFString_Compare(pTok, "Mesh"))
		{
			gMeshChunks.push(XMeshChunk::Create(worldMatrix, pText, pName));
			SkipSection(pText);
		}
		else
		{
			MFDebug_Warn(4, MFStr("Unexpected token '%s'\n", pTok));
			SkipSection(pText);
		}

		pTok = GetNextToken(pText, &pText);
	}

	return pText;
}
예제 #3
0
const char *ParseAnimation(const char *pText)
{
	const char *pAnimName = GetNextToken(pText, &pText);

	if(MFString_Compare(pAnimName, "{"))
		SkipToken(pText, "{");

	char bone[64];
	int numFrames = 0;

	float *pFrameTimes = NULL;
	MFQuaternion *pQuats = NULL;
	MFVector *pScale = NULL;
	MFVector *pTrans = NULL;
	MFMatrix *pMats = NULL;
	MFVector tQuat;

	const char *pTok = GetNextToken(pText, &pText);

	while(MFString_Compare(pTok, "}"))
	{
		if(!MFString_Compare(pTok, "AnimationKey"))
		{
			SkipToken(pText, "{");

			int type = GetInt(pText, &pText);
			numFrames = GetInt(pText, &pText);

			pFrameTimes = (float*)MFHeap_Alloc(sizeof(float)*numFrames);

			switch(type)
			{
				case KT_Quat:
					pQuats = (MFQuaternion*)MFHeap_Alloc(sizeof(MFQuaternion)*numFrames);
					break;
				case KT_Scale:
					pScale = (MFVector*)MFHeap_Alloc(sizeof(MFVector)*numFrames);
					break;
				case KT_Translation:
					pTrans = (MFVector*)MFHeap_Alloc(sizeof(MFVector)*numFrames);
					break;
				case KT_Matrix:
					pMats = (MFMatrix*)MFHeap_Alloc(sizeof(MFMatrix)*numFrames);
					break;
			}

			// read data
			for(int a=0; a<numFrames; a++)
			{
				int frame = GetInt(pText, &pText);
				pFrameTimes[a] = (float)frame;

				int numComponents = GetInt(pText, &pText);

				switch(type)
				{
					case KT_Quat:
						MFDebug_Assert(numComponents == 4, "Required 4 components for a quaternion.");
						GetFloatArray(pText, tQuat, numComponents, &pText);
						((MFVector&)pQuats[a]).Swizzle(tQuat, SW_Y|SW_NEG, SW_Z|SW_NEG, SW_W|SW_NEG, SW_X|SW_NEG);
						break;
					case KT_Scale:
						MFDebug_Assert(numComponents == 3, "Required 3 components for a scale.");
						GetFloatArray(pText, (float*)&pScale[a], numComponents, &pText);
						break;
					case KT_Translation:
						MFDebug_Assert(numComponents == 3, "Required 3 components for a translation.");
						GetFloatArray(pText, (float*)&pTrans[a], numComponents, &pText);
						break;
					case KT_Matrix:
						MFDebug_Assert(numComponents == 16, "Required 16 components for a matrix.");
						GetFloatArray(pText, (float*)&pMats[a], numComponents, &pText);
						break;
				}
				SkipToken(pText, ";");

				if(a < numFrames-1)
					SkipToken(pText, ",");
			}
			SkipToken(pText, ";");

			SkipToken(pText, "}");
		}
		else if(!MFString_Compare(pTok, "{"))
		{
			GetNextToken(pText, &pText, bone);
			SkipToken(pText, "}");
		}
		else
		{
			MFDebug_Warn(4, MFStr("Unexpected token '%s'\n", pTok));
			SkipSection(pText);
		}

		pTok = GetNextToken(pText, &pText);
	}

	if(!MFString_CaseCmpN(bone, "bn_", 3) || !MFString_CaseCmpN(bone, "z_", 2))
	{
		// copy data to bone
		F3DAnimation &anim = pModel->GetAnimationChunk()->anims.push();

		anim.boneID = pModel->GetSkeletonChunk()->FindBone(bone);
		if(anim.boneID == -1)
		{
			MFDebug_Warn(4, MFStr("Bone '%s' not found..\n", bone));
			return pText;
		}

		anim.minTime = pFrameTimes[0];
		anim.maxTime = pFrameTimes[numFrames-1];

		for(int a=0; a<numFrames; a++)
		{
			anim.keyframes[a].time = pFrameTimes[a];

			if(pMats)
			{
				anim.keyframes[a].key = pMats[a];

//				anim.keyframes[a].scale = MakeVector(pMats[a].GetXAxis().Magnitude3(), pMats[a].GetYAxis().Magnitude3(), pMats[a].GetZAxis().Magnitude3(), 1.0f);
//				pMats[a].Normalise();
//				anim.keyframes[a].rotation = pMats[a].GetRotationQ();
//				anim.keyframes[a].translation = pMats[a].GetTrans();
			}
			else
			{
				anim.keyframes[a].key.SetRotationQ(pQuats ? pQuats[a] : MFQuaternion::identity);
				if(pScale)
					anim.keyframes[a].key.Scale(pScale[a]);
				anim.keyframes[a].key.SetTrans3(pTrans ? pTrans[a] : MFVector::identity);

//				anim.keyframes[a].rotation = pQuats ? pQuats[a] : MFQuaternion::identity;
//				anim.keyframes[a].scale = pScale ? pScale[a] : MFVector::one;
//				anim.keyframes[a].translation = pTrans ? pTrans[a] : MFVector::identity;
			}
		}
	}

	return pText;
}
예제 #4
0
const char *ParseSkinWeights(const char *pText, F3DSubObject &sub, int numPositions)
{
	SkipToken(pText, "{");

	const char *pName = GetString(pText, &pText);

	// get num weights
	int numWeights = GetInt(pText, &pText);

	if(numWeights > 0)
		MFDebug_Assert(numWeights == numPositions, "Number of weights's does not match the number of verts in the mesh.");

	int *pIndices = numWeights > 0 ? (int*)MFHeap_Alloc(sizeof(int) * numWeights) : NULL;
	GetIntArray(pText, pIndices, numWeights, &pText);

	float *pWeights = numWeights > 0 ? (float*)MFHeap_Alloc(sizeof(float) * numWeights) : NULL;
	GetFloatArray(pText, pWeights, numWeights, &pText);

	MFMatrix matrixOffset;
	GetFloatArray(pText, (float*)&matrixOffset, 16, &pText);
	SkipToken(pText, ";");

	SkipToken(pText, "}");

	if(numWeights > 0)
	{
		// now we want to do something with all this data...
		F3DSkeletonChunk *pSC = pModel->GetSkeletonChunk();

		int boneID = pSC->FindBone(pName);

		// if boneID == -1 we dont want to process this data
		if(boneID == -1)
			return pText;

		// check weights are sequential
		for(int a=0; a<numWeights; a++)
			MFDebug_Assert(a == pIndices[a], "Weight array is not sequential!");

		for(int a=0; a<sub.matSubobjects.size(); a++)
			++sub.matSubobjects[a].numBones;

		// map to faces
		for(int m=0; m<sub.matSubobjects.size(); m++)
		{
			int totalVerts = sub.matSubobjects[m].vertices.size();
			for(int a=0; a<totalVerts; a++)
			{
				F3DVertex &v = sub.matSubobjects[m].vertices[a];

				int i = v.position;
				const int numBones = sizeof(v.bone)/sizeof(v.bone[0]);

				if(pWeights[i] != 0.0f)
				{
					for(int b=0; b<numBones; b++)
					{
						if(v.bone[b] == -1)
						{
							v.weight[b] = pWeights[i];
							v.bone[b] = boneID;
							pSC->bones[boneID].bIsSkinned = true;
							sub.matSubobjects[m].maxWeights = MFMax(sub.matSubobjects[m].maxWeights, b+1);
							break;
						}
					}
				}
			}
		}
	}

	return pText;
}