Beispiel #1
0
// read/write a file to a filesystem
MF_API char* MFFileSystem_Load(const char *pFilename, size_t *pBytesRead, size_t extraBytes)
{
	char *pBuffer = NULL;

	MFFile *hFile = MFFileSystem_Open(pFilename, MFOF_Read|MFOF_Binary);
	if(hFile)
	{
		uint64 size = MFFile_GetSize(hFile);

		if(size > 0)
		{
#if defined(MF_32BIT)
			if(size >= 1LL << 32)
			{
				MFDebug_Warn(1, MFStr("File is larger than the available address space!", pFilename));
				return NULL;
			}
#endif

			pBuffer = (char*)MFHeap_Alloc((size_t)size + extraBytes);

			size_t bytesRead = MFFile_Read(hFile, pBuffer, (size_t)size);

			if(extraBytes > 0)
				pBuffer[size] = 0;

			if(pBytesRead)
				*pBytesRead = bytesRead;
		}

		MFFile_Close(hFile);
	}

	return pBuffer;
}
Beispiel #2
0
// if file does not exist, GetSize returns 0, however, a zero length file can also return 0 use 'Exists' to confirm
MF_API uint64 MFFileSystem_GetSize(const char *pFilename)
{
	MFCALLSTACK;

	uint64 size = 0;

	MFFile *hFile = MFFileSystem_Open(pFilename, MFOF_Read|MFOF_Binary);
	if(hFile)
	{
		size = MFFile_GetSize(hFile);
		MFFile_Close(hFile);
	}

	return size;
}
MF_API MFAnimation* MFAnimation_Create(const char *pFilename, MFModel *pModel)
{
	MFAnimationTemplate *pTemplate = MFAnimation_FindTemplate(pFilename);

	if(!pTemplate)
	{
		size_t size = 0;
		pTemplate = (MFAnimationTemplate*)MFModelInternal_PendingAnimationTemplate(&size);

		if(!pTemplate)
		{
			MFFile *hFile = MFFileSystem_Open(MFStr("%s.anm", pFilename), MFOF_Read|MFOF_Binary);

			if(hFile)
			{
				size = (size_t)MFFile_GetSize(hFile);

				if(size > 0)
				{
					char *pTemplateData;

					// allocate memory and load file
					pTemplateData = (char*)MFHeap_Alloc(size + MFString_Length(pFilename) + 1);
					MFFile_Read(hFile, pTemplateData, size);

					pTemplate = (MFAnimationTemplate*)pTemplateData;

					// check ID string
					MFDebug_Assert(pTemplate->hash == MFMAKEFOURCC('A', 'N', 'M', '2'), "Incorrect MFAnimation version.");
				}

				MFFile_Close(hFile);
			}
		}

		if(!pTemplate)
			return NULL;

		pFilename = MFString_Copy((char*)pTemplate + size, pFilename);

		MFAnimation_FixUp(pTemplate, true);
		MFResource_AddResource(pTemplate, MFRT_AnimationTemplate, MFUtil_HashString(pFilename) ^ 0xA010A010, pFilename);
	}

	// get the model bone chunk
	MFModelDataChunk *pBoneChunk = MFModel_GetDataChunk(pModel->pTemplate, MFChunkType_Bones);
	MFDebug_Assert(pBoneChunk, "Cant apply animation to a model with no skeleton!");

	// create and init instance
	MFAnimation *pAnimation;
	size_t bytes = MFALIGN16(sizeof(MFAnimation)) + sizeof(MFMatrix)*pBoneChunk->count + sizeof(int)*pBoneChunk->count + sizeof(MFAnimationCurrentFrame)*pBoneChunk->count;
	pAnimation = (MFAnimation*)MFHeap_Alloc(bytes);
	pAnimation->pModel = pModel;
	pAnimation->pTemplate = pTemplate;

	// add animation to model animation list
	pModel->pAnimation = pAnimation;

	// get bones pointer from model (for convenience)
	pAnimation->pBones = (MFModelBone*)pBoneChunk->pData;
	pAnimation->numBones = pBoneChunk->count;

	// set matrices to identity
	pAnimation->pMatrices = (MFMatrix*)MFALIGN16(&pAnimation[1]);
	for(int a=0; a<pBoneChunk->count; a++)
	{
		pAnimation->pMatrices[a] = MFMatrix::identity;
	}

	MFStateConstant_AnimationMatrices animMats;
	animMats.pMatrices = pAnimation->pMatrices;
	animMats.numMatrices = pAnimation->numBones;
	MFStateBlock_SetAnimMatrices(pModel->pEntityState, animMats);

	// build bone to animation stream mapping
	pAnimation->pBoneMap = (int*)MFALIGN16(&pAnimation->pMatrices[pBoneChunk->count]);
	for(int a=0; a<pBoneChunk->count; a++)
	{
		const char *pBoneName = MFModel_GetBoneName(pModel, a);

		// find bone in animation
		pAnimation->pBoneMap[a] = -1;
		for(uint32 b=0; b<pTemplate->numBones; b++)
		{
			if(!MFString_CaseCmp(pBoneName, pTemplate->pBones[b].pBoneName))
			{
				pAnimation->pBoneMap[a] = b;
				break;
			}
		}
	}

	pAnimation->pCustomMatrices = NULL;
	pAnimation->blendLayer.frameTime = pAnimation->pTemplate->startTime;

	pAnimation->blendLayer.pCurFrames = (MFAnimationCurrentFrame*)&pAnimation->pBoneMap[pBoneChunk->count];
	MFZeroMemory(pAnimation->blendLayer.pCurFrames, sizeof(MFAnimationCurrentFrame)*pBoneChunk->count);

	return pAnimation;
}
Beispiel #4
0
MF_API MFModel* MFModel_Create(const char *pFilename)
{
	const char* pOriginalFilename = pFilename;

	// see if it's already loaded
	MFModelPool::Iterator it = gModelBank.Get(pOriginalFilename);
	MFModelTemplate *pTemplate = it ? *it : NULL;

	if(!pTemplate)
	{
		char *pTemplateData = NULL;

		MFFile *hFile = MFFileSystem_Open(MFStr("%s.mdl", pFilename), MFOF_Read|MFOF_Binary);
		if(hFile)
		{
			int64 size = MFFile_GetSize(hFile);

			if(size > 0)
			{
				// allocate memory and load file
				pTemplateData = (char*)MFHeap_Alloc((size_t)size + MFString_Length(pFilename) + 1);
				MFFile_Read(hFile, pTemplateData, (size_t)size);
				MFFile_Close(hFile);

				MFString_Copy(&pTemplateData[size], pFilename);
				pFilename = &pTemplateData[size];
			}
		}
		else
		{
#if defined(ALLOW_LOAD_FROM_SOURCE_DATA)
			// try to load from source data
			const char * const pExt[] = { ".f3d", ".dae", ".x", ".ase", ".obj", ".md2", ".md3", ".me2", NULL };
			const char * const *ppExt = pExt;
			MFIntModel *pIM = NULL;
			while(!pIM && *ppExt)
			{
				MFString tempFilename = MFString::Format("%s%s", pFilename, *ppExt);
				pIM = MFIntModel_CreateFromFile(tempFilename.CStr());
				if(pIM)
				{
					pFilename = MFString_Copy((char*)MFHeap_Alloc(tempFilename.NumBytes()+1), tempFilename.CStr());
					break;
				}
				++ppExt;
			}

			if(pIM)
			{
				MFIntModel_Optimise(pIM);

				size_t size;
				MFIntModel_CreateRuntimeData(pIM, (void**)&pTemplateData, &size, MFSystem_GetCurrentPlatform());

				MFFile *pFile = MFFileSystem_Open(MFStr("cache:%s.mdl", pOriginalFilename), MFOF_Write | MFOF_Binary);
				if(pFile)
				{
					MFFile_Write(pFile, pTemplateData, size, false);
					MFFile_Close(pFile);
				}

				MFIntModel_Destroy(pIM);
			}
#endif
		}

		if(!pTemplateData)
			return NULL;

		// check ID string
		MFDebug_Assert(*(uint32*)pTemplateData == MFMAKEFOURCC('M', 'D', 'L', '2'), "Incorrect MFModel version.");

		// store filename for later reference
		pTemplate = (MFModelTemplate*)pTemplateData;
		pTemplate->pFilename = pFilename;

		gModelBank.Add(pOriginalFilename, pTemplate);

		MFModel_FixUp(pTemplate, true);

		MFModelDataChunk *pChunk = MFModel_GetDataChunk(pTemplate, MFChunkType_SubObjects);

		if(pChunk)
		{
			MFModelSubObject *pSubobjects = (MFModelSubObject*)pChunk->pData;

			for(int a=0; a<pChunk->count; a++)
			{
//				pSubobjects[a].pMaterial = MFMaterial_Create((char*)pSubobjects[a].pMaterial);

				for(int b=0; b<pSubobjects[a].numMeshChunks; b++)
				{
					MFModel_CreateMeshChunk(MFModel_GetMeshChunkInternal(pTemplate, a, b));
				}
			}
		}
	}

	MFModel *pModel;
	pModel = (MFModel*)MFHeap_Alloc(sizeof(MFModel));

	pModel->worldMatrix = MFMatrix::identity;
	pModel->modelColour = MFVector::one;
	pModel->pTemplate = pTemplate;
	pModel->pAnimation = NULL;

	++pTemplate->refCount;

	return pModel;
}