From d990bcb2a13808853c174a5d45ac1819f4ae1509 Mon Sep 17 00:00:00 2001 From: Benau Date: Tue, 2 Apr 2019 08:50:07 +0800 Subject: [PATCH] Remove hacks for lod completely which breaks legacy pipeline We will do the proper lod optimization after this release --- src/graphics/draw_calls.cpp | 13 +-- src/graphics/lod_node.cpp | 154 ++++++++++++++++++------------------ src/graphics/lod_node.hpp | 26 ++---- 3 files changed, 89 insertions(+), 104 deletions(-) diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index a686f6220..5e8b3663d 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -146,10 +146,10 @@ void DrawCalls::parseSceneManager(core::list &List, { node->updateVisibility(); } + (*I)->updateAbsolutePosition(); if (!(*I)->isVisible()) continue; - (*I)->updateAbsolutePosition(); if (STKParticle *node = dynamic_cast(*I)) { if (!isCulledPrecise(cam, *I, irr_driver->getBoundingBoxesViz())) @@ -202,17 +202,11 @@ void DrawCalls::prepareDrawCalls(scene::ICameraSceneNode *camnode) { CPUParticleManager::getInstance()->reset(); TextBillboardDrawer::reset(); - PROFILER_PUSH_CPU_MARKER("- prepare draw call", 0xFF, 0xFF, 0x0); + PROFILER_PUSH_CPU_MARKER("- culling", 0xFF, 0xFF, 0x0); SP::prepareDrawCalls(); - PROFILER_POP_CPU_MARKER(); - - PROFILER_PUSH_CPU_MARKER("-- parse scene manager", 0x00, 0xFF, 0x0); parseSceneManager( irr_driver->getSceneManager()->getRootSceneNode()->getChildren(), camnode); - PROFILER_POP_CPU_MARKER(); - - PROFILER_PUSH_CPU_MARKER("-- handle dynamic draw", 0x00, 0xFF, 0x0); SP::handleDynamicDrawCall(); SP::updateModelMatrix(); PROFILER_POP_CPU_MARKER(); @@ -220,7 +214,7 @@ void DrawCalls::prepareDrawCalls(scene::ICameraSceneNode *camnode) PROFILER_PUSH_CPU_MARKER("- cpu particle generation", 0x2F, 0x1F, 0x11); CPUParticleManager::getInstance()->generateAll(); PROFILER_POP_CPU_MARKER(); - + // Add a 1 s timeout if (m_sync != 0) { @@ -239,7 +233,6 @@ void DrawCalls::prepareDrawCalls(scene::ICameraSceneNode *camnode) PROFILER_POP_CPU_MARKER(); } - PROFILER_PUSH_CPU_MARKER("- particle and text billboard upload", 0x3F, 0x03, 0x61); CPUParticleManager::getInstance()->uploadAll(); diff --git a/src/graphics/lod_node.cpp b/src/graphics/lod_node.cpp index 917e1d5ca..90041e4e4 100644 --- a/src/graphics/lod_node.cpp +++ b/src/graphics/lod_node.cpp @@ -40,6 +40,8 @@ LODNode::LODNode(std::string group_name, scene::ISceneNode* parent, m_group_name = group_name; + m_previous_visibility = FIRST_PASS; + // At this stage refcount is two: one because of the object being // created, and once because it is a child of the parent. Drop once, // so that only the reference from the parent is active, causing this @@ -48,17 +50,6 @@ LODNode::LODNode(std::string group_name, scene::ISceneNode* parent, m_forced_lod = -1; m_last_tick = 0; - m_area = 0; - - m_previous_level = 0; - m_current_level = 0; - - m_timer = 0; - - is_in_transition = false; - - //m_node_to_fade_out = 0; - //m_node_to_fade_in = 0; } LODNode::~LODNode() @@ -87,33 +78,13 @@ int LODNode::getLevel() return (int)m_detail.size() - 1; const Vec3 &pos = camera->getCameraSceneNode()->getAbsolutePosition(); - int dist = + const int dist = (int)((m_nodes[0]->getAbsolutePosition()).getDistanceFromSQ(pos.toIrrVector() )); - - // Based on the complexity of the track we are more or less aggressive with culling - int complexity = irr_driver->getSceneComplexity(); - // The track has high complexity so we decrease the draw distance by 10% - if (complexity > 3000 ) - { - dist += (dist/10); - } - // The track has medium complexity, we can increase slightly the draw distance - else if(complexity > 1500 ) - { - dist -= (dist/100); - } - // The track has low complexity we can increase a lot the draw distance - else - { - dist -= (dist/10); - } for (unsigned int n=0; nsetVisible(i == m_current_level); + m_nodes[i]->setVisible(i == level); + if (i == level && shown != NULL) + *shown = (i > 0); } - } void LODNode::OnRegisterSceneNode() { + bool shown = false; + updateVisibility(&shown); #ifndef SERVER_ONLY if (CVS->isGLSL()) @@ -196,7 +169,73 @@ void LODNode::OnRegisterSceneNode() return; } #endif - + + const u32 now = irr_driver->getDevice()->getTimer()->getTime(); + + // support an optional, mostly hard-coded fade-in/out effect for objects with a single level + if (m_nodes.size() == 1 && (m_nodes[0]->getType() == scene::ESNT_MESH || + m_nodes[0]->getType() == scene::ESNT_ANIMATED_MESH) && + now > m_last_tick) + { + if (m_previous_visibility == WAS_HIDDEN && shown) + { + scene::IMesh* mesh; + + if (m_nodes[0]->getType() == scene::ESNT_MESH) + { + scene::IMeshSceneNode* node = (scene::IMeshSceneNode*)(m_nodes[0]); + mesh = node->getMesh(); + } + else + { + assert(m_nodes[0]->getType() == scene::ESNT_ANIMATED_MESH); + scene::IAnimatedMeshSceneNode* node = + (scene::IAnimatedMeshSceneNode*)(m_nodes[0]); + assert(node != NULL); + mesh = node->getMesh(); + } + } + else if (m_previous_visibility == WAS_SHOWN && !shown) + { + scene::IMesh* mesh; + + if (m_nodes[0]->getType() == scene::ESNT_MESH) + { + scene::IMeshSceneNode* node = (scene::IMeshSceneNode*)(m_nodes[0]); + mesh = node->getMesh(); + } + else + { + assert(m_nodes[0]->getType() == scene::ESNT_ANIMATED_MESH); + scene::IAnimatedMeshSceneNode* node = + (scene::IAnimatedMeshSceneNode*)(m_nodes[0]); + assert(node != NULL); + mesh = node->getMesh(); + } + + } + else if (m_previous_visibility == FIRST_PASS && !shown) + { + scene::IMesh* mesh; + + if (m_nodes[0]->getType() == scene::ESNT_MESH) + { + scene::IMeshSceneNode* node = (scene::IMeshSceneNode*)(m_nodes[0]); + mesh = node->getMesh(); + } + else + { + assert(m_nodes[0]->getType() == scene::ESNT_ANIMATED_MESH); + scene::IAnimatedMeshSceneNode* node = + (scene::IAnimatedMeshSceneNode*)(m_nodes[0]); + assert(node != NULL); + mesh = node->getMesh(); + } + } + } + + m_previous_visibility = (shown ? WAS_SHOWN : WAS_HIDDEN); + m_last_tick = now; #ifndef SERVER_ONLY if (!CVS->isGLSL()) { @@ -210,43 +249,8 @@ 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 = 235 + (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(unsigned 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, @@ -262,7 +266,6 @@ void LODNode::add(int level, scene::ISceneNode* node, bool reparent) node->grab(); node->remove(); node->setPosition(core::vector3df(0,0,0)); - node->setVisible(false); m_detail.push_back(level*level); m_nodes.push_back(node); m_nodes_set.insert(node); @@ -277,4 +280,3 @@ void LODNode::add(int level, scene::ISceneNode* node, bool reparent) node->updateAbsolutePosition(); } - diff --git a/src/graphics/lod_node.hpp b/src/graphics/lod_node.hpp index bb95cc1df..a60a6ff50 100644 --- a/src/graphics/lod_node.hpp +++ b/src/graphics/lod_node.hpp @@ -62,18 +62,14 @@ 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; - - // Previous level for the smooth transitions - unsigned int m_previous_level; - unsigned int m_current_level; - - int m_timer; - - bool is_in_transition; - + enum PreviousVisibility + { + FIRST_PASS, + WAS_SHOWN, + WAS_HIDDEN + }; + PreviousVisibility m_previous_visibility; u32 m_last_tick; @@ -87,7 +83,7 @@ public: int getLevel(); - void updateVisibility(); + void updateVisibility(bool* shown = NULL); /* //! Returns a reference to the current relative transformation matrix. @@ -108,11 +104,6 @@ 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 */ @@ -138,4 +129,3 @@ public: }; #endif -