• 加载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();
    }
  • 相关阅读:
    再理解HDFS的存储机制
    C实现头插法和尾插法来构建单链表(不带头结点)
    linux系统编程:线程同步-相互排斥量(mutex)
    基于github for windows&amp;github的团队协作基本操作
    分治法求众数问题 (配图)
    hdu1576 mod 运算的逆元
    Android5.0(lollipop)新特性介绍(一)
    jenkins详解(一)
    手机APP测试点总结
    App测试方法总结
  • 原文地址:https://www.cnblogs.com/LinuxHunter/p/1886096.html
Copyright © 2020-2023  润新知