Remove hacks for lod completely which breaks legacy pipeline

We will do the proper lod optimization after this release
This commit is contained in:
Benau 2019-04-02 08:50:07 +08:00
parent 625a192cda
commit d990bcb2a1
3 changed files with 89 additions and 104 deletions

View File

@ -146,10 +146,10 @@ void DrawCalls::parseSceneManager(core::list<scene::ISceneNode*> &List,
{
node->updateVisibility();
}
(*I)->updateAbsolutePosition();
if (!(*I)->isVisible())
continue;
(*I)->updateAbsolutePosition();
if (STKParticle *node = dynamic_cast<STKParticle*>(*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();
@ -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();

View File

@ -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; n<m_detail.size(); n++)
{
if (dist < m_detail[n])
{
return n;
}
}
return -1;
@ -173,22 +144,24 @@ void LODNode::OnAnimate(u32 timeMs)
}
}
void LODNode::updateVisibility()
void LODNode::updateVisibility(bool* shown)
{
if (!isVisible()) return;
if (m_nodes.size() == 0) return;
m_current_level = getLevel();
for (unsigned int i = 0; i < m_nodes.size(); i++)
unsigned int level = getLevel();
for (size_t i = 0; i < m_nodes.size(); i++)
{
m_nodes[i]->setVisible(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())
@ -197,6 +170,72 @@ void LODNode::OnRegisterSceneNode()
}
#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();
}

View File

@ -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