270 lines
7.2 KiB
C++
270 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
|