加载TLBB场景(二)

#include "StdAfx.h"

#include "TerrainScene.h"

#include <tinyxml/tinyxml.h>



#ifdef _DEBUG

#pragma comment(lib, "tinyxml_d.lib")

#else

#pragma comment(lib, "tinyxml.lib")

#endif



struct CUSTOMVERTEX

{

	float x, y, z;	   // 世界坐标

	float u, v;      // 纹理坐标

};



struct GeometryData

{

	unsigned int			numVertices;

	unsigned int			numIndices;

	std::vector<CUSTOMVERTEX>	vertexData;	

	std::vector<unsigned int>	indexData;

	TexturePtr			pTexture;

};



struct PixMap

{

	int textureId;

	float left;

	float top;

	float right;

	float bottom;

};	



struct GridHeader

{

	unsigned int nMagic;

	// 版本号

	unsigned int nVersion;

	// 地表宽度(横向格子数)

	int nWidth;

	// 地表高度(纵向格子数)

	int nHeight;

};



struct GridInfo

{

	// 该值即为pixelmap的索引(第几个pixelmap)

	short    nFirstLayer;

	// 对nFirstLayer的操作,取值是上面几个定义的宏,可以互相组合

	unsigned char    nFirstLayerOp;

	// 该值为pixelmap的索引

	//天龙八部的地表最多可以两层融合,说白了就是每个点里有两层UV,这里为第二层pixelmap的索引

	short    nSecondLayer;

	// 对nSecondLayer的操作,取值同nFirstLayerOp

	unsigned char    nSecondLayerOp;

	// 对格子的三角形的操作,可能取值如下

	//    0正常三角形索引

	//    1不同于正常的三角形索引

	unsigned char    IndexOrder;



	// 图片水平翻转,即左右翻转

#define FLIP_HORIZINTAL 1

	// 图片垂直翻转,即上下翻转

#define FLIP_VERTICAL 2

	// 逆时针旋转90度

#define ANTICLOCKWISE_90 4

	// 以三角形的对角线镜像,IndexOrder==0时就把左上的纹理坐标复制到右下,否则把右上的坐标复制到左下

#define FLIP_DIAGONAL 8



};



CTerrainScene::CTerrainScene(void)

{

	m_pSceneManager  = NULL;

	m_iTerrainWidth  = 0;

	m_iTerrainHeight = 0;

	m_pHeightMapData = NULL;



	for( int idx = 0; idx < 3; ++idx )

	{

		m_fTerrainScale[idx] = 1.0f;

	}

}



CTerrainScene::~CTerrainScene(void)

{

	ClearScene();



	m_pSceneManager = NULL;

}



void CTerrainScene::SetSceneManager( SceneManager* pManager )

{

	m_pSceneManager = pManager;

}



void CTerrainScene::LoadScene( const char* strFileName, SceneNode* pRootNode )

