// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "std3d.h" #include "nel/3d/load_balancing_trav.h" #include "nel/3d/hrc_trav.h" #include "nel/3d/clip_trav.h" #include "nel/misc/common.h" #include "nel/misc/hierarchical_timer.h" #include "nel/3d/transform.h" using namespace std; using namespace NLMISC; // *************************************************************************** #define NL3D_DEFAULT_LOADBALANCING_VALUE_SMOOTHER 50 #define NL3D_LOADBALANCING_SMOOTHER_MAX_RATIO 1.1f namespace NL3D { // *************************************************************************** // *************************************************************************** // *************************************************************************** // *************************************************************************** // *************************************************************************** CLoadBalancingGroup::CLoadBalancingGroup() { _PrecPolygonBalancingMode= CLoadBalancingGroup::PolygonBalancingOff; _NbFaceWanted= 20000; _ValueSmoother.init(NL3D_DEFAULT_LOADBALANCING_VALUE_SMOOTHER); _DefaultGroup= false; _NbFacePass0= 0; _FaceRatio= 1; } // *************************************************************************** void CLoadBalancingGroup::computeRatioAndSmooth(TPolygonBalancingMode polMode) { // If Default group, disable load balancing if(_DefaultGroup) polMode= PolygonBalancingOff; // Compute ratio switch(polMode) { case PolygonBalancingOff: _FaceRatio= 1; break; case PolygonBalancingOn : if(_NbFacePass0!=0) _FaceRatio= (float)_NbFaceWanted / _NbFacePass0; else _FaceRatio= 1; break; case PolygonBalancingClamp: if(_NbFacePass0!=0) _FaceRatio= (float)_NbFaceWanted / _NbFacePass0; else _FaceRatio= 1; clamp(_FaceRatio, 0, 1); break; default: break; }; // smooth the value. // if change of PolygonBalancingMode, reset the _ValueSmoother. if(polMode!=_PrecPolygonBalancingMode) { _ValueSmoother.init(NL3D_DEFAULT_LOADBALANCING_VALUE_SMOOTHER); _PrecPolygonBalancingMode= polMode; } // if not PolygonBalancingOff, smooth the ratio. if(polMode!=PolygonBalancingOff) { // FIX: If the _FaceRatio is not a float (NaN or +-oo), don't add it!! if(isValidDouble(_FaceRatio)) _ValueSmoother.addValue(_FaceRatio); float fSmooth= _ValueSmoother.getSmoothValue(); // If after smoothing, the number of faces is still too big, reduce smooth effect! (frustrum clip effect) if(fSmooth*_NbFacePass0 > _NbFaceWanted*NL3D_LOADBALANCING_SMOOTHER_MAX_RATIO) { // reset the smoother _ValueSmoother.reset(); // reduce smooth effect fSmooth= _FaceRatio*NL3D_LOADBALANCING_SMOOTHER_MAX_RATIO; _ValueSmoother.addValue(fSmooth); } // take the smoothed value. _FaceRatio= fSmooth; } } // *************************************************************************** // *************************************************************************** // *************************************************************************** // *************************************************************************** // *************************************************************************** CLoadBalancingTrav::CLoadBalancingTrav() { PolygonBalancingMode= CLoadBalancingGroup::PolygonBalancingOff; // Add the default group and make it default _GroupMap["Default"].Name= "Default"; _GroupMap["Default"]._DefaultGroup= true; // set the DefaultGroup ptr. _DefaultGroup= &_GroupMap["Default"]; // prepare some space _VisibleList.resize(1024); _CurrentNumVisibleModels= 0; } // *************************************************************************** void CLoadBalancingTrav::clearVisibleList() { _CurrentNumVisibleModels= 0; } // *************************************************************************** void CLoadBalancingTrav::traverse() { H_AUTO( NL3D_TravLoadBalancing ); CTravCameraScene::update(); // Reset each group. //================ ItGroupMap it= _GroupMap.begin(); for(;it!=_GroupMap.end();it++) { // reset _NbFacePass0. it->second._NbFacePass0= 0; } // Traverse the graph 2 times. // 1st pass, count NBFaces drawed. //================ _LoadPass= 0; // count _NbFacePass0. traverseVisibilityList(); // Reset _SumNbFacePass0 _SumNbFacePass0= 0; // For each group it= _GroupMap.begin(); for(;it!=_GroupMap.end();it++) { // compute ratio and smooth it->second.computeRatioAndSmooth(PolygonBalancingMode); // update _SumNbFacePass0 _SumNbFacePass0+= it->second.getNbFaceAsked(); } // 2nd pass, compute Faces that will be drawed. //================ _LoadPass= 1; traverseVisibilityList(); } // *************************************************************************** void CLoadBalancingTrav::traverseVisibilityList() { // Traverse all nodes of the visibility list. for(uint i=0; i<_CurrentNumVisibleModels; i++) { CTransform *model= _VisibleList[i]; model->traverseLoadBalancing(); } } // *************************************************************************** float CLoadBalancingTrav::getNbFaceAsked () const { return _SumNbFacePass0; } // *************************************************************************** CLoadBalancingGroup *CLoadBalancingTrav::getOrCreateGroup(const std::string &group) { // find ItGroupMap it; it= _GroupMap.find(group); // if not exist, create. if(it==_GroupMap.end()) { // create and set name. it= _GroupMap.insert(make_pair(group, CLoadBalancingGroup())).first; it->second.Name= group; } return &(it->second); } // *************************************************************************** void CLoadBalancingTrav::setGroupNbFaceWanted(const std::string &group, uint nFaces) { // get/create if needed, and assign. getOrCreateGroup(group)->setNbFaceWanted(nFaces); } // *************************************************************************** uint CLoadBalancingTrav::getGroupNbFaceWanted(const std::string &group) { // get/create if needed, and get. return getOrCreateGroup(group)->getNbFaceWanted(); } // *************************************************************************** float CLoadBalancingTrav::getGroupNbFaceAsked (const std::string &group) const { TGroupMap::const_iterator it; it= _GroupMap.find(group); if(it==_GroupMap.end()) return 0; else return it->second.getNbFaceAsked(); } // *************************************************************************** void CLoadBalancingTrav::reserveVisibleList(uint numModels) { // enlarge only. if(numModels>_VisibleList.size()) _VisibleList.resize(numModels); } } // NL3D