khanat-opennel-code/code/nel/src/3d/load_balancing_trav.cpp

269 lines
7.2 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// 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 <http://www.gnu.org/licenses/>.
#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