From 5cb36e38cffb88b80b61165c521b35e9009a9dd6 Mon Sep 17 00:00:00 2001 From: samuncle Date: Fri, 12 Feb 2021 04:16:38 +0100 Subject: [PATCH] Feature/enable lod autocompute (#3970) * Enable LoD autocompute * bring back the autocompute lod function * Add the area as main function to compute the lod level * Bring back the area based auto lod computation Co-authored-by: samuncle --- src/graphics/lod_node.cpp | 37 ++++++++++++++++++++++++++ src/graphics/lod_node.hpp | 8 ++++++ src/tracks/model_definition_loader.cpp | 3 +-- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/graphics/lod_node.cpp b/src/graphics/lod_node.cpp index 90041e4e4..f776a4e03 100644 --- a/src/graphics/lod_node.cpp +++ b/src/graphics/lod_node.cpp @@ -50,6 +50,7 @@ LODNode::LODNode(std::string group_name, scene::ISceneNode* parent, m_forced_lod = -1; m_last_tick = 0; + m_area = 0; } LODNode::~LODNode() @@ -249,8 +250,44 @@ void LODNode::OnRegisterSceneNode() scene::ISceneNode::OnRegisterSceneNode(); } + +void LODNode::autoComputeLevel(float scale) +{ + m_area *= scale; + + // Amount of details based on user's input + float agressivity = 1.0; + if(UserConfigParams::m_geometry_level == 0) agressivity = 1.25; + if(UserConfigParams::m_geometry_level == 1) agressivity = 1.0; + if(UserConfigParams::m_geometry_level == 2) agressivity = 0.75; + + // First we try to estimate how far away we need to draw + float max_draw = 0.0; + max_draw = sqrtf((0.5 * m_area + 10) * 200) - 10; + // If the draw distance is too big we artificially reduce it + if(max_draw > 250) + { + max_draw = 250 + (max_draw * 0.06); + } + + max_draw *= agressivity; + + int step = (int) (max_draw * max_draw) / m_detail.size(); + + // Then we recompute the level of detail culling distance + int biais = m_detail.size(); + for(int i = 0; i < m_detail.size(); i++) + { + m_detail[i] = ((step / biais) * (i + 1)); + biais--; + } +} + void LODNode::add(int level, scene::ISceneNode* node, bool reparent) { + Box = node->getBoundingBox(); + m_area = Box.getArea(); + // samuncle suggested to put a slight randomisation in LOD // I'm not convinced (Auria) but he's the artist pro, so I listen ;P // The last level should not be randomized because after that the object disappears, diff --git a/src/graphics/lod_node.hpp b/src/graphics/lod_node.hpp index a60a6ff50..3c15f9fc7 100644 --- a/src/graphics/lod_node.hpp +++ b/src/graphics/lod_node.hpp @@ -62,6 +62,9 @@ private: * m_forced_lod is >=0, only this level is be used. */ int m_forced_lod; + // Area of the bounding box (for autoLOD computation) + float m_area; + enum PreviousVisibility { FIRST_PASS, @@ -104,6 +107,11 @@ public: */ void add(int level, scene::ISceneNode* node, bool reparent); + /** + * This method can be used to automatically compute LoD level + */ + void autoComputeLevel(float scale); + void forceLevelOfDetail(int n); /** Get the highest level of detail node */ diff --git a/src/tracks/model_definition_loader.cpp b/src/tracks/model_definition_loader.cpp index f0c007293..09898a843 100644 --- a/src/tracks/model_definition_loader.cpp +++ b/src/tracks/model_definition_loader.cpp @@ -151,8 +151,7 @@ LODNode* ModelDefinitionLoader::instanciateAsLOD(const XMLNode* node, scene::ISc } vector3df scale = vector3df(1.f, 1.f, 1.f); node->get("scale", &scale); - // TODO samuncle: can be enabled after RC - //lod_node->autoComputeLevel(scale.getLength()); + lod_node->autoComputeLevel(scale.getLength()); #ifdef DEBUG std::string debug_name = groupname+" (LOD track-object)";