#include "StdAfx.h" #ifndef CODE_INGAME #include "tinyxml.h" #endif #include "Terrain.h" #include "TerrainModifier.h" #include "NPC.h" #include "ObjectsManager.h" #include #include #include #include "utility.h" #define NPCINFOFILENAME ".\\NPCInfo.xml" #define NPC_PAL_FILENAME ".\\AppData\\Palettes\\NPCCreator.pal" #define NPCCREATORCOMPONENT ".\\NPCCreatorComponent.xml" #define NPCCREATOR_AREA_COMPONENT ".\\NPCCreatorAreaComponent.xml" #define BLEND_TEX_NAME ".\\chunk_blend_texture_" #define PROPERTY_TEX_NAME ".\\chunk_property_texture_" #ifndef CODE_INGAME CNPCManager CTerrain::m_NpcManager; CNPCCreatorManager CTerrain::m_NpcCreatorManager; #endif bool CTerrain::ImportFromFile( const char* pszFile ) { //char *pszFileLower = new char[ MAX_PATH ]; //strncpy_s( pszFileLower, strlen( pszFile )+1, pszFile, _TRUNCATE ); char pszFileLower[MAX_PATH]; strcpy_s( pszFileLower, pszFile ); size_t iLen = strlen( pszFileLower ); for ( size_t i = 0; i < iLen; ++i ) pszFileLower[i] = tolower( pszFileLower[i] ); const char *pszExt = pszFileLower + iLen - 4; if ( strcmp( pszExt, ".etr" ) != 0 ) { LOG( "导入地形扩展名必须为: etr \n" ); return false; } // @step0 打开文件 errno_t err; FILE *fp; if( ( err = fopen_s( &fp, pszFile, "r+b" ) ) !=0 ) { LOG1( "文件:%s打开错误!\n", pszFile ); return false; } LOG( "打开文件okay\n" ); if ( !m_spTerrainRoot ) m_spTerrainRoot = NiNew NiNode; // @step1 读版本号 DWORD dwVersion; fread( &dwVersion, sizeof( DWORD ), 1, fp ); assert( dwVersion == 0x0101 ); LOG( "写版本号okay\n" ); // @step2 读地图编号 fread( &m_MapNO, sizeof( DWORD ), 1, fp ); LOG( "读地图编号okay\n" ); //*********** // comment by Shi Yazheng //*********** // @step3 读取顶点数据 //fread( &m_iVertexX, sizeof( int ), 1, fp ); //fread( &m_iVertexY, sizeof( int ), 1, fp ); //int iVertexNum = m_iVertexX * m_iVertexY; //m_pVertices = NiNew NiPoint3[iVertexNum]; //m_pNormals = NiNew NiPoint3[iVertexNum]; //m_pTexset0 = NiNew NiPoint2[iVertexNum]; //m_pTexset1 = NiNew NiPoint2[iVertexNum]; //m_pVertexClr= NiNew NiColorA[iVertexNum]; //int index = 0; //for ( int i = 0; i < m_iVertexY; ++i ) //{ // for ( int j = 0; j < m_iVertexX; ++j ) // { // fread( &( m_pVertices[index].x ),sizeof( float ), 3, fp ); // fread( &( m_pNormals[index].x ), sizeof( float ), 3, fp ); // fread( &( m_pVertexClr[index]), sizeof(float), 4, fp); // m_pTexset0[index] = NiPoint2( float(j*0.1f), float(i*0.1f) ); // m_pTexset1[index] = NiPoint2( float(j)/float(GRIDINCHUNK), float(i)/(float)GRIDINCHUNK ); // //m_pVertexClr[index] = NiColorA(0,0,0,1); // index++; // } //} //LOG( "读取顶点数据okay\n" ); //********** // end of comment //********* // @step4 读取Chunk点数据 fread( &m_iChunkNumX, sizeof( int ), 1, fp ); fread( &m_iChunkNumY, sizeof( int ), 1, fp ); // 合法性检查 if (m_iChunkNumX>16 || m_iChunkNumX<=0 || m_iChunkNumY>16 || m_iChunkNumY<=0) { LOG("读入错误的 chunk 尺寸."); return false; } int iChunkNum = m_iChunkNumX * m_iChunkNumY; m_pChunks = new stChunk[iChunkNum]; // 获取地形文件所在目录 int iLast = StrFindLast(pszFile, '\\'); char szDirectory[255]; strcpy_s(szDirectory, pszFile); szDirectory[iLast+1] = '\0'; strcat_s(szDirectory, BLEND_TEX_NAME); int index = 0; char szBuf[MAX_PATH]; for ( int i = 0; i < m_iChunkNumY; ++i ) { for ( int j = 0; j < m_iChunkNumX; ++j ) { m_pChunks[index].pChunkMtl = new CTerrainMaterial( NULL, NULL, NULL, NULL ); char szBlendTexName[255]; sprintf_s(szBlendTexName, "%s%d.dds", szDirectory, index); if ( !m_pChunks[index].pChunkMtl->Create(szBlendTexName) ) { LOG1( "第%d个Chunk材质创建失败!\n", index ); return false; } int iLayerCount = 0; fread( &iLayerCount, sizeof(int), 1, fp ); for ( int n = 0; n < iLayerCount; ++n ) { int iStrLen = 0; fread( &iStrLen, sizeof(int), 1, fp ); fread( szBuf, sizeof(char) * iStrLen, 1, fp ); bool b; m_pChunks[index].pChunkMtl->SetTexture( string( szBuf ), b); } int iMinIndex = (i*m_iVertexX + j) * GRIDINCHUNK; int iMaxIndex = ((i+1)*m_iVertexX + (j+1) ) * GRIDINCHUNK; m_pChunks[index].vPosMin = NiPoint2(j*GRIDINCHUNK*EDIT_UNIT, i*GRIDINCHUNK*EDIT_UNIT); m_pChunks[index].vPosMax = NiPoint2((j+1)*GRIDINCHUNK*EDIT_UNIT, (i+1)*GRIDINCHUNK*EDIT_UNIT); //************ // Added By Shi 08.03.28 //************ // 读入 chunk 顶点数据 //NiTriShapePtr pkTriShape = m_pChunks[i].geomData.pTriShape; //int iVertNum = pkTriShape->GetActiveVertexCount(); //fwrite(&iVertNum, sizeof(int), 1, fp); // 顶点个数 //fwrite(pVerts, sizeof(NiPoint3), iVertNum, fp); // 顶点位置 //fwrite(pTexCoords, sizeof(NiPoint2), iVertNum*2, fp); // 纹理 //fwrite(pColors, sizeof(NiColorA), iVertNum, fp); // 顶点颜色 int iNumVert = 0; fread(&iNumVert, sizeof(int), 1, fp); NiPoint3* pVerts = NiNew NiPoint3[iNumVert]; NiPoint2* pTexCoords = NiNew NiPoint2[iNumVert*2]; NiPoint3* pNormals = NiNew NiPoint3[iNumVert*3]; NiColorA* pColors = NiNew NiColorA[iNumVert]; fread(pVerts, sizeof(NiPoint3), iNumVert, fp); // 顶点位置 fread(pTexCoords, sizeof(NiPoint2), iNumVert*2, fp); // 纹理 fread(pColors, sizeof(NiColorA), iNumVert, fp); // 顶点颜色 for (int k=0; kAttachChild(m_pChunks[index].geomData.pTriShape); // 分配chunk的可渲染数据 _BuildChunkData( j, i, false, true); index++; } } LOG( "读取Chunk数据okay\n" ); // @step5 读取阻挡信息 int iGridX = m_iChunkNumX * GRIDINCHUNK; int iGridY = m_iChunkNumY * GRIDINCHUNK; m_pGrids = new stGrid[ iGridX*iGridY ]; m_iTotalX = EDIT_UNIT * iGridX; m_iTotalY = EDIT_UNIT * iGridY; index = 0; for ( int i = 0; i < iGridY; ++i ) { for ( int j = 0; j < iGridX; ++j ) { m_pGrids[index].iPointIndx[0] = i*m_iVertexX+j; m_pGrids[index].iPointIndx[1] = i*m_iVertexX+j+1; m_pGrids[index].iPointIndx[2] = (i+1)*m_iVertexX+j+1; m_pGrids[index].iPointIndx[3] = (i+1)*m_iVertexX+j; fread( &( m_pGrids[index].iTerrainProperty ), sizeof( int ), 1, fp ); index++; } } LOG( "读取地表属性信息okay\n" ); // @step6 读灯光信息 //m_pLightsMgr->Load( fp ); // @step7 读物件信息 //m_pObjectsMgr->Load( pszFile ); // @step8 读植被信息 fclose( fp ); return true; } bool CTerrain::ImportFromStream(NiBinaryStream * pBinStream, std::vector chunkTextures) { LOG( "开始从流载入地形\n" ); if ( !m_spTerrainRoot ) m_spTerrainRoot = NiNew NiNode; // @step1 读版本号 DWORD dwVersion; pBinStream->Read(&dwVersion, sizeof( DWORD )); assert( dwVersion == 0x0101 ); LOG( "写版本号okay\n" ); // @step2 读地图编号 pBinStream->Read( &m_MapNO, sizeof( DWORD )); //******* // comment by Shi Yazheng 03.08.28 //******* // @step3 读取顶点数据 //pBinStream->Read( &m_iVertexX, sizeof( int ) ); //pBinStream->Read( &m_iVertexY, sizeof( int )); //int iVertexNum = m_iVertexX * m_iVertexY; //m_pVertices = NiNew NiPoint3[iVertexNum]; //m_pNormals = NiNew NiPoint3[iVertexNum]; //m_pTexset0 = NiNew NiPoint2[iVertexNum]; //m_pTexset1 = NiNew NiPoint2[iVertexNum]; //m_pVertexClr= NiNew NiColorA[iVertexNum]; //int index = 0; //for ( int i = 0; i < m_iVertexY; ++i ) //{ // for ( int j = 0; j < m_iVertexX; ++j ) // { // pBinStream->Read( &( m_pVertices[index].x ),sizeof( float )*3); // pBinStream->Read( &( m_pNormals[index].x ), sizeof( float )*3); // pBinStream->Read( &( m_pVertexClr[index]), sizeof(float)*4); // m_pTexset0[index] = NiPoint2( float(j*0.1f), float(i*0.1f) ); // m_pTexset1[index] = NiPoint2( float(j)/float(GRIDINCHUNK), float(i)/(float)GRIDINCHUNK ); // //m_pVertexClr[index] = NiColorA(0,0,0,1); // index++; // } //} //LOG( "读取顶点数据okay\n" ); //********* // End of comment //********* //// @step4 读取Chunk点数据 pBinStream->Read( &m_iChunkNumX, sizeof( int )); pBinStream->Read( &m_iChunkNumY, sizeof( int )); int iChunkNum = m_iChunkNumX * m_iChunkNumY; m_pChunks = new stChunk[iChunkNum]; // 初始化所有 chunk if (iChunkNum != chunkTextures.size()) { return false; } int index = 0; char szBuf[256]; for ( int i = 0; i < m_iChunkNumY; ++i ) // 行 { for ( int j = 0; j < m_iChunkNumX; ++j ) // 列 { //int iChunkID = i*m_iChunkNumX+j; m_pChunks[index].pChunkMtl = new CTerrainMaterial(); if ( !m_pChunks[index].pChunkMtl->Create(chunkTextures[index]) ) { LOG1( "第%d个Chunk材质创建失败!\n", index ); return false; } // 跳过 chunk 纹理信息部分 int iLayerCount = 0; pBinStream->Read( &iLayerCount, sizeof(int)); for ( int n = 0; n < iLayerCount; ++n ) { int iStrLen = 0; pBinStream->Read( &iStrLen, sizeof(int)); pBinStream->Read( szBuf, sizeof(char) * iStrLen); } int iMinIndex = (i*m_iVertexX + j) * GRIDINCHUNK; int iMaxIndex = ((i+1)*m_iVertexX + (j+1) ) * GRIDINCHUNK; m_pChunks[index].vPosMin = NiPoint2(j*GRIDINCHUNK*EDIT_UNIT, i*GRIDINCHUNK*EDIT_UNIT); m_pChunks[index].vPosMax = NiPoint2((j+1)*GRIDINCHUNK*EDIT_UNIT, (i+1)*GRIDINCHUNK*EDIT_UNIT); //************ // Added By Shi 08.03.28 //************ // 读入 chunk 顶点数据 //NiTriShapePtr pkTriShape = m_pChunks[i].geomData.pTriShape; //int iVertNum = pkTriShape->GetActiveVertexCount(); //fwrite(&iVertNum, sizeof(int), 1, fp); // 顶点个数 //fwrite(pVerts, sizeof(NiPoint3), iVertNum, fp); // 顶点位置 //fwrite(pTexCoords, sizeof(NiPoint2), iVertNum*2, fp); // 纹理 //fwrite(pColors, sizeof(NiColorA), iVertNum, fp); // 顶点颜色 int iNumVert = 0; pBinStream->Read(&iNumVert, sizeof(int)); NiPoint3* pVerts = NiNew NiPoint3[iNumVert]; NiPoint2* pTexCoords = NiNew NiPoint2[iNumVert*2]; NiPoint3* pNormals = NiNew NiPoint3[iNumVert*3]; NiColorA* pColors = NiNew NiColorA[iNumVert]; pBinStream->Read(pVerts, sizeof(NiPoint3)*iNumVert); // 顶点位置 pBinStream->Read(pTexCoords, sizeof(NiPoint2)*iNumVert*2); // 纹理 pBinStream->Read(pColors, sizeof(NiColorA)*iNumVert); // 顶点颜色 for (int k=0; kRead( &iNumTri, sizeof(int)); // 读入三角形数量 WORD *pConnect = NiAlloc( WORD, iNumTri * 3 ); pBinStream->Read(pConnect, sizeof(WORD)*iNumTri * 3); // 顶点索引 NiTriShapeDynamicData *pData = NiNew NiTriShapeDynamicData( iNumVert, pVerts, pNormals, pColors, pTexCoords, 2, NiGeometryData::NBT_METHOD_NDL, iNumTri, pConnect, iNumVert, iNumTri ); m_pChunks[index].geomData.pTriShape = NiNew NiTriShape( pData ); m_spTerrainRoot->AttachChild(m_pChunks[index].geomData.pTriShape); // 分配chunk的可渲染数据 _BuildChunkData( j, i, false, true); index++; } } //LOG( "读取Chunk数据okay\n" ); //// @step5 读取阻挡信息 int iGridX = m_iChunkNumX * GRIDINCHUNK; int iGridY = m_iChunkNumY * GRIDINCHUNK; m_pGrids = new stGrid[ iGridX*iGridY ]; m_iTotalX = EDIT_UNIT * iGridX; m_iTotalY = EDIT_UNIT * iGridY; index = 0; for ( int i = 0; i < iGridY; ++i ) { for ( int j = 0; j < iGridX; ++j ) { m_pGrids[index].iPointIndx[0] = i*m_iVertexX+j; m_pGrids[index].iPointIndx[1] = i*m_iVertexX+j+1; m_pGrids[index].iPointIndx[2] = (i+1)*m_iVertexX+j+1; m_pGrids[index].iPointIndx[3] = (i+1)*m_iVertexX+j; pBinStream->Read( &( m_pGrids[index].iTerrainProperty ), sizeof( int )); index++; } } LOG( "读取阻挡信息okay\n" ); //// @step6 读灯光信息 ////m_pLightsMgr->Load( fp ); //// @step7 读物件信息 ////m_pObjectsMgr->Load( pszFile ); //// @step8 读植被信息 //fclose( fp ); return true; } // 函数作废 //bool CTerrain::RotateTerrain() //{ // int iVertexNum = m_iVertexX*m_iVertexY; // // NiPoint3 *pNewVertex = NiNew NiPoint3[iVertexNum]; // NiPoint2 *pNewTexset0= NiNew NiPoint2[iVertexNum]; // NiPoint2 *pNewTexset1= NiNew NiPoint2[iVertexNum]; // NiPoint3 *pNewNormal = NiNew NiPoint3[iVertexNum]; // // memcpy(pNewVertex, m_pVertices, sizeof(NiPoint3)*iVertexNum); // memcpy(pNewTexset0, m_pVertices, sizeof(NiPoint2)*iVertexNum); // memcpy(pNewTexset1, m_pVertices, sizeof(NiPoint2)*iVertexNum); // memcpy(pNewNormal, m_pNormals, sizeof(NiPoint3)*iVertexNum); // // // 顺时针旋转180度的 // //for (int i=0; iGetSourcePixelData(); for ( int y = 0; y < BLEND_TEX_SIZE; ++y ) { for ( int x = 0; x < BLEND_TEX_SIZE; ++x ) { unsigned char *pPtr = ( *pPixelData )(x,y); fread( pPtr, sizeof(unsigned char), 4, fp ); } } pPixelData->MarkAsChanged(); LOG( "读取Blend数据okay\n" );*/ // @step3 读取顶点数据 fread( &m_iVertexX, sizeof( int ), 1, fp ); fread( &m_iVertexY, sizeof( int ), 1, fp ); int iVertexNum = m_iVertexX * m_iVertexY; m_pVertices = NiNew NiPoint3[iVertexNum]; m_pNormals = NiNew NiPoint3[iVertexNum]; m_pTexset0 = NiNew NiPoint2[iVertexNum]; m_pTexset1 = NiNew NiPoint2[iVertexNum]; m_pVertexClr= NiNew NiColorA[iVertexNum]; //float fTexelOffset = 1.0f/BLENDTEX_SIZE*0.5f; int index = 0; for ( int i = 0; i < m_iVertexY; ++i ) { for ( int j = 0; j < m_iVertexX; ++j ) { fread( &( m_pVertices[index].x ),sizeof( float ), 3, fp ); fread( &( m_pNormals[index].x ), sizeof( float ), 3, fp ); fread( &( m_pVertexClr[index]), sizeof(float), 4, fp); // 检查顶点位置 if (m_pVertices[index].x!=j || m_pVertices[index].y!=i) { m_pVertices[index].x=j; m_pVertices[index].y=i; } // 4层材质纹理的 uv m_pTexset0[index] = NiPoint2( float(j*0.1f), float(i*0.1f) ); // blend texture 的 uv m_pTexset1[index] = NiPoint2( float(j)/float(GRIDINCHUNK), float(i)/(float)(GRIDINCHUNK)); //m_pTexset1[index].x -= (int)m_pTexset1[index].x; //m_pTexset1[index].y -= (int)m_pTexset1[index].y; //m_pVertexClr[index] = NiColorA(0,0,0,1); index++; } } LOG( "读取顶点数据okay\n" ); // @step4 读取Chunk点数据 fread( &m_iChunkNumX, sizeof( int ), 1, fp ); fread( &m_iChunkNumY, sizeof( int ), 1, fp ); int iChunkNum = m_iChunkNumX * m_iChunkNumY; m_pChunks = new stChunk[iChunkNum]; // 获取地形文件所在目录 int iLast = StrFindLast(pszFile, '\\'); char szDirectory[255]; strcpy(szDirectory, pszFile); szDirectory[iLast+1] = '\0'; //strcat(szDirectory, BLEND_TEX_NAME); index = 0; char szBuf[MAX_PATH]; for ( int i = 0; i < m_iChunkNumY; ++i ) { for ( int j = 0; j < m_iChunkNumX; ++j ) { m_pChunks[index].pChunkMtl = new CTerrainMaterial( NULL, NULL, NULL, NULL ); char szBlendTexName[255]; char szPropertyTexName[255]; sprintf(szBlendTexName, "%s%s%d.dds", szDirectory, BLEND_TEX_NAME, index); sprintf(szPropertyTexName, "%s%s%d.dds", szDirectory, PROPERTY_TEX_NAME, index); if ( !m_pChunks[index].pChunkMtl->Create(szBlendTexName, szPropertyTexName) ) { LOG1( "第%d个Chunk材质创建失败!\n", index ); return false; } int iLayerCount = 0; fread( &iLayerCount, sizeof(int), 1, fp ); for ( int n = 0; n < iLayerCount; ++n ) { int iStrLen = 0; fread( &iStrLen, sizeof(int), 1, fp ); fread( szBuf, sizeof(char) * iStrLen, 1, fp ); bool b; m_pChunks[index].pChunkMtl->SetTexture( string( szBuf ), b); } int iMinIndex = (i*m_iVertexX + j) * GRIDINCHUNK; int iMaxIndex = ((i+1)*m_iVertexX + (j+1) ) * GRIDINCHUNK; m_pChunks[index].vPosMin = NiPoint2( m_pVertices[ iMinIndex ].x, m_pVertices[ iMinIndex ].y ); m_pChunks[index].vPosMax = NiPoint2( m_pVertices[ iMaxIndex ].x, m_pVertices[ iMaxIndex ].y ); // 分配chunk的可渲染数据 _BuildChunkData( j, i ); index++; } } SetCollisionTexture( ); LOG( "读取Chunk数据okay\n" ); // @step5 读取阻挡信息 int iGridX = m_iChunkNumX * GRIDINCHUNK; int iGridY = m_iChunkNumY * GRIDINCHUNK; m_pGrids = new stGrid[ iGridX*iGridY ]; m_iTotalX = EDIT_UNIT * iGridX; m_iTotalY = EDIT_UNIT * iGridY; index = 0; for ( int i = 0; i < iGridY; ++i ) { for ( int j = 0; j < iGridX; ++j ) { m_pGrids[index].iPointIndx[0] = i*m_iVertexX+j; m_pGrids[index].iPointIndx[1] = i*m_iVertexX+j+1; m_pGrids[index].iPointIndx[2] = (i+1)*m_iVertexX+j+1; m_pGrids[index].iPointIndx[3] = (i+1)*m_iVertexX+j; fread( &( m_pGrids[index].iTerrainProperty ), sizeof( int ), 1, fp ); index++; } } LOG( "读取阻挡信息okay\n" ); // @step6 读灯光信息 //m_pLightsMgr->Load( fp ); // @step7 读物件信息 //m_pObjectsMgr->Load( pszFile ); // @step8 读植被信息 fclose( fp ); return true; } bool CTerrain::SaveToFile( const char* pszFile ) { if (!CheckEmptyTextureLayer()) { return false; } //_SaveTerrain(); //_SaveObjects(); //char *pszFileLower = new char[ MAX_PATH ]; //strncpy_s( pszFileLower, strlen( pszFile )+1, pszFile, _TRUNCATE ); char pszFileLower[MAX_PATH]; strcpy_s( pszFileLower, pszFile ); size_t iLen = strlen( pszFileLower ); for ( size_t i = 0; i < iLen; ++i ) pszFileLower[i] = tolower( pszFileLower[i] ); const char *pszExt = pszFileLower + iLen - 4; if ( strcmp( pszExt, ".trr" ) != 0 ) { LOG( "地形文件扩展名必须为: trr \n" ); return false; } FILE *fp; TRY_BEGIN // @step0 打开文件 errno_t err; if( ( err = fopen_s( &fp, pszFileLower, "w+b" ) ) !=0 ) { LOG1( "文件:%s打开错误!\n", pszFileLower ); //SAFE_DELETE_ARRAY( pszFileLower ); return false; } LOG( "打开文件okay\n" ); // @step1 写版本号 static const DWORD dwVersion = 0x0101; fwrite( &dwVersion, sizeof( DWORD ), 1, fp ); LOG( "写版本号okay\n" ); // @step2 写地图编号 fwrite( &m_MapNO, sizeof( DWORD ), 1, fp ); // @step2 写BlendTexture数据 /*assert( m_spBlendTexture ); NiPixelData *pPixelData = m_spBlendTexture->GetSourcePixelData(); for ( int y = 0; y < BLEND_TEX_SIZE; ++y ) { for ( int x = 0; x < BLEND_TEX_SIZE; ++x ) { unsigned char *pPtr = ( *pPixelData )(x,y); fwrite( pPtr, sizeof(unsigned char), 4, fp ); } } LOG( "写Blend数据okay\n" );*/ // @step3 写顶点数据 fwrite( &m_iVertexX, sizeof( int ), 1, fp ); fwrite( &m_iVertexY, sizeof( int ), 1, fp ); for ( int i = 0; i < m_iVertexX*m_iVertexY; ++i ) { fwrite( &( m_pVertices[i].x ),sizeof( float ), 3, fp ); fwrite( &( m_pNormals[i].x ), sizeof( float ), 3, fp ); fwrite( &( m_pVertexClr[i]), sizeof(float), 4, fp); } LOG( "写顶点数据okay\n" ); // @step4 写Chunk数据 fwrite( &m_iChunkNumX, sizeof( int ), 1, fp ); fwrite( &m_iChunkNumY, sizeof( int ), 1, fp ); for ( int i = 0; i < m_iChunkNumX*m_iChunkNumY; ++i ) { CTerrainMaterial *pMtl = m_pChunks[i].pChunkMtl; int iLayerCount = pMtl->GetUsedLayerCount(); fwrite( &iLayerCount, sizeof(int), 1, fp ); for ( int j = 0; j GetTextureFile(j); size_t iLen = strTexFile.length() + 1; fwrite( &iLen, sizeof(int), 1, fp ); fwrite( strTexFile.c_str(), sizeof(char)*iLen, 1, fp ); } } LOG( "写Chunk数据okay\n" ); // @step5 写阻挡信息 int iGridX = m_iChunkNumX * GRIDINCHUNK; int iGridY = m_iChunkNumY * GRIDINCHUNK; for ( int i = 0; i < iGridY*iGridX; ++i ) fwrite( &( m_pGrids[i].iTerrainProperty ), sizeof( int ), 1, fp ); LOG( "写阻挡信息okay\n" ); // @step6 写灯光信息 //m_pLightsMgr->Save(); // @step7 写物件信息 m_pObjectsMgr->Save(pszFile); // @step8 写植被信息 fclose( fp ); TRY_END_HANDLE( fclose( fp ); return false; ) // 在这里测试纹理保存 //ExportTextTexture(); return true; } bool CTerrain::ExportToFile( const char* pszFile ) { if (!CheckEmptyTextureLayer()) { return false; } //_SaveTerrain(); //_SaveObjects(); //char *pszFileLower = new char[ MAX_PATH ]; //strncpy_s( pszFileLower, strlen( pszFile )+1, pszFile, _TRUNCATE ); char pszFileLower[MAX_PATH]; strcpy_s( pszFileLower, pszFile ); size_t iLen = strlen( pszFileLower ); for ( size_t i = 0; i < iLen; ++i ) pszFileLower[i] = tolower( pszFileLower[i] ); const char *pszExt = pszFileLower + iLen - 4; if ( strcmp( pszExt, ".etr" ) != 0 ) { LOG( "导出地形扩展名必须为: etr \n" ); return false; } FILE *fp; TRY_BEGIN // @step0 打开文件 errno_t err; if( ( err = fopen_s( &fp, pszFileLower, "w+b" ) ) !=0 ) { LOG1( "文件:%s打开错误!\n", pszFileLower ); //SAFE_DELETE_ARRAY( pszFileLower ); return false; } LOG( "打开文件okay\n" ); // @step1 写版本号 static const DWORD dwVersion = 0x0101; fwrite( &dwVersion, sizeof( DWORD ), 1, fp ); LOG( "写版本号okay\n" ); // @step2 写地图号 fwrite( &m_MapNO, sizeof( DWORD ), 1, fp ); // @step2 写BlendTexture数据 /*assert( m_spBlendTexture ); NiPixelData *pPixelData = m_spBlendTexture->GetSourcePixelData(); for ( int y = 0; y < BLEND_TEX_SIZE; ++y ) { for ( int x = 0; x < BLEND_TEX_SIZE; ++x ) { unsigned char *pPtr = ( *pPixelData )(x,y); fwrite( pPtr, sizeof(unsigned char), 4, fp ); } } LOG( "写Blend数据okay\n" );*/ //**** //comment by Shi Yazheng 08.03.28 //**** // @step3 写顶点数据 //fwrite( &m_iVertexX, sizeof( int ), 1, fp ); //fwrite( &m_iVertexY, sizeof( int ), 1, fp ); //for ( int i = 0; i < m_iVertexX*m_iVertexY; ++i ) //{ // fwrite( &( m_pVertices[i].x ),sizeof( float ), 3, fp ); // fwrite( &( m_pNormals[i].x ), sizeof( float ), 3, fp ); // fwrite( &( m_pVertexClr[i]), sizeof(float), 4, fp); //} //LOG( "写顶点数据okay\n" ); //**** //end of comment //**** // @step4 写Chunk数据 fwrite( &m_iChunkNumX, sizeof( int ), 1, fp ); fwrite( &m_iChunkNumY, sizeof( int ), 1, fp ); for ( int i = 0; i < m_iChunkNumX*m_iChunkNumY; ++i ) { // 写 chunk 所用的4层纹理 CTerrainMaterial *pMtl = m_pChunks[i].pChunkMtl; int iLayerCount = pMtl->GetUsedLayerCount(); fwrite( &iLayerCount, sizeof(int), 1, fp ); for ( int j = 0; j GetTextureFile(j); size_t iLen = strTexFile.length() + 1; fwrite( &iLen, sizeof(int), 1, fp ); fwrite( strTexFile.c_str(), sizeof(char)*iLen, 1, fp ); } //**** // Added by Shi Yazheng 08.03.28 //**** // 写 chunk 顶点数据 NiTriShapePtr pkTriShape = m_pChunks[i].geomData.pTriShape; NiPoint3* pVerts = pkTriShape->GetVertices(); NiPoint2* pTexCoords = pkTriShape->GetTextures(); NiColorA* pColors = pkTriShape->GetColors(); int iVertNum = pkTriShape->GetVertexCount(); fwrite(&iVertNum, sizeof(int), 1, fp); // 顶点个数 fwrite(pVerts, sizeof(NiPoint3), iVertNum, fp); // 顶点位置 fwrite(pTexCoords, sizeof(NiPoint2), iVertNum*2, fp); // 纹理 fwrite(pColors, sizeof(NiColorA), iVertNum, fp); // 顶点颜色 //**** // end of add //**** // 写 chunk 三角形的连接信息 int iTriCount = m_pChunks[i].geomData.pTriShape->GetTriangleCount(); // 三角形个数 fwrite(&iTriCount, sizeof(int), 1, fp); for (int j=0; jGetTriangleIndices(j, i0, i1, i2); fwrite( &i0, sizeof(unsigned short), 1, fp ); fwrite( &i1, sizeof(unsigned short), 1, fp ); fwrite( &i2, sizeof(unsigned short), 1, fp ); } //unsigned short* pwTriList = m_pChunks[i].geomData.pTriShape->GetTriList(); //for (int j=0; jSave(); // @step7 写物件信息 m_pObjectsMgr->Save(pszFile); // @step8 写植被信息 fclose( fp ); TRY_END_HANDLE( fclose( fp ); return false; ) return true; } bool CTerrain::SaveTerrainToNif(const char *pszPath) { if (pszPath == NULL) { return false; } // 遍历所有 chunk, 将每个 chunk 对应的 geometry 保存为 (ID).nif. for (int i=0; iInsertEndChild(*pXmlDec); TiXmlElement* pXmlRootElement = new TiXmlElement("GSA"); pXmlRootElement->SetAttribute("Major", 1); pXmlRootElement->SetAttribute("Minor", 0); pXmlRootElement->SetAttribute("Patch", 0); pXmlDoc->LinkEndChild(pXmlRootElement); int nIndex = 4; TiXmlElement* pXmlOjbs = new TiXmlElement("OBJECTS"); pXmlRootElement->LinkEndChild(pXmlOjbs); TiXmlElement* pXmlScene = new TiXmlElement("SCENES"); pXmlRootElement->LinkEndChild(pXmlScene); TiXmlElement* pXmlSceneRef = new TiXmlElement("SCENE"); pXmlSceneRef->SetAttribute("Class", "NiScene"); pXmlSceneRef->SetAttribute("Name", "NPCCreator"); pXmlScene->LinkEndChild(pXmlSceneRef); //**************************************************添加NPC区域实体************************************************ TiXmlDocument XmlAreaComponentsDoc(NPCCREATOR_AREA_COMPONENT); if (!XmlAreaComponentsDoc.LoadFile()) { return -1; } TiXmlElement* pRootAreaComponentElement = XmlAreaComponentsDoc.RootElement(); for (TiXmlElement* pXmlAreaComponent = pRootAreaComponentElement->FirstChildElement();pXmlAreaComponent;pXmlAreaComponent = pXmlAreaComponent->NextSiblingElement()) { TiXmlElement* pXmlNewAreaComponent = new TiXmlElement(*pXmlAreaComponent); pXmlOjbs->LinkEndChild(pXmlNewAreaComponent); } TiXmlElement* pXmlAreaEntityRef = new TiXmlElement("ENTITY"); pXmlAreaEntityRef->SetAttribute("RefLinkID", 0); pXmlSceneRef->LinkEndChild(pXmlAreaEntityRef); //*****************************************************添加NPC区域实体************************************************/ for (map::iterator Ite = m_NpcManager.m_NPCList.begin(); Ite != m_NpcManager.m_NPCList.end(); Ite++) { TiXmlElement* pXmlEntity = new TiXmlElement("ENTITY"); pXmlEntity->SetAttribute("LinkID", nIndex); pXmlEntity->SetAttribute("Class", "NiGeneralEntity"); CNPC* pNPC = Ite->second; string strName = "[NPCCreator]" + pNPC->m_Name; pXmlEntity->SetAttribute("Name", strName.c_str()); string strNPCNO; stringstream ssTemp; ssTemp << pNPC->m_NPCNO; ssTemp >> strNPCNO; //通过动作号,获取所对应的nif文件 string strNPCNif; strNPCNif = pNPC->m_NPCAppearance; strNPCNif += ".nif"; //构造TemplateID WORD wHi = HIWORD(pNPC->m_NPCNO); WORD wLo = LOWORD(pNPC->m_NPCNO); char szTmp[MAX_PATH]; sprintf_s(szTmp, "%0x,%0x,%0x,%0x,0,0,0,0,0,0,0,0,0,0,0,0", HIBYTE(wHi), LOBYTE(wHi), HIBYTE(wLo), LOBYTE(wLo)); pXmlEntity->SetAttribute("TemplateID", szTmp); pXmlOjbs->LinkEndChild(pXmlEntity); TiXmlElement* pXmlEntityRef = new TiXmlElement("ENTITY"); pXmlEntityRef->SetAttribute("RefLinkID", nIndex); pXmlSceneRef->LinkEndChild(pXmlEntityRef); //加入Component信息 for (const TiXmlElement* pComponent = pRootComponentElement->FirstChildElement(); pComponent; pComponent = pComponent->NextSiblingElement()) { nIndex++; TiXmlElement* pNewComponent = new TiXmlElement(*pComponent); pNewComponent->SetAttribute("LinkID", nIndex); string strName(pNewComponent->Attribute("Name")); if (strName == "NPCCreator") { TiXmlText* pXmlText = new TiXmlText(strNPCNO.c_str()); pNewComponent->FirstChildElement()->InsertEndChild(*pXmlText); } if (strName == "Scene Graph") { TiXmlText* pXmlText = new TiXmlText(strNPCNif.c_str()); pNewComponent->FirstChildElement()->InsertEndChild(*pXmlText); } pXmlOjbs->LinkEndChild(pNewComponent); TiXmlElement* pComponentRef = new TiXmlElement("COMPONENT"); pComponentRef->SetAttribute("RefLinkID", nIndex); pXmlEntity->LinkEndChild(pComponentRef); } ++nIndex; } pXmlDoc->SaveFile(); delete pXmlDoc; return 0; } bool CTerrain::ExportNPCCreator() { m_pObjectsMgr->SaveNPCCreator(); return true; } int CTerrain::LoadNpcCreator() { m_NpcCreatorManager.LoadNPCCreator(NPCCREATORFILENAME); m_NpcCreatorManager.LoadNPCCreatorNo(NPCCREATORNOMNGFILENAME); return 0; } int CTerrain::SetGsaEncodingCode(const char* szXmlFileName) { // 加载NPC生成器的Component信息 TiXmlDocument XmlOrgGsaDoc(szXmlFileName); if (!XmlOrgGsaDoc.LoadFile(TIXML_ENCODING_LEGACY)) { return -1; } TiXmlElement* pXmlOrgRoot = XmlOrgGsaDoc.RootElement(); TiXmlDocument* pXmlDoc = new TiXmlDocument(szXmlFileName); TiXmlDeclaration* pXmlDecl = new TiXmlDeclaration("1.0", "gb2312", "yes"); pXmlDoc->LinkEndChild(pXmlDecl); TiXmlElement* pXmlNewRootElement = new TiXmlElement(*pXmlOrgRoot); pXmlDoc->LinkEndChild(pXmlNewRootElement); pXmlDoc->SaveFile(); delete pXmlDoc; return 0; } // 导出 blendTexture 和 propertyTexture bool CTerrain::ExportBlendTexture(const char* szDirectory, bool bSavePropTexture) { // 遍历每一个 chunk char szFilePath[255]; stChunk* pChunk = m_pChunks; for (int i=0; ipChunkMtl->GetTextureBlendResult(); NiSourceTexturePtr pkBlendTexture = pChunk->pChunkMtl->GetBlendTexture(); NiDX9Renderer* pkDX9Renderer = NiDynamicCast(NiDX9Renderer, NiDX9Renderer::GetRenderer()); //LPDIRECT3DBASETEXTURE9 PrepareTextureForRendering(NiTexture* pNewTexIm, bool &bChanged, bool &bMipmap, bool &bNonPow2) // This function takes the NiTexture that is passed in and ensures that it is ready to be rendered. // It returns a pointer to the DX texture that can be used with a NiD3DRenderState::SetTexture call, // and three Boolean values indicating whether the texture needs to be updated, whether the texture // contains mipmaps, and whether it has one or both dimensions that are not round powers of two. bool bChanged = false; bool bMipmap = false; bool bNonPow2 = false; LPDIRECT3DBASETEXTURE9 pD3D9Tex = pkDX9Renderer->GetTextureManager()->PrepareTextureForRendering(pkBlendTexture, bChanged, bMipmap, bNonPow2); char cLast = szDirectory[strlen(szDirectory)-1]; if (cLast=='\\' || cLast == '/') { sprintf_s(szFilePath, "%schunk_blend_texture_%d.dds", szDirectory, i); } else { sprintf_s(szFilePath, "%s\\chunk_blend_texture_%d.dds", szDirectory, i); } if (!bSavePropTexture) { pD3D9Tex = ConvertTextureToDDS((LPDIRECT3DTEXTURE9)pD3D9Tex, D3DFMT_DXT5); } HRESULT hr = D3DXSaveTextureToFileA(szFilePath,D3DXIFF_DDS,pD3D9Tex,NULL); if (FAILED(hr)) { return false; } if (bSavePropTexture) { // 保存 property texture NiSourceTexturePtr pkPropertyTexture = pChunk->pChunkMtl->GetPropertyTexture(); pD3D9Tex = pkDX9Renderer->GetTextureManager()->PrepareTextureForRendering(pkPropertyTexture, bChanged, bMipmap, bNonPow2); if (cLast=='\\' || cLast == '/') { sprintf_s(szFilePath, "%schunk_property_texture_%d.dds", szDirectory, i); } else { sprintf_s(szFilePath, "%s\\chunk_property_texture_%d.dds", szDirectory, i); } hr = D3DXSaveTextureToFileA(szFilePath,D3DXIFF_DDS,pD3D9Tex,NULL); if (FAILED(hr)) { return false; } } else { // 调用 dxtex 转换到dxt5 压缩格式 //static char szCommand[255]; //sprintf(szCommand, "dxtex.exe %s DXT5 %s", szFilePath, szFilePath); //system(szCommand); } //SAFE_RELEASE(pD3D9Tex); pChunk++; } return true; } void CTerrain::ExportTextTexture() { // 创建混合目标纹理 NiTexture::FormatPrefs kPrefs; kPrefs.m_ePixelLayout = NiTexture::FormatPrefs::TRUE_COLOR_32; kPrefs.m_eMipMapped = NiTexture::FormatPrefs::NO; NiPixelDataPtr pResultPixelData = NiNew NiPixelData( BLENDTEX_SIZE, BLENDTEX_SIZE, NiPixelFormat::RGBA32); unsigned char *pPtrResult = ( *pResultPixelData )(0,0); ZeroMemory(pPtrResult, BLENDTEX_SIZE*BLENDTEX_SIZE*4); NiSourceTexture::SetDestroyAppDataFlag( false ); NiSourceTexturePtr pkTexBlendResult = NiSourceTexture::Create( pResultPixelData ); pkTexBlendResult->SetStatic( false ); NiSourceTexture::SetDestroyAppDataFlag( true ); NiDX9Renderer* pkDX9Renderer = NiDynamicCast(NiDX9Renderer, NiDX9Renderer::GetRenderer()); pResultPixelData->MarkAsChanged(); //LPDIRECT3DBASETEXTURE9 PrepareTextureForRendering(NiTexture* pNewTexIm, bool &bChanged, bool &bMipmap, bool &bNonPow2) // This function takes the NiTexture that is passed in and ensures that it is ready to be rendered. // It returns a pointer to the DX texture that can be used with a NiD3DRenderState::SetTexture call, // and three Boolean values indicating whether the texture needs to be updated, whether the texture // contains mipmaps, and whether it has one or both dimensions that are not round powers of two. bool bChanged = true; bool bMipmap = false; bool bNonPow2 = false; LPDIRECT3DBASETEXTURE9 pD3D9Tex = pkDX9Renderer->GetTextureManager()->PrepareTextureForRendering(pkTexBlendResult, bChanged, bMipmap, bNonPow2); HRESULT hr = D3DXSaveTextureToFileA("e:/textTexture1.dds",D3DXIFF_DDS,pD3D9Tex,NULL); if (FAILED(hr)) { return ; } } bool CTerrain::ExportTerrainInfo( const char *pszFile, TiXmlElement* pElmtWalkableObject, /*TiXmlElement* pElmtEntityInfo, TiXmlElement* pElmtBGMusic, */TiXmlElement* pElmtGlobalSetting,const char* pszMapID) { // 将 pszFile 的绝对路径转化为相对路径 char szRelativePath[MAX_PATH]; char szAppPath[MAX_PATH]; char szTmpFileName[MAX_PATH]; NiPath::GetExecutableDirectory(szAppPath, MAX_PATH); if (tolower(pszFile[0]) != tolower(szAppPath[0])) { ERROR_I("导出盘符与场景编辑器所在盘符不符.导出停止。"); return false; } NiPath::ConvertToRelative(szRelativePath, MAX_PATH, pszFile, szAppPath); int iLastSlash = StrFindLast(szRelativePath, '\\'); szRelativePath[iLastSlash+1] = '\0'; TiXmlDocument* pDoc = new TiXmlDocument(pszFile); // 添加兼容中文字符版本信息 [11/23/2009 hemeng] TiXmlDeclaration* pXmlDec = new TiXmlDeclaration("1.0", "gb2312", "yes"); pDoc->InsertEndChild(*pXmlDec); TiXmlElement* pElmMapRoot = new TiXmlElement("Root"); { TiXmlElement* pElmMapInfo = new TiXmlElement("MapInfo"); // 根据存储的文件名判定是否是另存为其他地图编号 [6/23/2010 hemeng] if (pszMapID) { string strSaveMapID = string(pszMapID); DWORD dwSaveMapID = MyStringToDWORD(strSaveMapID); if (dwSaveMapID == m_MapNO) { pElmMapInfo->SetAttribute("MapNumber", m_MapNO); } else { pElmMapInfo->SetAttribute("MapNumber", dwSaveMapID); } } else { pElmMapInfo->SetAttribute("MapNumber", m_MapNO); } pElmMapInfo->SetAttribute("NumChunkX", m_iChunkNumX); pElmMapInfo->SetAttribute("NumChunkY", m_iChunkNumY); // 取消导出etr文件 [5/18/2009 hemeng] sprintf(szTmpFileName, "%s%s", szRelativePath, "Terrain\\"); pElmMapInfo->SetAttribute("TerrainDataFile", szTmpFileName); // [5/18/2009 hemeng] sprintf(szTmpFileName, "%s%s", szRelativePath, "terrainProperty.map"); pElmMapInfo->SetAttribute("TerrainPropertyFile", szTmpFileName); sprintf(szTmpFileName, "%s%s", szRelativePath, "scene.gas"); pElmMapInfo->SetAttribute("SceneFile", szTmpFileName); sprintf(szTmpFileName, "%s%s", szRelativePath, "EntityInfo.xml"); pElmMapInfo->SetAttribute("EntityFile", szTmpFileName); //081225 add by 和萌 策划需求 pElmMapInfo->SetAttribute("RegionScript",".\\Data\\Script\\System\\scene.lua"); sprintf(szTmpFileName,"%s%s",szRelativePath,"RegionDesc.xml"); pElmMapInfo->SetAttribute("RegionDescFile",szTmpFileName); pElmMapRoot->LinkEndChild(pElmMapInfo); // 修改文件描述信息以便导出为dll [5/18/2009 hemeng] TiXmlElement* pElmChunkInfoRoot = new TiXmlElement("ChunkInfoRoot"); pElmChunkInfoRoot->SetAttribute("CheckCompounds","true"); pElmMapRoot->LinkEndChild(pElmChunkInfoRoot); { // all chunks info for (int i=0; iSetAttribute("ChunkID", i); pElmChunkInfo->SetAttribute("UsedTexLayer", m_pChunks[i].pChunkMtl->GetUsedLayerCount()); char szBlendTexFile[MAX_PATH]; sprintf(szBlendTexFile, "%sTerrain/chunk_blend_texture_%d.dds", szRelativePath, i); pElmChunkInfo->SetAttribute("BlendTexture", szBlendTexFile); for (int j=0; jGetUsedLayerCount(); j++) { TiXmlElement* pElmChunkTex = new TiXmlElement("Texture"); pElmChunkTex->SetAttribute("TextureID", j); pElmChunkTex->SetAttribute("FileName", m_pChunks[i].pChunkMtl->GetTextureFile(j).c_str()); pElmChunkInfo->LinkEndChild(pElmChunkTex); } pElmChunkInfoRoot->LinkEndChild(pElmChunkInfo); } } pElmMapRoot->LinkEndChild(pElmtWalkableObject); /*pElmMapRoot->LinkEndChild(pElmtEntityInfo); pElmMapRoot->LinkEndChild(pElmtBGMusic);*/ pElmMapRoot->LinkEndChild(pElmtGlobalSetting); } pDoc->LinkEndChild(pElmMapRoot); pDoc->SaveFile(pszFile); delete pDoc; return true; } // 导出地形信息给任务编辑器。包括草图和 void CTerrain::ExportTerrainInfoToMissionEditor(const char* pszPath, vector& aObjList) { // 导出场景信息 xml char szFileName[MAX_PATH]; sprintf(szFileName, "%s\\%d%s", pszPath, m_MapNO, ".xml"); TiXmlDocument* pDoc = new TiXmlDocument(szFileName); TiXmlElement* pElmMapRoot = new TiXmlElement("Root"); { TiXmlElement* pElmMapInfo = new TiXmlElement("MapInfo"); pElmMapInfo->SetAttribute("MapNumber", m_MapNO); pElmMapInfo->SetAttribute("DimX", m_iChunkNumX*GRIDINCHUNK); pElmMapInfo->SetAttribute("DimY", m_iChunkNumY*GRIDINCHUNK); pElmMapRoot->LinkEndChild(pElmMapInfo); } pDoc->LinkEndChild(pElmMapRoot); pDoc->SaveFile(); // 导出场景缩略图 NiRenderer* pkRenderer = NiRenderer::GetRenderer(); NiTexture::FormatPrefs kPrefs; kPrefs.m_ePixelLayout = NiTexture::FormatPrefs::TRUE_COLOR_32; kPrefs.m_eMipMapped = NiTexture::FormatPrefs::NO; NiRenderedTexturePtr pkTargetTexture = NiRenderedTexture::Create(1024, 1024, pkRenderer, kPrefs, Ni2DBuffer::MULTISAMPLE_NONE); NiRenderTargetGroupPtr pkRTG = NiRenderTargetGroup::Create(pkTargetTexture->GetBuffer(), pkRenderer, true, true); NiCamera kCamera; //kCamera.SetTranslate(-kLitDir*50.0); kCamera.LookAtWorldPoint(NiPoint3(0,0,-1), NiPoint3(0,1,0)); kCamera.SetTranslate(0,0,50); kCamera.Update(0.0f); int iMaxLength = max(m_iChunkNumX, m_iChunkNumY); NiFrustum kFrustum(0 , iMaxLength*GRIDINCHUNK, iMaxLength*GRIDINCHUNK, 0, 0.1f, 1000.0f, true); kCamera.SetViewFrustum(kFrustum); kCamera.Update(0.0f); pkRenderer->BeginOffScreenFrame(); { NiVisibleArray kVisibleArray; NiCullingProcess kCullProcess(&kVisibleArray); NiEntityRenderingContext kRenderingContext; kRenderingContext.m_pkCamera = &kCamera; kRenderingContext.m_pkCullingProcess = &kCullProcess; kRenderingContext.m_pkRenderer = pkRenderer; pkRenderer->BeginUsingRenderTargetGroup(pkRTG, NiRenderer::CLEAR_ALL); pkRenderer->SetCameraData(&kCamera); NiCullScene(&kCamera, m_spTerrainRoot, kCullProcess, kVisibleArray, true); for (unsigned int i=0; iEndUsingRenderTargetGroup(); } pkRenderer->EndOffScreenFrame(); sprintf(szFileName, "%s\\%d%s", pszPath, m_MapNO, ".jpg"); SaveTextureToJPG(pkTargetTexture, szFileName); } ////////////////////////////////////////////////////////////////////////// //导出Grid属性到文件 void CTerrain::ExportGridProPerty(const char *pszFile) { //本地化,防止路径为中文不能识别 std::locale::global(std::locale("")); //Grid数据 int iGridX = m_iChunkNumX * GRIDINCHUNK; int iGridY = m_iChunkNumY * GRIDINCHUNK; int index = 0; ofstream fOut; fOut.open( pszFile,ios::binary); //写入地图号 fOut.write( (char*)(&m_MapNO),sizeof(m_MapNO) ); //写入Grid长宽 fOut.write( (char*)(&iGridX), sizeof(iGridX) ); fOut.write( (char*)(&iGridY), sizeof(iGridY) ); for (int i =0; i < iGridY; i++) { for (int j = 0; j< iGridX;j++) { int iGridProperty = m_pGrids[index++].iTerrainProperty; //写入地表属性 fOut.write( (char*)(&iGridProperty), sizeof(iGridProperty) ); } } fOut.close(); } ////////////////////////////////////////////////////////////////////////// //导入Grid属性文件到地形 void CTerrain::ImportGridProPerty(const char *pszFile) { std::locale::global(std::locale("")); //Grid数据 int iGridX = m_iChunkNumX * GRIDINCHUNK; int iGridY = m_iChunkNumY * GRIDINCHUNK; int iInGridX; int iInGridY; DWORD dwInMapNO; int index = 0; //获得属性纹理 stChunk* pChunk = m_pChunks; NiSourceTexturePtr pkPropertyTexture = pChunk->pChunkMtl->GetPropertyTexture(); if ( !pkPropertyTexture ) return; ifstream fIn; fIn.open(pszFile,ios::binary); //读入地图编号 fIn.read( (char*)(&dwInMapNO),sizeof(dwInMapNO) ); if (dwInMapNO != m_MapNO) { NiMessageBox("导入信息不属于是当前地图!","Warn",0); } //读入Grid信息 fIn.read( (char*)(&iInGridX), sizeof(iInGridX) ); fIn.read( (char*)(&iInGridY), sizeof(iInGridY) ); if (iInGridX != iGridX || iInGridY != iGridY) { NiMessageBox("导入地形大小不匹配!","error",0); return; } for (int i = 0; i < iGridY; i++) { for (int j = 0; j < iGridX; j++) { int iTerrPro; fIn.read( (char*)&iTerrPro,sizeof(int) ); m_pGrids[index].iTerrainProperty = iTerrPro; index ++; } } fIn.close(); //重绘属性纹理 for (int i = 0; i < iGridX * iGridY; i++) { int iTerrPro = (m_pGrids[i].iTerrainProperty & 0x0000000f); CTerrain::stGrid &grid = m_pGrids[i]; // 显示设置 NiPoint3 vLeftBtm = m_pVertices[ grid.iPointIndx[0] ]; NiPoint3 vRightTop = m_pVertices[ grid.iPointIndx[2] ]; int iChunkIndx = GetChunkIndex( ( vLeftBtm+vRightTop) * 0.5f ); CTerrain::stChunk& chunk = m_pChunks[iChunkIndx]; CTerrainMaterial *pMtl = chunk.pChunkMtl; int iSize = pMtl->GetBlendTexSize(); float fLeft = iSize * ( vLeftBtm.x - chunk.vPosMin.x ) / ( chunk.vPosMax.x - chunk.vPosMin.x ); float fRight = iSize * ( vRightTop.x - chunk.vPosMin.x ) / ( chunk.vPosMax.x - chunk.vPosMin.x ); float fBtm = iSize * ( vLeftBtm.y - chunk.vPosMin.y ) / ( chunk.vPosMax.y - chunk.vPosMin.y ); float fTop = iSize * ( vRightTop.y - chunk.vPosMin.y ) / ( chunk.vPosMax.y - chunk.vPosMin.y ); pMtl->SetTerrainPropertyA( NiRect( fLeft, fRight, fTop, fBtm ), iTerrPro ); } } bool CTerrain::ExportGridProPertyTexture(const char *szDirectory ) { // 遍历每一个 chunk stChunk* pChunk = m_pChunks; for (int i=0; ipChunkMtl->GetTextureBlendResult(); NiSourceTexturePtr pkBlendTexture = pChunk->pChunkMtl->GetBlendTexture(); NiDX9Renderer* pkDX9Renderer = NiDynamicCast(NiDX9Renderer, NiDX9Renderer::GetRenderer()); //LPDIRECT3DBASETEXTURE9 PrepareTextureForRendering(NiTexture* pNewTexIm, bool &bChanged, bool &bMipmap, bool &bNonPow2) // This function takes the NiTexture that is passed in and ensures that it is ready to be rendered. // It returns a pointer to the DX texture that can be used with a NiD3DRenderState::SetTexture call, // and three Boolean values indicating whether the texture needs to be updated, whether the texture // contains mipmaps, and whether it has one or both dimensions that are not round powers of two. bool bChanged = false; bool bMipmap = false; bool bNonPow2 = false; LPDIRECT3DBASETEXTURE9 pD3D9Tex = pkDX9Renderer->GetTextureManager()->PrepareTextureForRendering(pkBlendTexture, bChanged, bMipmap, bNonPow2); char szFilePath[255]; char cLast = szDirectory[strlen(szDirectory)-1]; // 导出 property texture NiSourceTexturePtr pkPropertyTexture = pChunk->pChunkMtl->GetPropertyTexture(); pD3D9Tex = pkDX9Renderer->GetTextureManager()->PrepareTextureForRendering(pkPropertyTexture, bChanged, bMipmap, bNonPow2); if (cLast=='\\' || cLast == '/') { sprintf_s(szFilePath, "%schunk_property_texture_%d.dds", szDirectory, i); } else { sprintf_s(szFilePath, "%s\\chunk_property_texture_%d.dds", szDirectory, i); } HRESULT hr = D3DXSaveTextureToFileA(szFilePath,D3DXIFF_DDS,pD3D9Tex,NULL); if (FAILED(hr)) { return false; } pChunk++; } return true; } #endif