{

	if( m_pSceneManager == NULL )

		return;



	TiXmlDocument doc;



	String FileName = strFileName;

	String FullPath = "";

	{

		ResourceGroupManager::LocationList locates = ResourceGroupManager::getSingleton().getResourceLocationList(

			ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);



		ResourceGroupManager::LocationList::iterator it_begin = locates.begin();

		ResourceGroupManager::LocationList::iterator it_end = locates.end();

		while( it_begin != it_end )

		{		

			FullPath = (*it_begin)->archive->getName() + String("/") + FileName; 

			FILE* pFile = fopen( FullPath.c_str(), "rb" );

			if( pFile != NULL )

			{

				fclose(pFile);

				break;

			}

			++it_begin;

		}

		if( it_begin == it_end )

			return;

	}	



	doc.LoadFile(FullPath.c_str(), TIXML_ENCODING_UTF8);

	TiXmlElement* pRoot = doc.FirstChildElement("Scene");

	if( pRoot == NULL )

		return;



	TiXmlElement* pChild = pRoot->FirstChildElement();



	while( pChild != NULL )

	{	

		const char* pUtf8NodeName = pChild->Value();

		if( pUtf8NodeName != NULL )

		{

			if( strcmp( pUtf8NodeName, "Terrain") == 0 )

			{

				const char* pUtf8FileName = pChild->Attribute("filename");

				if( pUtf8FileName != NULL )

				{

					int len = MultiByteToWideChar( CP_UTF8, 0, pUtf8FileName, -1, NULL, 0 );

					wchar_t* pwFileName = new wchar_t[len];

					MultiByteToWideChar(CP_UTF8, 0, pUtf8FileName, -1, pwFileName, len );		

					len = WideCharToMultiByte( CP_ACP, 0, pwFileName, -1, NULL, 0, NULL, NULL );

					char* pFileName = new char[len];

					WideCharToMultiByte( CP_ACP, 0, pwFileName, -1, pFileName, len, NULL, NULL );

					delete[] pwFileName;



					LoadTerrain(pFileName, pRootNode);



					delete pFileName;

				}

			}

			else if( strcmp( pUtf8NodeName, "Object") == 0 )

			{

				const char* pUtf8Type = pChild->Attribute("type");

				if( stricmp(pUtf8Type, "StaticEntity") == 0 ||

					stricmp(pUtf8Type, "Model")  == 0 )

				{

					SceneNode* pEntityNode = NULL;

					float pos[3] = {0.0f, 0.0f, 0.0f};

					float orientation[4] = {1.0f, 0.0f, 0.0f, 0.0f};

					float scale[3] = {1.0f, 1.0f, 1.0f};



					TiXmlElement* pProperty = pChild->FirstChildElement();

					while( pProperty != NULL )

					{

						const char* pUtf8Name = pProperty->Attribute("name");

						int tagMesh = stricmp(pUtf8Name, "mesh name");

						int tagModel = stricmp(pUtf8Name, "model name");

						if(  tagMesh == 0 || tagModel == 0 )

						{

							const char* pUtf8Value = pProperty->Attribute("value");

							if( pUtf8Value != NULL )

							{

								int len = MultiByteToWideChar(CP_UTF8, 0, pUtf8Value, -1, NULL, 0);

								wchar_t* pwValue = new wchar_t[len];

								MultiByteToWideChar(CP_UTF8, 0, pUtf8Value, -1, pwValue, len);

								len = WideCharToMultiByte(CP_ACP, 0, pwValue, -1, NULL, 0, NULL, NULL);

								char* pMeshName = new char[len];

								WideCharToMultiByte(CP_ACP, 0, pwValue, -1, pMeshName, len, NULL, NULL);



								pEntityNode = pRootNode->createChildSceneNode();

								if( tagMesh == 0 )

								{

									Entity* pEntity = NULL;

									if( ResourceGroupManager::getSingleton().resourceExists(

										ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 

										pMeshName) )

									{

										pEntity = m_pSceneManager->createEntity(pMeshName);

										pEntityNode->attachObject(pEntity);

									}

								}

								else

								{

									LoadModelObject( pMeshName, pEntityNode);

								}



								delete[] pwValue;

								delete[] pMeshName;

							}

						}

						else if( stricmp(pUtf8Name, "position") == 0 )

						{

							const char* pUtf8Value = pProperty->Attribute("value");

							if( pUtf8Value != NULL )

							{

								int len = strlen(pUtf8Value);

								char* pValue = new char[len + 1];



								const char* p1 = pUtf8Value;

								const char* p2 = pUtf8Value;

								int idx = 0;



								while( *p1 != NULL && idx < 3 )

								{

									if( *p1 == ' ' )

									{

										int interval = p1 - p2;

										memcpy( pValue, p2, interval);

										pValue[interval] = NULL;

										pos[idx] = atof(pValue);

										p2 = p1 + 1;

										++idx;

									}

									++p1;

								}

								if( idx < 3 )

								{

									int interval = p1 - p2;

									memcpy( pValue, p2, interval);

									pValue[interval] = NULL;

									pos[idx] = atof(pValue);

								}



								delete[] pValue;

							}

						}

						else if( stricmp(pUtf8Name, "orientation") == 0 )

						{

							const char* pUtf8Value = pProperty->Attribute("value");

							if( pUtf8Value != NULL )

							{

								int len = strlen(pUtf8Value);

								char* pValue = new char[len + 1];



								const char* p1 = pUtf8Value;

								const char* p2 = pUtf8Value;

								int idx = 0;



								while( *p1 != NULL && idx < 4 )

								{

									if( *p1 == ' ' )

									{

										int interval = p1 - p2;

										memcpy( pValue, p2, interval);

										pValue[interval] = NULL;

										orientation[idx] = atof(pValue);

										p2 = p1 + 1;

										++idx;

									}

									++p1;

								}

								if( idx < 4 )

								{

									int interval = p1 - p2;

									memcpy( pValue, p2, interval);

									pValue[interval] = NULL;

									orientation[idx] = atof(pValue);

								}



								delete[] pValue;

							}

						}

						else if( stricmp(pUtf8Name, "scale") == 0 )

						{

							const char* pUtf8Value = pProperty->Attribute("value");

							if( pUtf8Value != NULL )

							{

								int len = strlen(pUtf8Value);

								char* pValue = new char[len + 1];



								const char* p1 = pUtf8Value;

								const char* p2 = pUtf8Value;

								int idx = 0;



								while( *p1 != NULL && idx < 3 )

								{

									if( *p1 == ' ' )

									{

										int interval = p1 - p2;

										memcpy( pValue, p2, interval);

										pValue[interval] = NULL;

										scale[idx] = atof(pValue);

										p2 = p1 + 1;

										++idx;

									}

									++p1;

								}

								if( idx < 3 )

								{

									int interval = p1 - p2;

									memcpy( pValue, p2, interval);

									pValue[interval] = NULL;

									scale[idx] = atof(pValue);

								}



								delete[] pValue;

							}

						}



						pProperty = pProperty->NextSiblingElement();

					}



					if( pEntityNode != NULL )

					{

						pEntityNode->setScale(scale[0], scale[1], scale[2]);

						pEntityNode->setPosition(pos[0], pos[1], pos[2]);

						pEntityNode->setOrientation(orientation[0], orientation[1], orientation[2], orientation[3]);

					}

				}

			}

		}



		pChild = pChild->NextSiblingElement();

	}

}



