Пример #1
0
int PreCacheFrameOffsets(MFMADDecoder *pDecoder)
{
	MP3Header header;
	unsigned char headerBuffer[10];
	int sampleRate = 0;

	uint32 filePos = MFFile_Tell(pDecoder->pFile);
	while(MFFile_Read(pDecoder->pFile, headerBuffer, 4))
	{
		int validHeader = ReadMP3Header(&header, headerBuffer);
		sampleRate = header.samplerate;

		if(validHeader != 1)
		{
			if(pDecoder->frameCount >= pDecoder->numFrameOffsetsAllocated)
			{
				pDecoder->numFrameOffsetsAllocated *= 2;
				pDecoder->pFrameOffsets = (uint32*)MFHeap_Realloc(pDecoder->pFrameOffsets, sizeof(uint32) * pDecoder->numFrameOffsetsAllocated);
			}
			pDecoder->pFrameOffsets[pDecoder->frameOffsetCount++] = filePos;
			++pDecoder->frameCount;

			MFFile_Seek(pDecoder->pFile, header.frameSize-4, MFSeek_Current);
		}
		else
		{
			// check if we have some other header.. ID3?
			if(!MFString_CaseCmpN((char*)headerBuffer, "TAG", 3))
			{
				// read ID3 v1? ...

				// skip past it for now...
				MFFile_Seek(pDecoder->pFile, 128-4, MFSeek_Current);
			}
			else if(!MFString_CaseCmpN((char*)headerBuffer, "ID3", 3))
			{
				// ID3 v2...
				MFFile_Read(pDecoder->pFile, headerBuffer + 4, 6);
				uint32 size = GetSynchSafeInt(headerBuffer + 6);

				// skip ID3 v2 data
				MFFile_Seek(pDecoder->pFile, size, MFSeek_Current);
			}
			else
			{
				// lost sync? :/
				return 0;
			}
		}

		filePos = MFFile_Tell(pDecoder->pFile);
	}

	return sampleRate;
}
Пример #2
0
void GotoSection(int cancel, const char *pString)
{
	if(cancel || !*pString) return;

	const char *pTest = pString;
	while(*pTest && (MFIsNumeric(*pTest) || *pTest == '.'))
		++pTest;

	int res = gEditor.pSong->GetRes();

	if(pTest > pString)
	{
		if(!*pTest)
		{
			OffsetToMeasureAndBeat((int)((float)atof(pString) * res), &gEditor.measure, &gEditor.beat);
			return;
		}
		if(!MFString_CaseCmp(pTest, "s"))
		{
			float time = (float)atof(pString);
			OffsetToMeasureAndBeat(gEditor.pSong->CalculateTickAtTime((int64)(time*1000000.0f)), &gEditor.measure, &gEditor.beat);
			return;
		}
		else if(!MFString_CaseCmp(pTest, "ms"))
		{
			float time = (float)atof(pString);
			OffsetToMeasureAndBeat(gEditor.pSong->CalculateTickAtTime((int64)(time*1000.0f)), &gEditor.measure, &gEditor.beat);
			return;
		}
	}

	// find section by name
	size_t len = MFString_Length(pString);

	GHEvent *pSE = gEditor.pSong->events.First();

	while(pSE)
	{
		if(!MFString_CaseCmpN(pSE->GetString(), "section ", 8) && !MFString_CaseCmpN(&pSE->GetString()[8], pString, len))
		{
			OffsetToMeasureAndBeat(pSE->tick, &gEditor.measure, &gEditor.beat);
			return;
		}

		pSE = pSE->Next();
	}
}
Пример #3
0
void ParseXFile(char *pFilePtr)
{
	if(MFString_CaseCmpN(pFilePtr, "xof ", 4))
	{
		MFDebug_Warn(4, "File is not an .x file\n");
		return;
	}

	if(!MFString_CaseCmpN(&pFilePtr[8], "txt ", 4))
	{
		pFilePtr += 16;

		LoadTextXFile(pFilePtr);
	}
	else if(!MFString_CaseCmpN(&pFilePtr[8], "bin ", 4))
	{
		MFDebug_Warn(4, "Binary .x files not yet supported...\n");
	}
	else
	{
		MFDebug_Warn(4, "Not a valid .x file...\n");
	}
}
Пример #4
0
char* ReadGeomChunk(char *pFilePtr, char *pToken)
{
	if(!MFString_CaseCmp(pToken, "*NODE_NAME"))
	{
		char *pNodeName;

		pFilePtr = GetString(pFilePtr, &pNodeName);

		if(!MFString_CaseCmpN(pNodeName, "z_", 2))
		{
			// node is bone
			nodeType = 2;
		}
		else if(!MFString_CaseCmpN(pNodeName, "r_", 2))
		{
			// node is refPoint
			nodeType = 4;
		}
		else
		{
			// node is mesh
			nodeType = 1;
		}

		// if exporting geometry, add a subobject
		if(nodeType & 1)
		{
			pSub = &pModel->GetMeshChunk()->subObjects.push();

			if(MFString_Length(pNodeName) > 63)
			{
				MFDebug_Warn(3, MFStr("Error: More than 64 characters in mesh name, \"%s\"", pNodeName));
			}
			else
				pSub->name = pNodeName;
		}

		// if exporting a bone, add a bone
		if(nodeType & 2)
		{
			pBone = &pModel->GetSkeletonChunk()->bones.push();
		}

		// if exporting a refPoint, add a refPoint
		if(nodeType & 4)
		{
			pRefPoint = &pModel->GetRefPointChunk()->refPoints.push();

			if(MFString_Length(pNodeName) > 63)
			{
				MFDebug_Warn(3, MFStr("Error: More than 64 characters in refPoint name, \"%s\"", pNodeName));
			}
			else
                pRefPoint->name = pNodeName;
		}
	}
	else if(!MFString_CaseCmp(pToken, "*NODE_PARENT"))
	{
		if(nodeType & 2)
		{
			char *pParentName;

			pFilePtr = GetString(pFilePtr, &pParentName);

			if(MFString_Length(pParentName) > 63)
			{
				MFDebug_Warn(3, MFStr("Error: More than 64 characters in bone parent name, \"%s\"", pParentName));
				return pFilePtr;
			}

			pBone->parentName = pParentName;
		}
	}
	else if(!MFString_CaseCmp(pToken, "*NODE_TM"))
	{
		if(nodeType & 2)
		{
			pFilePtr = ProcessBlock(pFilePtr, "*NODE_TM", ReadBone);
		}
	}
	else if(!MFString_CaseCmp(pToken, "*MESH"))
	{
		if(nodeType & 1)
		{
			pFilePtr = ProcessBlock(pFilePtr, "*MESH", ReadMesh);
		}
	}
	else if(!MFString_CaseCmp(pToken, "*MATERIAL_REF"))
	{
		if(nodeType & 1)
		{
			pFilePtr = GetInt(pFilePtr, &pSub->matSubobjects[0].materialIndex);
		}
	}
	else
	{
		MFDebug_Warn(3, MFStr("Unknown token: %s", pToken));
	}

	return pFilePtr;
}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
0
const char *ParseMesh(const char *pText, const MFMatrix &mat, const char *pFrameName)
{
	// read name
	char meshName[64];
	const char *pMeshName = GetNextToken(pText, &pText, meshName);

	if(!MFString_Compare(pMeshName, "{"))
		pMeshName = pFrameName;
	else
		SkipToken(pText, "{");

	if(MFString_CaseCmpN(pMeshName, "m_", 2))
	{
		// not a mesh!
		SkipSection(pText);
		return pText;
	}

	F3DMeshChunk *pMesh = pModel->GetMeshChunk();
	F3DSubObject &sub = pMesh->subObjects.push();

	MFString_Copy(sub.name, pMeshName);

	// get num positions
	int numPositions = GetInt(pText, &pText);

	sub.positions.resize(numPositions);

	// read positions
	for(int a=0; a<numPositions; a++)
	{
		sub.positions[a].x = GetFloat(pText, &pText);
		sub.positions[a].y = GetFloat(pText, &pText);
		sub.positions[a].z = GetFloat(pText, &pText);

		sub.positions[a] = ApplyMatrixH(sub.positions[a], mat);

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

	// get num faces
	int numFaces = GetInt(pText, &pText);

	// see if we have a material face mapping
	int *pMatFaces = ParseMaterialList(pText, sub, numFaces);

	// read faces
	int face[16], numVerts[16], numTris[16];
	MFZeroMemory(numVerts, sizeof(numVerts));
	MFZeroMemory(numTris, sizeof(numTris));
	for(int a=0; a<numFaces; a++)
	{
		int matSub = pMatFaces ? pMatFaces[a] : 0;
		F3DMaterialSubobject &matsub = sub.matSubobjects[matSub];

		int numPoints = GetInt(pText, &pText);
		MFDebug_Assert(numPoints < 16, "Exceeded maximum 16 points per face...");
		GetIntArray(pText, face, numPoints, &pText);

		int firstVert = numVerts[matSub];
		numVerts[matSub] += numPoints;
		if(matsub.vertices.size() < numVerts[matSub])
			matsub.vertices.resize(numVerts[matSub]);

		int firstTri = numTris[matSub];
		numTris[matSub] += numPoints-2;
		if(matsub.triangles.size() < numTris[matSub])
			matsub.triangles.resize(numTris[matSub]);

		for(int b=0; b<numPoints; b++)
			matsub.vertices[firstVert+b].position = face[b];

		for(int b=0; b<numPoints-2; b++)
		{
			matsub.triangles[firstTri+b].v[0] = firstVert+0;
			matsub.triangles[firstTri+b].v[1] = firstVert+b+1;
			matsub.triangles[firstTri+b].v[2] = firstVert+b+2;
		}

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

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

	while(MFString_Compare(pTok, "}"))
	{
		if(!MFString_Compare(pTok, "MeshMaterialList"))
		{
			SkipSection(pText);
		}
		else if(!MFString_Compare(pTok, "MeshNormals"))
		{
			pText = ParseNormals(pText, sub, mat, numFaces, pMatFaces);
		}
		else if(!MFString_Compare(pTok, "MeshTextureCoords"))
		{
			pText = ParseTexCoords(pText, sub, numPositions);
		}
		else if(!MFString_Compare(pTok, "MeshVertexColors"))
		{
			pText = ParseColours(pText, sub, numPositions);
		}
		else if(!MFString_Compare(pTok, "XSkinMeshHeader"))
		{
			SkipToken(pText, "{");

			// get num positions
			int nMaxSkinWeightsPerVertex = GetInt(pText, &pText);
			int nMaxSkinWeightsPerFace = GetInt(pText, &pText);
			int nBones = GetInt(pText, &pText);

			// not yet sure how this helps...
/*
			for(int m=0; m<sub.matSubobjects.size(); m++)
			{
				sub.matSubobjects[m].numBones = nBones;
			}
*/

			SkipToken(pText, "}");
		}
		else if(!MFString_Compare(pTok, "SkinWeights"))
		{
			pText = ParseSkinWeights(pText, sub, numPositions);
		}
		else if(!MFString_Compare(pTok, "DeclData"))
		{
			SkipSection(pText);
		}
		else
		{
			MFDebug_Warn(4, MFStr("Unknown token '%s'\n", pTok));
			SkipSection(pText);
		}

		pTok = GetNextToken(pText, &pText);
	}

	// we should order the bone weights into the most to least weighting.

	return pText;
}