#include "StdAfx.h" #ifndef CODE_INGAME #include "FogSurfaceMaker.h" #include "NiOptimize.h" using namespace SceneCore; //----------------------------------------------------------------------------- CFogSurfaceMaker::CFogSurfaceMaker(CTerrain* pkTerrain) : m_pkTerrain(pkTerrain), m_spFogGeometry(NULL), m_pGridList(NULL) { } //----------------------------------------------------------------------------- CFogSurfaceMaker::~CFogSurfaceMaker(void) { m_spFogGeometry = NULL; SAFE_DELETE_ARRAY(m_pGridList); } //----------------------------------------------------------------------------- bool CFogSurfaceMaker::Make(const stSimpleFogPrarm param) { if (m_pkTerrain == NULL) { return false; } SAFE_DELETE_ARRAY(m_pGridList); int iNumVertTotalX = m_pkTerrain->GetTotalSize().x+1; int iNumVertTotalY = m_pkTerrain->GetTotalSize().y+1; // 1. 获取目标区域内按照 terrain grid 尺寸的 grid, 并且初始化 int iLeft = max(0, (int)param.kLBPoint.x); int iRight = min(iNumVertTotalX-1, (int)param.kRUPoint.x); int iBottom = max(0, (int)param.kLBPoint.y); int iTop = min(iNumVertTotalY-1, (int)param.kRUPoint.y); int iGridInRow = iRight-iLeft; int iGridInColum = iTop-iBottom; m_iNumGridX = iGridInRow; m_iNumGridY = iGridInColum; // Fog Geometry 第一个顶点(左下)坐标 int iOffsetX = iLeft; int iOffsetY = iBottom; m_pGridList = new stFogGrid[iGridInColum*iGridInRow]; int iIdx = 0; for (int i=0; iGetVertices(); iIdx = 0; for (int i=0; i pVertices[m_pGridList[iIdx].i0].z; bool bOver1 = param.fStartZ > pVertices[m_pGridList[iIdx].i1].z; bool bOver2 = param.fStartZ > pVertices[m_pGridList[iIdx].i2].z; bool bOver3 = param.fStartZ > pVertices[m_pGridList[iIdx].i3].z; if (bOver0 && bOver1 && bOver2 && bOver3) { // 完全在地形之上 if (i==0 || i==iGridInColum-1 || j==0 || j==iGridInRow-1) { // 边缘的 grid m_pGridList[iIdx].locationState = GS_OUTSIDE; m_pGridList[iIdx].combineState = GS_DELETED; } else { m_pGridList[iIdx].locationState = GS_INSIDE; m_pGridList[iIdx].combineState = GS_UNDESIDED; } } else if(!bOver0 && !bOver1 && !bOver2 && !bOver3) { // 完全地形之下 m_pGridList[iIdx].locationState = GS_UNDERGROUND; m_pGridList[iIdx].combineState = GS_DELETED; } else { if (i==0 || j==0 || i==iGridInColum-1 || j==iGridInRow-1) { m_pGridList[iIdx].locationState = GS_HALFOUTSIDE; m_pGridList[iIdx].combineState = GS_DELETED; } else { m_pGridList[iIdx].locationState = GS_HALFINSIDE; m_pGridList[iIdx].combineState = GS_UNDESIDED; } } } } // 2.2 从边缘 grid 遍历所有邻居 grid. // // 如果是 GS_INSIDE 改为 GS_OUTSIDE.并从该节点开始遍历邻居 // 如果是 GS_HALFINSIDE 改为 GS_HALFOUTSIDE.并从该节点开始遍历邻居 // 如果是 GS_UNDERGROUND, GS_HALFOUTSIDE, GS_OUTSIDE 不遍历该节点 // 遍历四条外边 // 左边, 右边 for (int iY=0; iY::iterator iter = m_OpenList.begin(); while (iter != m_OpenList.end()) { iter = _DecideLocation(iter); //iter++; } //Debug_OutputGrid("e:\\before_combine.txt"); // 3 合并 grid _CombineAllGrids(); //Debug_OutputGrid("e:\\after_combine.txt"); //Debug_OutputGrid("e:\\gridCombine.txt"); // 4 根据合并的 grid 生成 geometry vector gridIdList; //iIdx = 0; for (int i=0; iGetVertices(); int iVertNum = gridIdList.size()*4; // 顶点数量 int iTriNum = gridIdList.size()*2; // 三角形数量 NiPoint3* pVerts = NiNew NiPoint3[iVertNum]; NiPoint3* pNormals = NiNew NiPoint3[iVertNum]; NiPoint2* pTexCoords = NiNew NiPoint2[iVertNum]; NiColorA* pColors = NiNew NiColorA[iVertNum]; WORD *pConnect = NiAlloc(WORD, iTriNum*3); int dX = param.kRUPoint.x-param.kLBPoint.x; int dY = param.kRUPoint.y-param.kLBPoint.y; for (unsigned int i=0; iUpdate(0.0f); //m_spFogGeometry->PrependController() //NiOptimize::OptimizeTriShape(m_spFogGeometry); //m_spFogGeometry->Update(0.0f); // 优化 return true; } //----------------------------------------------------------------------------- NiTriShape* CFogSurfaceMaker::GetFogGeometry() { return m_spFogGeometry; } //----------------------------------------------------------------------------- list::iterator CFogSurfaceMaker::_DecideLocation(list::iterator iter) { int iCurrX = (*iter)._iX; int iCurrY = (*iter)._iY; // 遍历周围8个grid for (int i=-1; i<2; i++) { for (int j=-1; j<2; j++) { if (i==0 && j==0) // 忽略当前节点 { continue; } static int iX; iX = iCurrX+i; static int iY; iY = iCurrY+j; // 判断当前 grid 坐标是否合法 if (iX<0 || iY<0 || iX>=m_iNumGridX || iY>=m_iNumGridY) { // 不合法 continue; } static int iIdx; iIdx = iY*m_iNumGridX+iX; if (m_pGridList[iIdx].locationState == GS_INSIDE) { m_pGridList[iIdx].locationState = GS_OUTSIDE; m_pGridList[iIdx].combineState = GS_DELETED; //_RecursiveDecideLocation(iX, iY); m_OpenList.push_back(stGridCoord(iX, iY)); } else if(m_pGridList[iIdx].locationState == GS_HALFINSIDE) { m_pGridList[iIdx].locationState = GS_HALFOUTSIDE; m_pGridList[iIdx].combineState = GS_DELETED; m_OpenList.push_back(stGridCoord(iX, iY)); } else if(m_pGridList[iIdx].locationState == GS_UNDERGROUND) { //m_pGridList[iIdx].locationState = GS_HALFOUTSIDE; m_pGridList[iIdx].combineState = GS_DELETED; //_RecursiveDecideLocation(iX, iY, iNumGridsX, iNumGridsY); } } } return m_OpenList.erase(iter); } //----------------------------------------------------------------------------- void CFogSurfaceMaker::_CombineAllGrids() { // 从下向上,从左向右遍历所有 grid. // 对于每个 grid // 如果 combineState 为 GS_DELETED 忽略该节点 // 如果 combineState 为 GS_UNDESIDED, 改为GS_COMBINED。将该节点作为当前节点。 // 以矩形向右上合并 GS_UNDESIDED 节点,改变本节点的顶点索引。 // 被合并的节点变为 GS_DELETE。 int iGridID = 0; for (int i=0; i gridIDList; //bool bCombine = true; // 向右方扩展 for (int i=1; i