void CTerrainScene::LoadTerrain( const char* strFileName, SceneNode* pRootNode )

{

	if( m_pSceneManager == NULL )

		return;



	String FileName = strFileName;

	String FullPath = "";

	{

		ResourceGroupManager::LocationList locates = ResourceGroupManager::getSingleton().getResourceLocationList(

			ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);



		ResourceGroupManager::LocationList::iterator it_begin = locates.begin();

		ResourceGroupManager::LocationList::iterator it_end = locates.end();

		while( it_begin != it_end )

		{		

			FullPath = (*it_begin)->archive->getName() + String("/") + FileName; 

			FILE* pFile = fopen( FullPath.c_str(), "rb" );

			if( pFile != NULL )

			{

				fclose(pFile);

				break;

			}

			++it_begin;

		}

		if(it_begin == it_end)

			return; 

	}

	TiXmlDocument doc;

	doc.LoadFile( FullPath.c_str(), TIXML_ENCODING_UTF8);

	TiXmlElement* pTerrainNode = doc.RootElement();

	if( pTerrainNode == NULL )

		return;

	const char* pUtf8XSize = pTerrainNode->Attribute("xsize");

	const char* pUtf8ZSize = pTerrainNode->Attribute("zsize");

	

	m_iTerrainWidth		= atoi(pUtf8XSize) + 1;

	m_iTerrainHeight	= atoi(pUtf8ZSize) + 1;



	TiXmlElement* texturesElement = pTerrainNode->FirstChildElement("textures");

	TiXmlElement* textureElement = texturesElement->FirstChildElement();

	int size_textures = 0;



	std::vector<TexturePtr> list_textures;



	while( textureElement != NULL )

	{	

		const char* p = textureElement->Attribute("filename");



		int len = MultiByteToWideChar(CP_UTF8, 0, p, -1, 0, 0 );

		wchar_t* wFilename = new wchar_t[len];

		MultiByteToWideChar(CP_UTF8, 0, p, -1, wFilename, len);



		len = WideCharToMultiByte(CP_ACP, 0, wFilename, -1, 0, 0, NULL, NULL);

		char* Filename = new char[len];

		WideCharToMultiByte(CP_ACP, 0, wFilename, -1, Filename, len, NULL, NULL);



		TexturePtr texturePtr = 

			TextureManager::getSingleton().getByName( Filename );

		if( texturePtr.isNull() )

		{	

			texturePtr = TextureManager::getSingleton().create( Filename, 

				ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );			    

			texturePtr->load();

		}



		list_textures.push_back(texturePtr);



		++size_textures;



		delete[] wFilename;

		delete[] Filename;



		textureElement = textureElement->NextSiblingElement();

	}



	TiXmlElement* pixmapsElement = pTerrainNode->FirstChildElement("pixmaps");

	TiXmlElement* pixmapElement = pixmapsElement->FirstChildElement();



	std::vector<PixMap> pixmaps;



	while( pixmapElement != NULL )

	{	

		PixMap pixmap;



		const char* p = pixmapElement->Attribute("textureId");

		pixmap.textureId = atof(p);

		const char* pLeftVal = pixmapElement->Attribute("left");

		if( pLeftVal != NULL )

			pixmap.left = atof(pLeftVal);

		else

			pixmap.left = 0.0f;



		const char* pTopVal = pixmapElement->Attribute("top");

		if( pTopVal != NULL )

			pixmap.top = atof(pTopVal);

		else

			pixmap.top = 0.0f;



		const char* pRightVal = pixmapElement->Attribute("right");

		if( pRightVal != NULL )

			pixmap.right = atof(pRightVal);

		else

			pixmap.right = 1.0f;



		const char* pBottomVal = pixmapElement->Attribute("bottom");

		if( pBottomVal != NULL )

			pixmap.bottom = atof(pBottomVal);

		else

			pixmap.bottom = 1.0f;



		pixmaps.push_back(pixmap);



		pixmapElement = pixmapElement->NextSiblingElement();

	}



	TiXmlElement* height_map_element =

		pTerrainNode->FirstChildElement("heightmap");

	const char* height_map_filename = height_map_element->Attribute("filename");

	TiXmlElement* gridinfo_element =

		pTerrainNode->FirstChildElement("gridInfo");

	const char* gridinfo_filename = gridinfo_element->Attribute("filename");



	int height_map_width = 0;

	int height_map_height = 0;



	if( height_map_filename != NULL )

	{

		int len = MultiByteToWideChar( CP_UTF8, 0, height_map_filename, -1, NULL, 0 );

		wchar_t* pwFileName = new wchar_t[len];

		MultiByteToWideChar(CP_UTF8, 0, height_map_filename, -1, pwFileName, len );		

		len = WideCharToMultiByte( CP_ACP, 0, pwFileName, -1, NULL, 0, NULL, NULL );

		char* pFileName = new char[len];

		WideCharToMultiByte( CP_ACP, 0, pwFileName, -1, pFileName, len, NULL, NULL );

		delete[] pwFileName;



		FileName = pFileName;

		delete[] pFileName;

		{

			ResourceGroupManager::LocationList locates = ResourceGroupManager::getSingleton().getResourceLocationList(

				ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);



			ResourceGroupManager::LocationList::iterator it_begin = locates.begin();

			ResourceGroupManager::LocationList::iterator it_end = locates.end();

			while( it_begin != it_end )

			{		

				FullPath = (*it_begin)->archive->getName() + String("/") + FileName; 

				FILE* pFile = fopen( FullPath.c_str(), "rb" );

				if( pFile != NULL )

				{

					fclose(pFile);

					break;

				}

				++it_begin;

			}

			if(it_begin != it_end)

			{

				FILE* pHeightFile = fopen( FullPath.c_str(), "rb" );

				fseek( pHeightFile, 8, SEEK_CUR );

				fread( &height_map_width, sizeof(unsigned int), 1, pHeightFile );

				fread( &height_map_height, sizeof(unsigned int), 1, pHeightFile );

				m_pHeightMapData = new float[height_map_width * height_map_height];	

				fread( m_pHeightMapData, sizeof(float), 

					height_map_width * height_map_height, pHeightFile );	

				fclose( pHeightFile );

			}

		}		

	}



	GridInfo* pGridData = NULL;

	unsigned int grid_width = 0;

	unsigned int grid_height = 0;

	if( gridinfo_filename != NULL )

	{

		int len = MultiByteToWideChar( CP_UTF8, 0, gridinfo_filename, -1, NULL, 0 );

		wchar_t* pwFileName = new wchar_t[len];

		MultiByteToWideChar(CP_UTF8, 0, gridinfo_filename, -1, pwFileName, len );		

		len = WideCharToMultiByte( CP_ACP, 0, pwFileName, -1, NULL, 0, NULL, NULL );

		char* pFileName = new char[len];

		WideCharToMultiByte( CP_ACP, 0, pwFileName, -1, pFileName, len, NULL, NULL );

		delete[] pwFileName;



		FileName = pFileName;		

		delete[] pFileName;

		{

			ResourceGroupManager::LocationList locates = ResourceGroupManager::getSingleton().getResourceLocationList(

				ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);



			ResourceGroupManager::LocationList::iterator it_begin = locates.begin();

			ResourceGroupManager::LocationList::iterator it_end = locates.end();

			while( it_begin != it_end )

			{		

				FullPath = (*it_begin)->archive->getName() + String("/") + FileName; 

				FILE* pFile = fopen( FullPath.c_str(), "rb" );

				if( pFile != NULL )

				{

					fclose(pFile);

					break;

				}

				++it_begin;

			}

			if(it_begin != it_end)

			{

				LoadGridInfo( FullPath.c_str(), NULL, &grid_width, &grid_height );

				pGridData = new GridInfo[grid_width * grid_height];

				LoadGridInfo( FullPath.c_str(), pGridData, &grid_width, &grid_height );

			}

		}		

	}



	TiXmlElement* ScaleNode =

		pTerrainNode->FirstChildElement("scale");

	if( ScaleNode != NULL )

	{

		const char* XScale = ScaleNode->Attribute("x");

		const char* YScale = ScaleNode->Attribute("y");

		const char* ZScale = ScaleNode->Attribute("z");

		if( XScale != NULL && YScale != NULL && ZScale != NULL )

		{

			m_fTerrainScale[0] = atof(XScale);

			m_fTerrainScale[1] = atof(YScale);

			m_fTerrainScale[2] = atof(ZScale);

		}

	}



	float Min[3] = {  999999,  999999,  999999 };

	float Max[3] = { -999999, -999999, -999999 };

	Min[0] = -m_fTerrainScale[0] * m_iTerrainWidth / 2.0f;	

	Max[0] =  m_fTerrainScale[0] * m_iTerrainWidth / 2.0f;

	Min[2] = -m_fTerrainScale[2] * m_iTerrainHeight / 2.0f;

	Max[2] =  m_fTerrainScale[2] * m_iTerrainHeight / 2.0f;



	float height_map_value = 0.0f;

	CUSTOMVERTEX* pTerrainVertices = new CUSTOMVERTEX[m_iTerrainWidth * m_iTerrainHeight];

	for( int i = 0; i < m_iTerrainHeight; ++i )

	{

		for( int j = 0; j < m_iTerrainWidth; ++j )

		{

			int idx = i * m_iTerrainWidth + j;



			if( m_pHeightMapData != NULL )

				height_map_value = m_pHeightMapData[idx];



			pTerrainVertices[idx].x = -m_fTerrainScale[0] * (m_iTerrainWidth / 2.0f - j);

			pTerrainVertices[idx].y =  height_map_value * m_fTerrainScale[1];

			pTerrainVertices[idx].z = -m_fTerrainScale[2] * (m_iTerrainHeight / 2.0f - i);



			if( pTerrainVertices[idx].y >Max[1] )

				Max[1] = pTerrainVertices[idx].y;

			if( pTerrainVertices[idx].y < Min[1] )

				Min[1] = pTerrainVertices[idx].y;

		}

	}



	if( m_pHeightMapData != NULL )

		delete[] m_pHeightMapData;



	std::vector<GeometryData> vecMeshes1;

	std::vector<GeometryData> vecMeshes2;

	vecMeshes1.resize(size_textures);

	vecMeshes2.resize(size_textures);



	for( int i = 0; i < size_textures; ++i )

	{

		vecMeshes1[i].pTexture = list_textures[i];

		vecMeshes1[i].numIndices = 0;

		vecMeshes1[i].numVertices = 0;



		vecMeshes2[i].pTexture = list_textures[i];

		vecMeshes2[i].numIndices = 0;

		vecMeshes2[i].numVertices = 0;

	}



	std::vector<GeometryData>* pVecMeshes = NULL;

	int pixmap_idx = -1;

	unsigned char layerOp = 0;



	for( int i = 0; i < grid_height; ++i )

	{

		for( int j = 0; j < grid_width; ++j )

		{

			for( int idx = 0; idx < 2; ++idx )

			{

				if( idx > 0 )

				{

					pixmap_idx = pGridData[i * grid_width + j].nSecondLayer;

					layerOp = pGridData[i * grid_width + j].nSecondLayerOp;

					pVecMeshes = &vecMeshes2;

				}

				else

				{

					pixmap_idx = pGridData[i * grid_width + j].nFirstLayer;

					layerOp = pGridData[i * grid_width + j].nFirstLayerOp;

					pVecMeshes = &vecMeshes1;

				}



				if( pixmap_idx < 0 )

					continue;

				for( int k = 0; k < 4; ++k )

				{

					CUSTOMVERTEX* p = &pTerrainVertices[(i + (k/2)) * m_iTerrainWidth + j + (k % 2)];

					switch(k) 

					{

					case 0:

						p->u = pixmaps[pixmap_idx].left;

						p->v = pixmaps[pixmap_idx].top;

						break;

					case 1:

						p->u = pixmaps[pixmap_idx].right;

						p->v = pixmaps[pixmap_idx].top;

						break;

					case 2:

						p->u = pixmaps[pixmap_idx].left;

						p->v = pixmaps[pixmap_idx].bottom;

						break;

					case 3:

						p->u = pixmaps[pixmap_idx].right;

						p->v = pixmaps[pixmap_idx].bottom;

						break;

					default:

						break;

					}



					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData.push_back(*p);

				}

				(*pVecMeshes)[pixmaps[pixmap_idx].textureId].numVertices = 

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData.size();



				int vertex_index = (*pVecMeshes)[pixmaps[pixmap_idx].textureId].numVertices - 1;



				if( layerOp & 0x01)

				{

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index].u = 

						pixmaps[pixmap_idx].left;

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 1].u = 

						pixmaps[pixmap_idx].right;

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 2].u = 

						pixmaps[pixmap_idx].left;

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 3].u = 

						pixmaps[pixmap_idx].right;

				}



				if( layerOp & 0x02)

				{

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index].v = 

						pixmaps[pixmap_idx].top;

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 1].v = 

						pixmaps[pixmap_idx].top;

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 2].v = 

						pixmaps[pixmap_idx].bottom;

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 3].v = 

						pixmaps[pixmap_idx].bottom;

				}



				if( layerOp & 0x04)

				{

					float u1 = (*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index].u;

					float v1 = (*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index].v;



					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index].u = 

						(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 1].u;



					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 1].u = 

						(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 3].u;

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 1].v = 

						(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 3].v;



					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 3].u = 

						(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 2].u;



					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 2].u = u1;								

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 2].v = v1;

				}



				if( layerOp & 0x08)

				{

					float u = (*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 1].u;

					float v = (*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 1].v;



					if( pGridData[i * grid_width + j].IndexOrder == 0)

					{

						(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index].u = 

							(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 3].u;

						(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index].v = 

							(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 3].v;

					}

					else

					{

						(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 1].u = 

							(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 2].u;

						(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 1].v = 

							(*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData[vertex_index - 2].v;

					}

				}



				int vert_index = (*pVecMeshes)[pixmaps[pixmap_idx].textureId].vertexData.size() - 4;



				if( pGridData[i * grid_width + j].IndexOrder == 0)

				{

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.push_back(

						vert_index);

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.push_back(

						vert_index + 2);

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.push_back(

						vert_index + 1);

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.push_back(

						vert_index + 1);

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.push_back(

						vert_index + 2);

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.push_back(

						vert_index + 3);

				}

				else

				{

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.push_back(

						vert_index);

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.push_back(

						vert_index + 2);

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.push_back(

						vert_index + 3);

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.push_back(

						vert_index + 3);

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.push_back(

						vert_index + 1);

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.push_back(

						vert_index + 0);

				}

				(*pVecMeshes)[pixmaps[pixmap_idx].textureId].numIndices = 

					(*pVecMeshes)[pixmaps[pixmap_idx].textureId].indexData.size();

			}

		}

	}	



	delete[] pTerrainVertices;

	delete[] pGridData;	



	MeshPtr pMesh = MeshManager::getSingleton().createManual( strFileName, 

		ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );



	static unsigned int index = 0;

	std::vector<GeometryData>::iterator it_begin, it_end;



	for( int i = 0; i < 2; ++i )

	{				

		if( i > 0 )

		{

			it_begin = vecMeshes2.begin();

			it_end = vecMeshes2.end();			

		}

		else

		{

			it_begin = vecMeshes1.begin();

			it_end = vecMeshes1.end();

		}



		while( it_begin != it_end )

		{

			if( it_begin->numVertices < 3 )

			{

				++it_begin;

				continue;

			}

			String materialName = it_begin->pTexture->getName() + StringConverter::toString(index);

			MaterialPtr material = Ogre::MaterialManager::getSingleton().create( materialName, "General", true );

			Ogre::Technique* technique = material->getTechnique(0);



			Ogre::Pass* pass = technique->getPass(0);



			if( i > 0 )

				pass->setSceneBlending( SBF_SOURCE_ALPHA, SBF_ONE_MINUS_SOURCE_ALPHA );

			Ogre::TextureUnitState* textureUnitState = pass->createTextureUnitState();

			textureUnitState->setTextureAddressingMode( Ogre::TextureUnitState::TAM_CLAMP );

			textureUnitState->setTextureName( it_begin->pTexture->getName() );

			++index;



			SubMesh* sm = pMesh->createSubMesh();

			sm->useSharedVertices = false;

			sm->vertexData = new VertexData();

			sm->vertexData->vertexStart = 0;

			sm->vertexData->vertexCount = it_begin->numVertices;

			VertexDeclaration* dcl = sm->vertexData->vertexDeclaration;

			size_t offset = 0;

			dcl->addElement(0, offset, VET_FLOAT3, VES_POSITION);

			offset += VertexElement::getTypeSize(VET_FLOAT3);

			dcl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);

			offset += VertexElement::getTypeSize(VET_FLOAT3);

			dcl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES);

			offset += VertexElement::getTypeSize(VET_FLOAT2);



			HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton()

				.createVertexBuffer(

				offset, sm->vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY );

			float* pReal = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));



			for( int j = 0; j < sm->vertexData->vertexCount; j++ )

			{

				*pReal++ = it_begin->vertexData[j].x;

				*pReal++ = it_begin->vertexData[j].y;

				*pReal++ = it_begin->vertexData[j].z;



				*pReal++ = 0.0f;

				*pReal++ = 1.0f;

				*pReal++ = 0.0f;



				*pReal++ = it_begin->vertexData[j].u;

				*pReal++ = it_begin->vertexData[j].v;

			}

			vbuf->unlock();

			sm->vertexData->vertexBufferBinding->setBinding( 0, vbuf);

			sm->indexData->indexCount = it_begin->numIndices;

			sm->indexData->indexBuffer = HardwareBufferManager::getSingleton()

				.createIndexBuffer(HardwareIndexBuffer::IT_32BIT, sm->indexData->indexCount,

				HardwareBuffer::HBU_STATIC_WRITE_ONLY);

			uint32* pI = static_cast<uint32*>(

				sm->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD));

			for( uint32 j = 0; j < sm->indexData->indexCount; j++ )

			{

				*pI++ = it_begin->indexData[j];

			}



			sm->indexData->indexBuffer->unlock();



			sm->setMaterialName( materialName );



			++it_begin;

		}

	}



	pMesh->_setBounds(AxisAlignedBox( Min[0], Min[1], Min[2], Max[0], Max[1], Max[2]));

	pMesh->_setBoundingSphereRadius(

		std::max( Max[0] - Min[0], std::max(Max[1] - Min[1], Max[2] - Min[2])) / 2.0f );

	pMesh->load();



	Entity* pEntity = m_pSceneManager->createEntity(pMesh->getName());

	pRootNode->attachObject(pEntity);

}



