www.pudn.com > zfxcengine-0.1.0.zip > ceMeshFactory.cpp


// $Id: ceMeshFactory.cpp,v 1.1 2005/09/13 00:59:46 andreaskohn Exp $ 
//////////////////////////////////////////////////////////////////////////////// 
// 
//  Module:     Core 
//  File:       ceMeshFactory 
//  Created:    25.10.2004 
//  Author:     Enrico 
//	Licence:    See licence file in root 
//  Last Mod:	$Id: ceMeshFactory.cpp,v 1.1 2005/09/13 00:59:46 andreaskohn Exp $ 
// 
//////////////////////////////////////////////////////////////////////////////// 
#include "Core/ceExceptions.h" 
#include "Geometry/ceMeshFactory.h" 
#include "Core/ceResourceManager.h" 
#include "Geometry/ceMesh.h" 
#include "Core/ceDebug.h" 
#include "Core/ceMemManager.h" 
#include "Geometry/ceMeshFormatQ3BSP.h" 
 
namespace ZFXCE { 
	//------------------------------------------------------------------------------ 
	ceMeshFactory::ceMeshFactory(ceVFSystem* VFS, ceResourceManager *pResMgr)  
		: ceResourceFactory("ceMesh", pResMgr) 
	{ 
		PUSH_FUNCTION; 
 
		ce_assert(NULL != VFS); 
		ce_assert(NULL != pResMgr); 
		m_VFS = VFS; 
		Init(); 
	} 
	//------------------------------------------------------------------------------ 
	ceMeshFactory::~ceMeshFactory() 
	{ 
		PUSH_FUNCTION; 
 
		Release(); 
	} 
	//------------------------------------------------------------------------------ 
	void ceMeshFactory::Release() 
	{ 
		PUSH_FUNCTION; 
 
		// Releasing allocated file format descriptors 
		m_VFS = NULL; 
		for (size_t f=0; f < m_SupportedFileFormats.size(); ++f) 
			delete m_SupportedFileFormats[f]; 
		m_SupportedFileFormats.clear(); 
		 
		// Releasing allocated mesh instances 
		std::vector::iterator it; 
		for (it = m_vMeshArray.begin(); it != m_vMeshArray.end(); ++it) { 
			delete (*it); 
		} 
 
		m_vMeshArray.clear(); 
	} 
	//------------------------------------------------------------------------------ 
	void ceMeshFactory::Init() 
	{ 
		PUSH_FUNCTION; 
 
		m_SupportedFileFormats.push_back(new ceMeshFormatMD2()); 
		m_SupportedFileFormats.push_back(new ceMeshFormatMD3()); 
		m_SupportedFileFormats.push_back(new ceMeshFormatD3Proc()); 
		m_SupportedFileFormats.push_back(new ceMeshFormatQ3BSP()); 
	} 
	//------------------------------------------------------------------------------ 
	ceMesh* ceMeshFactory::Load(std::string filename) 
	{ 
		PUSH_FUNCTION; 
 
		if (0 == m_SupportedFileFormats.size()) { 
			const std::string error = std::string(__FUNCTION__) + std::string(": Keine Dateiformate unterstützt!"); 
			CE_EXCEPTION(error, CELS_ERROR); 
		} 
 
		// Checken, ob das Format unterstützt wird 
		const size_t nl = filename.length(); 
		//std::string ext = filename[nl-3] + filename[nl-2] + filename[nl-1]; 
		//std::string ext="md2"; 
		std::string ext = ""; 
		ext += filename[nl-3]; 
		ext += filename[nl-2]; 
		ext += filename[nl-1]; 
		 
		IMFI* formatinfo=NULL; 
		for (UINT i=0; i < m_SupportedFileFormats.size(); i++) { 
			if(ext == m_SupportedFileFormats[i]->FileExt) { 
				formatinfo = m_SupportedFileFormats[i]; 
				// Ok, will be supported 
				break; 
			} 
		} 
 
		if(NULL == formatinfo) { 
			std::cout << "Cannot find file format : " << filename << std::endl; 
			return NULL; 
		} 
 
		INT FileID = m_VFS->OpenFile(filename, (ZFXCE::eFileType) formatinfo->FileType); 
		 
		// Was a file found? 
		if (-1 == FileID) { 
			std::cout << __FUNCTION__ << ": Datei nicht gefunden: " << filename << endl; 
			return NULL; 
		} 
 
		const size_t FileSize = m_VFS->GetFileSize(FileID); 
		BYTE* FileData = new BYTE[ FileSize]; 
		ce_assert(NULL != FileData); 
		memset(&FileData[0], 0, sizeof(BYTE) * FileSize ); 
		m_VFS->GetFileData(FileID, &FileData[0], FileSize); 
		m_VFS->CloseFile(FileID); 
 
		return formatinfo->Load(FileData, FileSize); 
	} 
	//------------------------------------------------------------------------------ 
	ceMesh* ceMeshFactory::Load(BYTE *pData, const size_t sSize, 
		std::string FileformatExt) 
	{ 
		PUSH_FUNCTION; 
 
		ceResTypeID ResType; 
		ResType.m_uiResTypeID = m_uiResTypeID; 
		ceMesh *pMesh = NULL; 
		 
		// Load specific mesh data 
		if (FileformatExt == "md2") { 
			// MD2 dormat 
			IMFI* format = new ceMeshFormatMD2(); 
			ce_assert (NULL != format); 
			pMesh = format->Load(pData, sSize); 
			pMesh->SetResTypeID(ResType); 
		} 
		else if ("bsp" == FileformatExt) { 
			// Q3 format 
			IMFI *pFormat = new ceMeshFormatQ3BSP(); 
			ce_assert (NULL != pFormat); 
			pMesh = pFormat->Load(pData, sSize); 
			pMesh->SetResTypeID(ResType); 
		} 
		m_vMeshArray.push_back(pMesh); 
		 
		 
		return pMesh; 
	} 
	//------------------------------------------------------------------------------ 
	ceMesh *ceMeshFactory::CreateInstance(const std::string strMeshName) 
	{ 
		PUSH_FUNCTION; 
 
		ceMesh *pMesh = new ceMesh(); 
		ce_assert (NULL != pMesh); 
		pMesh->SetResName(strMeshName); 
		ceResTypeID ResType; 
		ResType.m_uiResTypeID = m_uiResTypeID; 
		m_vMeshArray.push_back(pMesh); 
		 
		return pMesh; 
	} 
	//------------------------------------------------------------------------------ 
	std::vector ceMeshFactory::GetSupportedFileFormats() const 
	{ 
		return m_SupportedFileFormats; 
	} 
	//------------------------------------------------------------------------------ 
	ceMesh *ceMeshFactory::BuildTriangle(ceVec3f V1, ceVec3f V2, 
		ceVec3f V3) 
	{ 
		PUSH_FUNCTION; 
 
		// Build new mesh instance 
		ceMesh *pMesh = CreateInstance("tri"); 
 
		// Generate basic data 
		vector Vecs; 
		Vecs.push_back(V1); 
		Vecs.push_back(V2); 
		Vecs.push_back(V3); 
		pMesh->SetVertices(Vecs); 
		vector vIndices; 
		vIndices.push_back(0); 
		vIndices.push_back(1); 
		vIndices.push_back(2); 
		pMesh->SetIndices(vIndices); 
		 
		return pMesh; 
	} 
	//------------------------------------------------------------------------------ 
	ceMesh *ceMeshFactory::BuildTriangleMesh(const std::string strName,  
		const ceVec3f V1, const ceVec3f V2, const ceVec3f V3, const ceColorRGBA color) 
	{ 
		PUSH_FUNCTION; 
		ceMesh *pMesh = CreateInstance(strName); 
		 
		return pMesh; 
	} 
	//------------------------------------------------------------------------------ 
	ceMesh *ceMeshFactory::BuildCubeMesh(const string strName, const ceVec3f vPos,  
		const FLOAT fL, const FLOAT fB, const FLOAT fH, const ceColorRGBA color) 
	{ 
		PUSH_FUNCTION; 
		ceMesh *pMesh = CreateInstance(strName); 
		 
		// Calculate coordinates down  
		ceVec3f v[8]; 
		v[0].x = vPos.x; 
		v[0].y = vPos.y; 
		v[0].z = vPos.z; 
 
		v[1].x = vPos.x + fL; 
		v[1].y = vPos.y; 
		v[1].z = vPos.z; 
		 
		v[2].x = vPos.x + fL; 
		v[2].y = vPos.y + fB; 
		v[2].z = vPos.z; 
 
		v[3].x = vPos.x; 
		v[3].y = vPos.y + fB; 
		v[3].z = vPos.z; 
		 
		v[4].x = vPos.x; 
		v[4].y = vPos.y; 
		v[4].z = vPos.z + fH; 
		 
		v[5].x = vPos.x + fL; 
		v[5].y = vPos.y; 
		v[5].z = vPos.z + fH; 
		 
		v[6].x = vPos.x + fL; 
		v[6].y = vPos.y + fB; 
		v[6].z = vPos.z + fH; 
		 
		v[7].x = vPos.x; 
		v[7].y = vPos.y + fB; 
		v[7].z = vPos.z + fH; 
 
		// Set cooridnates and color 
		vector Vecs; 
		vector vIndices; 
		vector vColor; 
		for (size_t i=0; i<8; ++i) { 
			ceColorRGBA col = color; 
			Vecs.push_back(v[i]); 
			vColor.push_back(col); 
			v[i].Dump(); 
			cout << "---"< vFaces; 
		 
		// Face down 
		faces[0].UIIndices.push_back(2); 
		faces[0].UIIndices.push_back(1); 
		faces[0].UIIndices.push_back(0); 
		faces[0].UIIndices.push_back(2); 
		faces[0].UIIndices.push_back(0); 
		faces[0].UIIndices.push_back(3); 
		vFaces.push_back(faces[0]); 
		 
		// Face front 
		faces[1].UIIndices.push_back(0); 
		faces[1].UIIndices.push_back(1); 
		faces[1].UIIndices.push_back(5); 
		faces[1].UIIndices.push_back(0); 
		faces[1].UIIndices.push_back(4); 
		faces[1].UIIndices.push_back(5); 
 
		vFaces.push_back(faces[1]); 
 
		// Face right 
		faces[2].UIIndices.push_back(1); 
		faces[2].UIIndices.push_back(2); 
		faces[2].UIIndices.push_back(6); 
		faces[2].UIIndices.push_back(6); 
		faces[2].UIIndices.push_back(5); 
		faces[2].UIIndices.push_back(1); 
		vFaces.push_back(faces[2]); 
 
		// Face back 
		faces[3].UIIndices.push_back(6); 
		faces[3].UIIndices.push_back(2); 
		faces[3].UIIndices.push_back(3); 
 
		faces[3].UIIndices.push_back(3); 
		faces[3].UIIndices.push_back(7); 
		faces[3].UIIndices.push_back(6); 
		vFaces.push_back(faces[3]); 
 
		// Face left 
		faces[4].UIIndices.push_back(0); 
		faces[4].UIIndices.push_back(3); 
		faces[4].UIIndices.push_back(7); 
		faces[4].UIIndices.push_back(7); 
		faces[4].UIIndices.push_back(4); 
		faces[4].UIIndices.push_back(0); 
		vFaces.push_back(faces[4]); 
 
		// Face top 
		faces[5].UIIndices.push_back(6); 
		faces[5].UIIndices.push_back(5); 
		faces[5].UIIndices.push_back(4); 
		faces[5].UIIndices.push_back(4); 
		faces[5].UIIndices.push_back(7); 
		faces[5].UIIndices.push_back(6); 
		vFaces.push_back(faces[5]); 
 
		// Set edges and faces 
		pMesh->SetVertices(Vecs); 
		pMesh->SetFaces(vFaces); 
		pMesh->SetColor(vColor); 
 
		return pMesh; 
	} 
	//------------------------------------------------------------------------------ 
	ceMesh *ceMeshFactory::BuildCubeMesh(const string strName, const ceVec3f vPos,  
		const FLOAT fL, const FLOAT fB, const FLOAT fH, const ceColorRGBA color,  
		const std::string strTexture) 
	{ 
		PUSH_FUNCTION; 
 
		ceMesh *pMesh = BuildCubeMesh(strName, vPos, fL, fB, fH, color); 
		if (0 != strTexture.size()) { 
			vector vTexNames; 
			vTexNames.push_back(strTexture); 
			pMesh->SetTextureNames(vTexNames); 
 
			ceVec2f t[8]; 
			vector vTexCoords; 
			t[0].x = 0.0f; 
			t[0].y = 0.0f; 
 
			t[1].x = 0.0f; 
			t[1].y = 0.0f; 
 
			t[2].x = 0.0f; 
			t[2].y = 0.0f; 
 
			t[3].x = 0.0f; 
			t[3].y = 0.0f; 
 
			t[4].x = 0.0f; 
			t[4].y = 0.0f; 
 
			t[5].x = 0.0f; 
			t[5].y = 0.0f; 
 
			t[6].x = 0.0f; 
			t[6].y = 0.0f; 
 
			t[7].x = 0.0f; 
			t[7].y = 0.0f; 
			for (size_t i=0; i<8; ++i) { 
				vTexCoords.push_back(t[i]); 
			} 
			pMesh->SetTexCoordsByName(strTexture, vTexCoords); 
		} 
		 
		return pMesh; 
	} 
	//------------------------------------------------------------------------------ 
	ceMesh* ceMeshFormatMD2::Load(BYTE* Data, size_t sSize) 
	{ 
		PUSH_FUNCTION; 
 
		struct md2header 
		{ 
			UINT Magic; 
			UINT Version; 
			UINT SkinWidth; 
			UINT SkinHeight; 
			UINT FrameSize; 
			UINT NSkins; 
			UINT NVertices; 
			UINT NTexCoords; 
			UINT NTriangles; 
			UINT NGLCommands; 
			UINT NFrames; 
			UINT OffsetSkins; 
			UINT OffsetTexCoords; 
			UINT OffsetTriangles; 
			UINT OffsetFrames; 
			UINT OffsetGLCommands; 
			UINT OffsetEnd; 
		}; 
		struct md2tc { 
			short tu,tv; 
		}; 
		struct md2skin { 
			char Name[64]; 
		}; 
		struct md2triangle { 
			md2triangle() { 
				Vertex[0] = Vertex[1] = Vertex[2] = 0.0f; 
				Normal[0] = Normal[1] = Normal[2] = 1.0f; 
			} 
			FLOAT Vertex[3]; 
			FLOAT Normal[3]; 
		}; 
		struct md2face { 
			short VertexIndex[3]; 
			short TexCoordIndex[3]; 
		}; 
		struct md2aliastriangle { 
			BYTE Vertex[3]; 
			BYTE Normal; 
		}; 
 
		struct md2aliasframe { 
			FLOAT Scale[3]; 
			FLOAT Translate[3]; 
			CHAR Name[16]; 
			md2aliastriangle AliasTriangles[1]; 
		}; 
		 
		struct md2frame { 
			FLOAT Scale[3]; 
			FLOAT Translate[3]; 
			md2frame(void) { Triangles = NULL; } 
			~md2frame(void) { if(Triangles) delete[] Triangles; Triangles = NULL; } 
			char Name[16]; 
			md2triangle* Triangles; 
		}; 
 
		UINT DataOffset = 0; 
 
		// read header 
		struct md2header Header; 
		memcpy(&Header, &Data[DataOffset], sizeof(struct md2header) ); 
		DataOffset += sizeof(struct md2header); 
/* 
		if(FormatVersion != Header.Version) 
		{ 
			std::string error = "ceMeshFormatMD2::Load(): Falsche Formatversion: "+Header.Version; 
			error += "\nBrauche aber: "; 
			error += FormatVersion; 
			CE_EXCEPTION(error, CELS_ERROR); 
		} 
		if(MagicNumber != Header.Magic) 
		{ 
			std::string error = "ceMeshFormatMD2::Load(): Falsche Magic-Number: "+Header.Magic; 
			error += "\nBrauche aber: "; 
			error += MagicNumber; 
			CE_EXCEPTION(error, CELS_ERROR); 
		} 
*/ 
		cout << "Skins: " << Header.NSkins << endl; 
		cout << "Vertices: " << Header.NVertices << endl; 
		cout << "TexCoords: " << Header.NTexCoords << endl; 
		cout << "Triangles: " << Header.NTriangles << endl; 
		cout << "Frames: " << Header.NFrames << endl; 
 
		ceMesh* Mesh = new ceMesh(); 
 
		// every mesh is a frame. so we make a huge list of connected meshes to represent the frames 
		md2tc* TC = new md2tc[Header.NTexCoords]; 
		md2face* triangles = new md2face[Header.NTriangles]; 
		md2frame* frames = new md2frame[Header.NFrames]; 
 
		DataOffset = Header.OffsetTexCoords; 
		memcpy(&TC[0], Data+DataOffset, sizeof(md2tc) * Header.NTexCoords); 
 
		DataOffset = Header.OffsetTriangles; 
		memcpy(&triangles[0], Data+DataOffset, sizeof(md2face) * Header.NTriangles); 
 
		DataOffset = Header.OffsetFrames; 
 
		UCHAR* Buffer = new UCHAR[2]; 
		memcpy(&Buffer[0], Data+DataOffset, Header.FrameSize); 
		 
		md2aliasframe* pFrame = (md2aliasframe*) Buffer; 
		//strncpy(&frames[0].Name[0], &tempframe->Name[0], 16); 
		cout << "Framename: " << pFrame->Name << endl; 
 
		frames[0].Triangles = new md2triangle[Header.NVertices]; 
 
		for (UINT t=0; t < Header.NVertices; t++) 
		{ 
			frames[0].Triangles[t].Vertex[0] = pFrame->AliasTriangles[t].Vertex[0] * pFrame->Scale[0] + pFrame->Translate[0]; 
			frames[0].Triangles[t].Vertex[1] = pFrame->AliasTriangles[t].Vertex[1] * pFrame->Scale[1] + pFrame->Translate[1]; 
			frames[0].Triangles[t].Vertex[2] = pFrame->AliasTriangles[t].Vertex[2] * pFrame->Scale[2] + pFrame->Translate[2]; 
		} 
		delete[]Buffer; 
		/* 
		for(int f=0; f < Header.NFrames; f++) 
		{ 
			 
			md2frame* frame = &frames[f]; 
			cout << "Frame: " << frame->Name << endl; 
			frame->Triangles = new md2vertex[Header.NVertices]; 
			 
			memcpy(&frame, Data+DataOffset, Header.FrameSize); 
			DataOffset += Header.FrameSize; 
		} 
		*/ 
 
		// Release allocated data 
		delete [] TC; 
		delete [] triangles; 
		delete [] frames; 
		delete[] Data; 
		Data = NULL; 
 
		return Mesh; 
	} 
	//------------------------------------------------------------------------------ 
 
} // Namespace ZFXCE