#include "StdAfx.h" #include "GrideBaseRiver.h" #ifndef CODE_INGAME CGrideBaseRiver* CGrideBaseRiver::m_spThis = NULL; CGrideBaseRiver::CGrideBaseRiver(void) { m_pTerrain = NULL; m_spRiverMesh = NULL; } CGrideBaseRiver::~CGrideBaseRiver(void) { if (m_spRiverMesh != NULL) { //m_pTerrain = NULL; m_spRiverMesh = NULL; } } CGrideBaseRiver* CGrideBaseRiver::GetInstance() { if (m_spThis == NULL) { m_spThis = new CGrideBaseRiver(); } return m_spThis; } bool CGrideBaseRiver::Init(CTerrain* pTerrain, float fDesAlpha, float fHeight,NiColor kColor,std::set& gridSet) { if (pTerrain == NULL) { return false; } m_pTerrain = pTerrain; m_fAlphaDet = fDesAlpha; m_fRiverHeight = fHeight; m_kColor = kColor; m_vGridSet.clear(); m_mapRiverPointInfo.clear(); set::iterator iter = gridSet.begin(); for (iter; iter != gridSet.end(); iter++) { int iTerrainIndex = _InsertPointToRiver((*iter)); if (iTerrainIndex != -1) { // 将点插入数组 m_vGridSet.push_back(iTerrainIndex); // 将点信息插入信息数组 stRiverPoint stPoint; stPoint.kVertex = m_pTerrain->GetVertex(iTerrainIndex); stPoint.kVertexClr = NiColorA(m_kColor.r, m_kColor.g, m_kColor.b, _GetAlphaValue(stPoint.kVertex)); // 计算alpha后 设置顶点高度为水体高度 stPoint.kVertex.z = m_fRiverHeight; m_mapRiverPointInfo.insert( map::value_type( iTerrainIndex,stPoint ) ); } } // 连接三角形 _BuildTriangles(); // 创建几何体 if (_GenerateRiverGeom() == false) { NiMessageBox("Error","创建水体几何体出错!",0); return false; } return true; } void CGrideBaseRiver::DoDispose() { if (m_spThis != NULL) { delete m_spThis; m_spThis = NULL; } } bool CGrideBaseRiver::_GenerateRiverGeom() { ////////////////////////////////////////////////////////////////////////// //注意:生成几何形NiTriShape中的顶点个数和多边形个数都不能大于unsigned short // 65535个,否则在创建几何形时无法创建出所需的几何形 unsigned int uiVertNum = m_vGridSet.size(); if (uiVertNum == 0) { return false; } DWORD terrainIndex = 0; if ( uiVertNum > 65535 ) { NiMessageBox("顶点数越界","error",0); return false; } // 分配渲染数据 // test NiPoint3* pkVerts = NiNew NiPoint3[uiVertNum]; NiPoint3* pkNormals = NiNew NiPoint3[uiVertNum]; NiColorA* pkColors = NiNew NiColorA[uiVertNum]; unsigned short* pTriList; unsigned int uiTriCount = m_stTri.size(); if ( uiTriCount > 65535 ) { NiMessageBox("三角形数越界","error",0); return false; } pTriList = NiAlloc( unsigned short, uiTriCount * 3 ); for (unsigned int uiIndex = 0; uiIndex < uiVertNum; uiIndex ++) { terrainIndex = m_vGridSet[uiIndex]; pkVerts[uiIndex] = m_mapRiverPointInfo[terrainIndex].kVertex; pkNormals[uiIndex] = NiPoint3(0.0f,0.0f,1.0f); pkColors[uiIndex] = m_mapRiverPointInfo[terrainIndex].kVertexClr; } ////////////////////////////////////////////////////////////////////////// //连接三角形 DWORD TriIndex = 0; for ( DWORD i = 0; i < uiTriCount; i ++ ) { if ( TriIndex >= uiTriCount * 3 ) { NiMessageBox("三角形个数越界","error",0); return false; } pTriList[ TriIndex ++ ] = m_stTri[i].uiP0; pTriList[ TriIndex ++ ] = m_stTri[i].uiP1; pTriList[ TriIndex ++ ] = m_stTri[i].uiP2; } // 生成几何数据 NiTriShapeDynamicData *pData = NiNew NiTriShapeDynamicData( uiVertNum, pkVerts, pkNormals, pkColors, 0, 1, NiGeometryData::NBT_METHOD_NONE, uiTriCount, pTriList, uiVertNum, uiTriCount ); m_spRiverMesh = NiNew NiTriShape( pData ); // 设置名字 char szName[16] = "River"; m_spRiverMesh->SetName(szName); NiVertexColorProperty * pVertexProp = NiNew NiVertexColorProperty; pVertexProp->SetLightingMode( NiVertexColorProperty::LIGHTING_E ); pVertexProp->SetSourceMode( NiVertexColorProperty::SOURCE_EMISSIVE ); m_spRiverMesh->AttachProperty( pVertexProp ); //////设置alpha属性 NiAlphaProperty* pkAlphaProp = NiNew NiAlphaProperty(); pkAlphaProp->SetAlphaBlending(true); pkAlphaProp->SetSrcBlendMode(NiAlphaProperty::ALPHA_SRCALPHA); pkAlphaProp->SetDestBlendMode(NiAlphaProperty::ALPHA_INVSRCALPHA); m_spRiverMesh->AttachProperty(pkAlphaProp); //设置显示为网格,仅供测试 //NiWireframeProperty* pkWireframeProp = NiNew NiWireframeProperty(); //pkWireframeProp->SetWireframe(true); //m_RiverRegion->pkRiverGeom->AttachProperty(pkWireframeProp); m_spRiverMesh->UpdateProperties(); m_spRiverMesh->Update(0.0f); m_spRiverMesh->UpdateEffects(); return true; } unsigned int CGrideBaseRiver::_BuildTriangles() { if ( m_vGridSet.size() == 0 ) { return 0; } //清空三角形连接列表 m_stTri.clear(); int scanline = m_pTerrain->GetChunkNumX() * GRIDINCHUNK + 1; int iTotalVertexCount = scanline * (m_pTerrain->GetChunkNumY() * GRIDINCHUNK + 1); /////////////////////////////////////////////////////////////////////////// // //添加顶点索引 for (int iIndex = 0; iIndex < (int)m_vGridSet.size(); iIndex++) { int iVertexIndex = m_vGridSet[iIndex]; stTriList stTri; //此处并为检查加值是否存在于terrain上 ////////////////////////////////////////////////////////////////////////// // 3*------*2 // | | // | | // @------* // 0 1 int p[4] = {iVertexIndex, iVertexIndex + 1, iVertexIndex+(scanline*1)+1, iVertexIndex+(scanline*1)}; bool temp[4] = {true,true,true,true}; ////////////////////////////////////////////////////////////////////////// //判断是否超出terrian范围,索引位置是否正确 // *横向越界没有检查 for (int j = 0; j < 4; j++) { //检查多边形各点是否存在于terrain上 if (p[j] > iTotalVertexCount) { //NiMessageBox("多边形越界","error",0); temp[j] = false; } //检查是否为右边界点 if (p[j] % scanline == (scanline-1)) { temp[j] = false; } } ////////////////////////////////////////////////////////////////////////// //多边形4顶点均满足以上2项,则添加多边形 if (temp[0] && temp[1] && temp[2] && temp[3]) { ////////////////////////////////////////////////////////////////////////// // /*2 // / | // / | // @------* // 0 1 // // *------* // | / // | / // |/ // @ //如果对角线点都在水域内则添加多边形 if ( _ExistPoint(p[2]) == true ) { if (_ExistPoint(p[1]) == true) { stTri.uiP0 = _GetRiverVerticeIndex(p[0]); stTri.uiP1 = _GetRiverVerticeIndex(p[1]); stTri.uiP2 = _GetRiverVerticeIndex(p[2]); m_stTri.push_back(stTri); } if (_ExistPoint(p[3]) == true) { stTri.uiP0 = _GetRiverVerticeIndex(p[0]); stTri.uiP1 = _GetRiverVerticeIndex(p[2]); stTri.uiP2 = _GetRiverVerticeIndex(p[3]); m_stTri.push_back(stTri); } } //对角线不在水域内 ////////////////////////////////////////////////////////////////////////// // * // | \ // | \ // @------* else { //1 3点都存在 if (_ExistPoint(p[1]) == true && _ExistPoint(p[3]) == true) { stTri.uiP0 = _GetRiverVerticeIndex(p[0]); stTri.uiP1 = _GetRiverVerticeIndex(p[1]); stTri.uiP2 = _GetRiverVerticeIndex(p[3]); m_stTri.push_back(stTri); } } } //当下对角线点不在水域中 ////////////////////////////////////////////////////////////////////////// // *----@ // \ | // \ | // \* // if (_ExistPoint( iVertexIndex-scanline-1 ) == false) { //左、下点均在水域中 if (_ExistPoint(iVertexIndex-1) == true && _ExistPoint(iVertexIndex-scanline) == true) { stTri.uiP0 = _GetRiverVerticeIndex(iVertexIndex-scanline); stTri.uiP1 = _GetRiverVerticeIndex(iVertexIndex); stTri.uiP2 = _GetRiverVerticeIndex(iVertexIndex-1); m_stTri.push_back(stTri); } } } return m_stTri.size(); } float CGrideBaseRiver::_GetAlphaValue(NiPoint3 kPoint) { float fAlpha = 0.0f; if (kPoint.z >= m_fRiverHeight) { fAlpha = 0.0f; }//end of if kPoint else if (kPoint.z < m_fRiverHeight) { //计算递增量 fAlpha = abs(m_fRiverHeight - kPoint.z) * m_fAlphaDet; fAlpha = min(fAlpha,1); }//end of else if return fAlpha; } bool CGrideBaseRiver::_ExistPoint(int iTerrainIndex) { if (iTerrainIndex < 0) { return false; } if (m_mapRiverPointInfo.count(iTerrainIndex) == 1) { return true; } else { return false; } } int CGrideBaseRiver::_GetRiverVerticeIndex(int iTerrainIndex) { if (iTerrainIndex < 0) { return -1; } for (unsigned int uiIndex = 0 ; uiIndex < m_vGridSet.size(); uiIndex++) { if (m_vGridSet[uiIndex] == iTerrainIndex) { return (int)uiIndex; } } return -1; } int CGrideBaseRiver::_InsertPointToRiver(int iGridID) { if (iGridID < 0) { return -1; } int iNumGridX = m_pTerrain->GetChunkNumX() * GRIDINCHUNK; // Grid 数量 int iNumGridY = m_pTerrain->GetChunkNumY() * GRIDINCHUNK; int scanline = iNumGridX + 1; int x = iGridID % iNumGridX; int y = iGridID / iNumGridX; /* 1__ 2 | /| |/_| 0 3 */ // 获取 grid 四个顶点索引 static int idx[4]; idx[0] = y * scanline + x; idx[1] = idx[0] + scanline; idx[2] = idx[1] + 1; idx[3] = idx[0] + 1; bool bUnderWater = false; for (int i = 0; i < 4; i++) { if (bUnderWater == true) { break; } NiPoint3 kCurPos = m_pTerrain->GetVertex(idx[i]); if (kCurPos.z > m_fRiverHeight) { continue; } else { bUnderWater = true; } } if (bUnderWater == true) { return idx[0]; } else { return -1; } } #endif