void CTerrainScene::LoadGridInfo( const char* strFileName, void* pGridInfo, unsigned int* pWidth, unsigned int* pHeight )

{

	if( m_pSceneManager == NULL )

		return;



	FILE* pFile = fopen( strFileName, "rb" );



	GridHeader header; 

	fread( &header, sizeof(GridHeader), 1, pFile );



	if( pGridInfo == NULL )

	{

		*pWidth = header.nWidth;

		*pHeight = header.nHeight;

		fclose(pFile);

		return;

	}



	if( *pWidth > header.nWidth || *pHeight > header.nHeight )

	{

		fclose(pFile);

		return;

	}



	char LargeVersion = 0;

	// 看版本号大于这个,就表示后面跟着有个标记用来表示结构体的大小是7字节的版本还是5字节的版本

	if( header.nVersion >= 0x00100001 )

	{

		fread(&LargeVersion , sizeof(LargeVersion), 1, pFile);

	}



	unsigned char byteValue;

	GridInfo* pInfo = (GridInfo*)pGridInfo;

	size_t numGrids = header.nWidth * header.nHeight;

	for(size_t i = 0 ; i < numGrids ; i ++)

	{		

		if( LargeVersion )

		{

			fread(&pInfo->nFirstLayer, sizeof(short), 1, pFile);

			fread(&pInfo->nFirstLayerOp, sizeof(char), 1, pFile);

			fread(&pInfo->nSecondLayer, sizeof(short), 1, pFile);			

		}

		else

		{

			fread(&byteValue, sizeof(char), 1, pFile);

			pInfo->nFirstLayer = byteValue;

			fread(&pInfo->nFirstLayerOp, 1, 1, pFile);						

			fread(&byteValue, sizeof(char), 1, pFile);

			pInfo->nSecondLayer = byteValue;

		}

		fread(&pInfo->nSecondLayerOp, sizeof(char), 1, pFile);

		fread(&pInfo->IndexOrder, sizeof(char), 1, pFile);



		pInfo->nFirstLayer--;

		pInfo->nSecondLayer--;	



		++pInfo;

	}

	fclose(pFile);

}



