/** @file RiverOptimizer.cpp @brief
* Copyright (c) 2007,第九城市游戏研发中心 * All rights reserved. * * 当前版本: * 作 者:和萌 * 完成日期:2008- * * 取代版本: * 作 者: * 完成日期:*/ #include "StdAfx.h" #include "RiverOptimizer.h" #ifndef CODE_INGAME CRiverOptimizer::CRiverOptimizer(CRiverManager* pRiverManager, CTerrain *pTerrain) :m_ucpQuadMatrix(NULL), m_bIsRiverChunk(NULL) { m_pRiverManager = pRiverManager; m_pTerrain = pTerrain; if ( Initial() == false) { NiMessageBox("水域优化器初始化建失败","failed",0); } } CRiverOptimizer::~CRiverOptimizer(void) { if (m_ucpQuadMatrix != NULL) { SAFE_DELETE_ARRAY(m_ucpQuadMatrix); } if ( m_bIsRiverChunk != NULL ) { delete m_bIsRiverChunk; m_bIsRiverChunk = NULL; } } bool CRiverOptimizer::Initial() { if (_CreateRiverChunks() == false) { NiMessageBox("水域外包矩形创建失败","failed",0); return false; } //初始化外包矩形内所有点LOD标志 else { unsigned int uiNumVertexX = m_iRiverChunkX * VERTEXINCHUNK + 1; //X方向顶点数 unsigned int uiNumVertexY = m_iRiverChunkY * VERTEXINCHUNK + 1; //Y方向顶点数 unsigned int uiTotalVertex = uiNumVertexX * uiNumVertexY; m_ucpQuadMatrix = new unsigned char[uiTotalVertex]; if (NULL == m_ucpQuadMatrix) { LOG("CRiverOptimizer::Optimize 内存分配失败"); return false; } memset(m_ucpQuadMatrix, 0, uiTotalVertex); m_bIsRiverChunk = new bool[m_iRiverChunkX * m_iRiverChunkY]; if (NULL == m_ucpQuadMatrix) { LOG("CRiverOptimizer::Optimize RiverChunk内存分配失败"); return false; } else { for (unsigned int i = 0; i < m_iRiverChunkX * m_iRiverChunkY; i++) { m_bIsRiverChunk[i] = true; } } } return true; } bool CRiverOptimizer::Optimize() { if (m_ucpQuadMatrix == NULL || m_bIsRiverChunk == NULL) { return false; } for (unsigned int uiY = 0; uiY < m_iRiverChunkY; uiY++) { for (unsigned int uiX = 0; uiX < m_iRiverChunkX; uiX++) { _IsUsedInRiver( uiX, uiY ); } } return true; } unsigned int CRiverOptimizer::GetRiverChunkNumX() { return m_iRiverChunkX; } unsigned int CRiverOptimizer::GetRiverChunkNumY() { return m_iRiverChunkY; } bool CRiverOptimizer::_CreateRiverChunks() { //或的水域最大、最小坐标 NiPoint2 minPoint,maxPoint; stRiverRegion *pRiver = m_pRiverManager->GetRiverData(); unsigned int uiVertexCount = m_pRiverManager->GetRiverVerticCount(); DWORD dwTerrIndex = pRiver->dwTerrainIndex[0]; NiPoint3 kPoint = pRiver->mVertex[dwTerrIndex].kVertex; m_kMaxPoint = kPoint; m_kMinPoint = kPoint; //外包矩形向左、下位移2,防止矩形越界 minPoint.x = kPoint.x - 2; minPoint.x = max( kPoint.x, 0 ); minPoint.y = kPoint.y - 2; minPoint.y = max( kPoint.y, 0 ); maxPoint = minPoint; for (unsigned int i = 0; i < uiVertexCount; i++) { dwTerrIndex = pRiver->dwTerrainIndex[i]; kPoint = pRiver->mVertex[dwTerrIndex].kVertex; minPoint.x = min( minPoint.x, kPoint.x ); minPoint.y = min( minPoint.y, kPoint.y ); maxPoint.x = max( maxPoint.x, kPoint.x ); maxPoint.y = max( maxPoint.y, kPoint.y ); } if (minPoint.x == maxPoint.x || minPoint.y == maxPoint.y) { return false; } //将最大,最小坐标差归一化到4的倍数 int iTemp; //横向顶点个数 unsigned int iVertexNumX = unsigned int( maxPoint.x - minPoint.x ); //与4的倍数的差值 iTemp = WIDTHEBITY(iVertexNumX) - iVertexNumX; maxPoint.x = maxPoint.x +iTemp; m_iRiverChunkX = WIDTHEBITY(iVertexNumX) / 4; //纵向顶点个数 unsigned int iVertexNumY = unsigned int( maxPoint.y - minPoint.y ); iTemp = WIDTHEBITY(iVertexNumY) - iVertexNumY; maxPoint.y = maxPoint.y + iTemp; m_iRiverChunkY = WIDTHEBITY(iVertexNumY) / 4; ////////////////////////////////////////////////////////////////////////// //测试用代码 m_kMinPoint.x = minPoint.x; m_kMinPoint.y = minPoint.y; m_kMaxPoint.x = maxPoint.x; m_kMaxPoint.y = maxPoint.y; return true; } DWORD CRiverOptimizer::_GetTerrainIndex(float fX,float fY) { return ( _GetScanline() * fY + fX ); } DWORD CRiverOptimizer::_GetScanline() { return ( m_pTerrain->GetChunkNumX() * GRIDINCHUNK + 1 ); } bool CRiverOptimizer::_IsUsedInRiver(unsigned int uiChunkX, unsigned int uiChunkY) { //或的当前RiverChunk的偏移量 float uiVertexOffsetX = (float)uiChunkX * VERTEXINCHUNK; float uiVertexOffsetY = (float)uiChunkY * VERTEXINCHUNK; DWORD dwTerrainIndex = _GetTerrainIndex( uiVertexOffsetX, uiVertexOffsetY ); for (unsigned int uiY = 0; uiY < VERTEXINCHUNK; uiY++) { uiVertexOffsetY += uiY * _GetScanline(); for (unsigned int uiX = 0; uiX < VERTEXINCHUNK; uiX++) { uiVertexOffsetX += uiX; dwTerrainIndex = _GetTerrainIndex( uiVertexOffsetX,uiVertexOffsetY ); if (m_pRiverManager->IsExistPos(dwTerrainIndex) == true) { return true; } } } return false; } #endif