Various adjustments to auto-LOD

- Increase the effect preventing LoD objects from popping at very short distances
- Add comments to all the steps and other clarifications
- Update the multiplier values to be approximately equally spaced geometrically
This commit is contained in:
Alayan 2024-05-06 22:51:25 +02:00
parent e47958f2d3
commit df803c18b8
No known key found for this signature in database

View File

@ -84,7 +84,7 @@ int LODNode::getLevel()
return (int)m_detail.size() - 1;
const Vec3 &pos = camera->getCameraSceneNode()->getAbsolutePosition();
const int dist =
const int squared_dist =
(int)((m_nodes[0]->getAbsolutePosition()).getDistanceFromSQ(pos.toIrrVector() ));
if (!m_lod_distances_updated)
@ -98,7 +98,7 @@ int LODNode::getLevel()
for (unsigned int n=0; n<m_detail.size(); n++)
{
if (dist < m_detail[n])
if (squared_dist < m_detail[n])
{
m_current_level = n;
return n;
@ -198,15 +198,16 @@ void LODNode::autoComputeLevel(float scale)
{
m_area *= scale;
// First we try to estimate how far away we need to draw
// Step 1 - We try to estimate how far away we need to draw
// This first formula is equivalent to the one used up to STK 1.4
float max_draw = 10*(sqrtf(m_area + 20) - 1);
// At really short distances, popping is more annoying even if
// the object is small, so we limit how small the distance can be
if (max_draw < 80)
max_draw = 30 + (max_draw * 0.625);
// If the draw distance is too big we artificially reduce it
// Step 2 - At really short distances, popping is more annoying even if
// the object is small, so we limit how small the distance can be
if (max_draw < 100)
max_draw = 40 + (max_draw * 0.6);
// Step 3 - If the draw distance is too big we artificially reduce it
// The formulas are still experimental and improvable.
if(max_draw > 250)
max_draw = 230 + (max_draw * 0.08);
@ -214,25 +215,29 @@ void LODNode::autoComputeLevel(float scale)
if (max_draw > 500)
max_draw = 200 + (max_draw * 0.6);
// As it is faster to compute the squared distance than distance, at runtime
// Step 4 - Distance multiplier based on the user's input
float aggressivity = 1.0;
if( UserConfigParams::m_geometry_level == 2) aggressivity = 0.8; // 2 in the params is the lowest setting
else if(UserConfigParams::m_geometry_level == 1) aggressivity = 1.1;
else if(UserConfigParams::m_geometry_level == 0) aggressivity = 1.5;
else if(UserConfigParams::m_geometry_level == 3) aggressivity = 2.0;
else if(UserConfigParams::m_geometry_level == 4) aggressivity = 2.7;
else if(UserConfigParams::m_geometry_level == 5) aggressivity = 3.6;
max_draw *= aggressivity;
// Step 5 - As it is faster to compute the squared distance than distance, at runtime
// we compare the distance saved in the LoD node with the square of the distance
// between the camera and the object. Therefore, we apply squaring here.
max_draw *= max_draw;
// Amount of details based on the user's input
float aggressivity = 1.0;
if( UserConfigParams::m_geometry_level == 0) aggressivity = 1.5;
else if(UserConfigParams::m_geometry_level == 1) aggressivity = 0.65;
else if(UserConfigParams::m_geometry_level == 2) aggressivity = 0.65; // Also removes many objects
else if(UserConfigParams::m_geometry_level == 3) aggressivity = 4.5;
else if(UserConfigParams::m_geometry_level == 4) aggressivity = 5.75;
else if(UserConfigParams::m_geometry_level == 5) aggressivity = 15.0;
max_draw *= aggressivity;
int step = (int) (max_draw) / m_detail.size();
// Then we recompute the level of detail culling distance
// Step 6 - Then we recompute the level of detail culling distance
// If there are N levels of detail, the transition distance
// between each level is currently each 1/Nth of the max
// display distance
// TODO - investigate a better division scheme
int biais = m_detail.size();
for(unsigned i = 0; i < m_detail.size(); i++)
{