void CTerrainScene::TraverseBonesAndBuildSceneNodes( Node* pNode, SceneNode* pSceneNode, String suffix, bool bRoot )

{

	Node::ChildNodeIterator pChildNode = pNode->getChildIterator();



	if( bRoot )

		pSceneNode = pSceneNode->createChildSceneNode();

	else

		pSceneNode = static_cast<SceneNode*>(pSceneNode->getParent())->createChildSceneNode();

	pSceneNode->setScale(pNode->getScale());

	pSceneNode->setPosition(pNode->getPosition());

	pSceneNode->setOrientation(pNode->getOrientation());



	pSceneNode = pSceneNode->createChildSceneNode();

	pSceneNode = pSceneNode->createChildSceneNode(pNode->getName() + suffix);



	while( pChildNode.hasMoreElements() )

	{

		Node* pBone = pChildNode.getNext();		

		TraverseBonesAndBuildSceneNodes(pBone, pSceneNode, suffix, false);

	}

}



void CTerrainScene::LoadModelObject( const char* strFileName, SceneNode* pRootNode )

{	

	if( m_pSceneManager == NULL )

		return;



	String FileName = strFileName;

	String FullPath = "";

	{

		ResourceGroupManager::LocationList locates = ResourceGroupManager::getSingleton().getResourceLocationList(

			ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);



		ResourceGroupManager::LocationList::iterator it_begin = locates.begin();

		ResourceGroupManager::LocationList::iterator it_end = locates.end();

		while( it_begin != it_end )

		{		

			FullPath = (*it_begin)->archive->getName() + String("/") + FileName; 

			FILE* pFile = fopen( FullPath.c_str(), "rb" );

			if( pFile != NULL )

			{

				fclose(pFile);

				break;

			}

			++it_begin;

		}

		if(it_begin == it_end)

			return;

	}



	static unsigned int model_count = 0;

	++model_count;

	int name_len = strlen(strFileName);



	const char* p1 = strFileName + name_len;

	const char* p2 = strFileName;

	while( p1 > strFileName )

	{

		if( *p1 == '/' || *p1 == '\\')

		{

			++p1;

			break;

		}

		--p1;

	}

	int interval = p1 - p2;

	String prefix = "";

	if( interval != 1 )

	{

		char* pPrefix = new char[interval + 1];

		memcpy( pPrefix, p2, interval + 1);

		pPrefix[interval] = NULL;

		prefix = pPrefix;

		delete[] pPrefix;

	}

	TiXmlDocument doc;

	doc.LoadFile( FullPath.c_str(), TIXML_ENCODING_UTF8);



	TiXmlElement* pRoot = doc.FirstChildElement("model");

	if( pRoot == NULL )

		return;



	TiXmlElement* pFrameElem = pRoot->FirstChildElement("frame");

	std::vector<String> m_vecRootBoneName;



	if( pFrameElem != NULL )

	{

		const char* pText = pFrameElem->Attribute("name");

		int len = MultiByteToWideChar( CP_UTF8, 0, pText, -1, NULL, 0 );

		wchar_t* pwFileName = new wchar_t[len];

		MultiByteToWideChar( CP_UTF8, 0, pText, -1, pwFileName, len );

		len = WideCharToMultiByte( CP_ACP, 0, pwFileName, -1, NULL, 0, NULL, NULL );

		char* pFileName = new char[len];

		WideCharToMultiByte( CP_ACP, 0, pwFileName, -1, pFileName, len, NULL, NULL );





		SkeletonPtr pSkeleton = SkeletonManager::getSingleton().load(prefix + String(pFileName), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );

		unsigned short numAnimation = pSkeleton->getNumAnimations();

		Skeleton::BoneIterator root_bone = pSkeleton->getRootBoneIterator();



		String suffix = StringConverter::toString(model_count);



		while( root_bone.hasMoreElements() )

		{

			Bone* pBone = root_bone.getNext();

			TraverseBonesAndBuildSceneNodes( pBone, pRootNode, suffix );

		}



		for( unsigned short i = 0; i < numAnimation; ++i )

		{

			Animation* pAnim = pSkeleton->getAnimation(i);

			Animation::NodeTrackIterator it = pAnim->getNodeTrackIterator();



			String AnimName = String(pFileName) + StringConverter::toString(model_count);

			Animation* pDestAnim = m_pSceneManager->createAnimation( AnimName, pAnim->getLength() );

			pDestAnim->setInterpolationMode(pAnim->getInterpolationMode());

			AnimationState* pAnimState = m_pSceneManager->createAnimationState(AnimName);

			pAnimState->setLoop(true);

			pAnimState->setEnabled(true);		



			while( it.hasMoreElements() )

			{

				NodeAnimationTrack* pTrack = it.getNext();

				String name = pTrack->getAssociatedNode()->getName();



				SceneNode* pSceneNode = m_pSceneManager->getSceneNode(String(name) + suffix);

				NodeAnimationTrack* pDestTrack = 

					pDestAnim->createNodeTrack(pTrack->getHandle(), pSceneNode->getParent());



				unsigned short numKeyFrames = pTrack->getNumKeyFrames();

				for( unsigned short index = 0; index < numKeyFrames; ++index )

				{

					TransformKeyFrame* keyframe = 

						pDestTrack->createNodeKeyFrame(pTrack->getKeyFrame(index)->getTime()); 

					*keyframe = *(TransformKeyFrame*)(pTrack->getKeyFrame(index));

				}

			}

		}



		delete[]pwFileName;

		delete[]pFileName;

	}

	TiXmlElement* pEntityElem = pRoot->FirstChildElement("entity");

	while( pEntityElem != NULL )

	{

		const char* pUtf8MeshName = pEntityElem->Attribute("mesh");

		const char* pUtf8NodeName = pEntityElem->Attribute("node");

		SceneNode* pSceneNode = NULL;



		if( pUtf8NodeName != NULL )

		{

			int len = MultiByteToWideChar(CP_UTF8, 0, pUtf8NodeName, -1, NULL, 0 );

			wchar_t* pwNodeName = new wchar_t[len];

			MultiByteToWideChar(CP_UTF8, 0, pUtf8NodeName, -1, pwNodeName, len );

			len = WideCharToMultiByte(CP_ACP, 0, pwNodeName, -1, NULL, 0, NULL, NULL );

			char* pNodeName = new char[len];

			WideCharToMultiByte(CP_ACP, 0, pwNodeName, -1, pNodeName, len, NULL, NULL );



			String NodeName = String(pNodeName) + StringConverter::toString(model_count);

			bool bHas = m_pSceneManager->hasSceneNode(NodeName);

			if( bHas )

			{

				pSceneNode = m_pSceneManager->getSceneNode(NodeName);				

			}

			else

				pSceneNode = pRootNode->createChildSceneNode();



			delete[] pwNodeName;

			delete[] pNodeName;

		}

		else

			pSceneNode = pRootNode->createChildSceneNode();



		int len = MultiByteToWideChar(CP_UTF8, 0, pUtf8MeshName, -1, NULL, 0);

		wchar_t* pwMeshName = new wchar_t[len];

		MultiByteToWideChar(CP_UTF8, 0, pUtf8MeshName, -1, pwMeshName, len);

		len = WideCharToMultiByte(CP_ACP, 0, pwMeshName, -1, NULL, 0, NULL, NULL);

		char* pMeshName = new char[len];

		WideCharToMultiByte(CP_ACP, 0, pwMeshName, -1, pMeshName, len, NULL, NULL);



		Entity* pEntity = NULL;

		if( ResourceGroupManager::getSingleton().resourceExists(ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, prefix + String(pMeshName)) )

		{

			pEntity = m_pSceneManager->createEntity( prefix + String(pMeshName));

			pSceneNode->attachObject(pEntity);	

		}



		delete[] pwMeshName;

		delete[] pMeshName;



		if( pEntity != NULL )

		{

			bool bHas = pEntity->hasSkeleton();

			if( bHas )

			{

				bHas = pEntity->getSkeleton()->hasAnimation("[auto]");

				if( bHas )

				{

					AnimationState* pAnimState = pEntity->getAnimationState("[auto]");				

					pAnimState->setLoop( true );

					pAnimState->setEnabled( true );				

					m_AnimationStates.push_back( pAnimState );

				}

			}

		}



		TiXmlElement* pOffset = pEntityElem->FirstChildElement("offset");

		if( pOffset != NULL )

		{

			TiXmlElement* pTranslate = pOffset->FirstChildElement("translate");

			if( pTranslate != NULL )

			{

				const char* pX = pTranslate->Attribute("x");

				const char* pY = pTranslate->Attribute("y");

				const char* pZ = pTranslate->Attribute("z");

				float x = atof(pX);

				float y = atof(pY);

				float z = atof(pZ);



				pSceneNode->translate(x, y, z);				

			}

		}

		pEntityElem = pEntityElem->NextSiblingElement("entity");

	}

}



void CTerrainScene::Update( const FrameEvent& evt )

{

	std::list<AnimationState*>::iterator it_begin = m_AnimationStates.begin();

	std::list<AnimationState*>::iterator it_end = m_AnimationStates.end();



	while( it_begin != it_end )

	{

		(*it_begin)->addTime(evt.timeSinceLastFrame);

		++it_begin;

	}

}



void CTerrainScene::ClearScene()

{

	m_pSceneManager  = NULL;

	m_iTerrainWidth  = 0;

	m_iTerrainHeight = 0;

	m_pHeightMapData = NULL;



	for( int idx = 0; idx < 2; ++idx )

	{

		m_fTerrainScale[idx] = 1.0f;

	}



	m_AnimationStates.clear();

}

你可能感兴趣的:(加载)