예제 #1
0
파일: MFAsset.cpp 프로젝트: TurkeyMan/fuji
MF_API bool MFAsset_ConvertModelAndAnimationFromFile(const char *pFilename, void **ppMesh, size_t *pMeshSize, void **ppAnimation, size_t *pAnimationSize, MFPlatform platform, size_t extraBytes)
{
	// should this request be forewarded to the file server, or should we do it locally?
	//... todo

	if(!MFIntAsset_ConvertModelAndAnimationFromFile(pFilename, ppMesh, pMeshSize, ppAnimation, pAnimationSize, platform, extraBytes))
		return false;

	if(ppMesh && *ppMesh)
	{
		MFFile *pFile = MFFileSystem_Open(MFStr("cache:%s.mdl", pFilename), MFOF_Write | MFOF_Binary);
		if(pFile)
		{
			MFFile_Write(pFile, *ppMesh, *pMeshSize, false);
			MFFile_Close(pFile);
		}
	}
	if(ppAnimation && *ppAnimation)
	{
		MFFile *pFile = MFFileSystem_Open(MFStr("cache:%s.anm", pFilename), MFOF_Write | MFOF_Binary);
		if(pFile)
		{
			MFFile_Write(pFile, *ppAnimation, *pAnimationSize, false);
			MFFile_Close(pFile);
		}
	}
	return true;
}
예제 #2
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;
}
예제 #3
0
파일: MFAsset.cpp 프로젝트: TurkeyMan/fuji
MF_API bool MFAsset_ConvertAssetFromFile(const char *pFilename, void **ppOutput, size_t *pSize, MFPlatform platform, size_t extraBytes)
{
	// should this request be forewarded to the file server, or should we do it locally?
	//... todo

	size_t size;
	if(!MFIntAsset_ConvertAssetFromFile(pFilename, ppOutput, &size, platform, extraBytes) || !*ppOutput)
		return false;

	if(pSize)
		*pSize = size;

	const char *pExt = MFString_GetFileExtension(pFilename);
	const char *pCacheExt = NULL;
	if(!MFString_CaseCmp(pExt, ".mfx"))
		pCacheExt = ".bfx";
	else if(!MFString_CaseCmp(pExt, ".fnt"))
		pCacheExt = ".fft";
	else if(!MFAsset_IsSoundFile(pExt))
		pCacheExt = ".snd";
	else if(!MFAsset_IsImageFile(pExt))
		pCacheExt = ".tex";
	else if(!MFAsset_IsGeometryFile(pExt))
		pCacheExt = ".mdl";
	else if(!MFAsset_IsShaderFile(pExt))
		pCacheExt = ".fsh";

	MFFile *pFile = MFFileSystem_Open(MFStr("cache:%s%s", pFilename, pCacheExt), MFOF_Write | MFOF_Binary);
	if(pFile)
	{
		MFFile_Write(pFile, *ppOutput, size, false);
		MFFile_Close(pFile);
	}
	return true;
}
예제 #4
0
파일: ReadOBJ.cpp 프로젝트: TurkeyMan/fuji
int F3DFile::ReadOBJ(const char *pFilename)
{
	pModel = this;

	MFFile *pFile = MFFileSystem_Open(pFilename, MFOF_Read);
	if(!pFile)
	{
		MFDebug_Warn(2, MFStr("Failed to open OBJ file %s", pFilename));
		return 1;
	}

	uint64 size = MFFile_Seek(pFile, 0, MFSeek_End);
	MFFile_Seek(pFile, 0, MFSeek_Begin);

	char *pMem = (char*)MFHeap_Alloc((size_t)size+1);
	MFFile_Read(pFile, pMem, size);
	pMem[size] = 0;

	MFFile_Close(pFile);

	ParseOBJFile(pMem);
	MFHeap_Free(pMem);

	return 0;
}
예제 #5
0
// returns true if the file can be found within the mounted filesystem stack
MF_API bool MFFileSystem_Exists(const char *pFilename)
{
	MFCALLSTACK;

	bool exists = false;

	MFFile *hFile = MFFileSystem_Open(pFilename, MFOF_Read|MFOF_Binary|MFOF_TryOpen);
	if(hFile)
	{
		exists = true;
		MFFile_Close(hFile);
	}

	return exists;
}
예제 #6
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;
}
예제 #7
0
MF_API size_t MFFileSystem_Save(const char *pFilename, const char *pBuffer, size_t size)
{
	MFDebug_Log(5, MFStr("Call: MFFileSystem_Save(\"%s\")", pFilename));

	size_t bytesWritten = 0;

	MFFile *hFile = MFFileSystem_Open(pFilename, MFOF_Write|MFOF_Truncate|MFOF_Binary|MFOF_CreateDirectory);
	if(hFile)
	{
		bytesWritten = MFFile_Write(hFile, pBuffer, size, false);

		MFFile_Close(hFile);
	}

	return bytesWritten;
}
예제 #8
0
파일: MFAsset.cpp 프로젝트: TurkeyMan/fuji
MF_API bool MFAsset_ConvertShaderFromFile(const char *pFilename, void **ppOutput, size_t *pSize, MFPlatform platform, MFShaderType shaderType, MFShaderMacro *pMacros, MFRendererDrivers renderDriver, MFShaderLanguage language)
{
	// should this request be forewarded to the file server, or should we do it locally?
	//... todo

	if(!MFIntAsset_ConvertShaderFromFile(pFilename, ppOutput, pSize, platform, shaderType, pMacros, renderDriver, language))
		return false;

	MFFile *pFile = MFFileSystem_Open(MFStr("cache:%s.fsh", pFilename), MFOF_Write | MFOF_Binary);
	if(pFile)
	{
		MFFile_Write(pFile, *ppOutput, *pSize, false);
		MFFile_Close(pFile);
	}
	return true;
}
예제 #9
0
파일: MFAsset.cpp 프로젝트: TurkeyMan/fuji
MF_API bool MFAsset_ConvertTextureFromFile(const char *pFilename, void **ppOutput, size_t *pSize, MFPlatform platform, uint32 flags, MFImageFormat targetFormat, size_t extraBytes)
{
	// should this request be forewarded to the file server, or should we do it locally?
	//... todo

	if(!MFIntAsset_ConvertTextureFromFile(pFilename, ppOutput, pSize, platform, flags, targetFormat, extraBytes))
		return false;

	MFFile *pFile = MFFileSystem_Open(MFStr("cache:%s.tex", pFilename), MFOF_Write | MFOF_Binary);
	if(pFile)
	{
		MFFile_Write(pFile, *ppOutput, *pSize, false);
		MFFile_Close(pFile);
	}
	return true;
}
예제 #10
0
MF_API const char *MFFileSystem_ResolveSystemPath(const char *pFilename, bool bAbsolute)
{
	MFFile *pFile = MFFileSystem_Open(pFilename, MFOF_Read|MFOF_Binary);

	const char *pPath = NULL;
	if(pFile)
	{
		GET_MODULE_DATA(MFFileSystemState);

		// TODO: support other filesystems that forward to the native filesystem (like cache filesystem?)
		if(pFile->filesystem == pModuleData->hNativeFileSystem)
			pPath = MFStr(pFile->fileIdentifier);
		MFFile_Close(pFile);
	}

	// convert to absolute...
	if(bAbsolute)
		pPath = MFFileNative_MakeAbsolute(pPath);

	return pPath;
}
예제 #11
0
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;
}
예제 #12
0
void CreateVorbisStream(MFAudioStream *pStream, const char *pFilename)
{
	MFCALLSTACK;

	MFVorbisStream *pVS = (MFVorbisStream*)MFHeap_Alloc(sizeof(MFVorbisStream));
	pStream->pStreamData = pVS;

	// open vorbis file
	MFFile* hFile = MFFileSystem_Open(pFilename);
	if(!hFile)
		return;

	// attempt to cache the vorbis stream
	MFOpenDataCachedFile cachedOpen;
	cachedOpen.cbSize = sizeof(MFOpenDataCachedFile);
	cachedOpen.openFlags = MFOF_Read | MFOF_Binary | MFOF_Cached_CleanupBaseFile;
	cachedOpen.maxCacheSize = 256*1024; // 256k cache for vorbis stream should be heaps!!
	cachedOpen.pBaseFile = hFile;

	MFFile *pCachedFile = MFFile_Open(MFFileSystem_GetInternalFileSystemHandle(MFFSH_CachedFileSystem), &cachedOpen);
	if(pCachedFile)
		hFile = pCachedFile;

	// setup vorbis read callbacks
	ov_callbacks callbacks;
	callbacks.read_func = MFFile_StdRead;
	callbacks.seek_func = MFSound_VorbisSeek;
	callbacks.close_func = MFFile_StdClose;
	callbacks.tell_func = MFFile_StdTell;

	// open vorbis file
	if(ov_test_callbacks(hFile, &pVS->vorbisFile, NULL, 0, callbacks))
	{
		MFDebug_Assert(false, "Not a vorbis file.");
		MFHeap_Free(pVS);
		return;
	}

	ov_test_open(&pVS->vorbisFile);

	// get vorbis file info
	pVS->pInfo = ov_info(&pVS->vorbisFile, -1);

#if defined(VORBIS_TREMOR)
//	pStream->trackLength = (float)ov_pcm_total(&pVS->vorbisFile, -1) / (float)pVS->pInfo->rate;
	pStream->trackLength = 1000.0f;
#else
	pStream->trackLength = (float)ov_time_total(&pVS->vorbisFile, -1);
#endif

	// fill out the stream info
	pStream->streamInfo.sampleRate = pVS->pInfo->rate;
	pStream->streamInfo.channels = pVS->pInfo->channels;
	pStream->streamInfo.bitsPerSample = 16;
	pStream->streamInfo.bufferLength = pVS->pInfo->rate;

	// read the vorbis comment data
	pVS->pComment = ov_comment(&pVS->vorbisFile, -1);
	if(pVS->pComment)
	{
		const char *pTitle = vorbis_comment_query(pVS->pComment, "TITLE", 0);
		const char *pArtist = vorbis_comment_query(pVS->pComment, "ALBUM", 0);
		const char *pAlbum = vorbis_comment_query(pVS->pComment, "ARTIST", 0);
		const char *pGenre = vorbis_comment_query(pVS->pComment, "GENRE", 0);

		if(pTitle)
			MFString_CopyN(pStream->streamInfo.songName, pTitle, sizeof(pStream->streamInfo.songName)-1);
		if(pArtist)
			MFString_CopyN(pStream->streamInfo.artistName, pArtist, sizeof(pStream->streamInfo.artistName)-1);
		if(pAlbum)
			MFString_CopyN(pStream->streamInfo.albumName, pAlbum, sizeof(pStream->streamInfo.albumName)-1);
		if(pGenre)
			MFString_CopyN(pStream->streamInfo.genre, pGenre, sizeof(pStream->streamInfo.genre)-1);
	}
}
예제 #13
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;
}
예제 #14
0
void CreateWAVStream(MFAudioStream *pStream, const char *pFilename)
{
	MFCALLSTACK;

	// open wav file
	MFFile* hFile = MFFileSystem_Open(pFilename);
	if(!hFile)
		return;

	// attempt to cache the vorbis stream
	MFOpenDataCachedFile cachedOpen;
	cachedOpen.cbSize = sizeof(MFOpenDataCachedFile);
	cachedOpen.openFlags = MFOF_Read | MFOF_Binary | MFOF_Cached_CleanupBaseFile;
	cachedOpen.maxCacheSize = 256*1024; // 256k cache for wav stream should be heaps!!
	cachedOpen.pBaseFile = hFile;

	MFFile *pCachedFile = MFFile_Open(MFFileSystem_GetInternalFileSystemHandle(MFFSH_CachedFileSystem), &cachedOpen);
	if(pCachedFile)
		hFile = pCachedFile;

	RIFFHeader header;
	MFFile_Read(hFile, &header, sizeof(header));

	if(header.RIFF != MFMAKEFOURCC('R', 'I', 'F', 'F') || header.WAVE != MFMAKEFOURCC('W', 'A', 'V', 'E'))
		return;	// not a .wav file...

	// if everything's good, and it appears to be a valid wav file
	MFWAVStream *pWS = (MFWAVStream*)MFHeap_AllocAndZero(sizeof(MFWAVStream));
	pStream->pStreamData = pWS;
	pWS->pStream = hFile;

	size_t read;
	size_t fptr = sizeof(header);
	do
	{
		MFFile_Seek(hFile, fptr, MFSeek_Begin);

		WAVChunk dataChunk;
		MFZeroMemory(&dataChunk, sizeof(dataChunk));
		read = MFFile_Read(hFile, &dataChunk, sizeof(dataChunk));
		fptr += sizeof(dataChunk) + dataChunk.size;

		if(dataChunk.id == MFMAKEFOURCC('f', 'm', 't', ' '))
		{
			read = MFFile_Read(hFile, &pWS->format, dataChunk.size);
			if(pWS->format.cbSize)
				read = (size_t)MFFile_Seek(hFile, pWS->format.cbSize, MFSeek_Current);
		}
		else if(dataChunk.id == MFMAKEFOURCC('d', 'a', 't', 'a'))
		{
			pWS->dataOffset = (size_t)MFFile_Tell(hFile);
			pWS->dataSize = dataChunk.size;
		}
	}
	while(read);

	// return to the start of the audio data
	MFFile_Seek(pWS->pStream, (int)pWS->dataOffset, MFSeek_Begin);

	// calculate the track length
	pWS->sampleSize = (pWS->format.nChannels * pWS->format.wBitsPerSample) >> 3;
	pStream->trackLength = (float)(pWS->dataSize / pWS->sampleSize) / (float)pWS->format.nSamplesPerSec;

	// fill out the stream info
	pStream->streamInfo.sampleRate = pWS->format.nSamplesPerSec;
	pStream->streamInfo.channels = pWS->format.nChannels;
	pStream->streamInfo.bitsPerSample = pWS->format.wBitsPerSample;
	pStream->streamInfo.bufferLength = pWS->format.nSamplesPerSec;
}