KRNode::m_childNodes replaced with a double-linked list to allow more efficient insertion.

This commit is contained in:
2022-10-04 22:40:09 -07:00
parent ab195e1323
commit ecfd410806
3 changed files with 110 additions and 72 deletions

View File

@@ -75,16 +75,17 @@ void KRLODSet::updateLODVisibility(const KRViewport& viewport)
*/ */
// Upgrade and downgrade LOD groups as needed // Upgrade and downgrade LOD groups as needed
for (std::list<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRLODGroup* lod_group = dynamic_cast<KRLODGroup*>(*itr); for (KRNode* childNode = m_firstChildNode; childNode != nullptr; childNode = childNode->m_nextNode) {
KRLODGroup* lod_group = dynamic_cast<KRLODGroup*>(childNode);
assert(lod_group != NULL); assert(lod_group != NULL);
LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible); LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible);
/* /*
// FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues: // FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues:
if(group_lod_visibility == LOD_VISIBILITY_VISIBLE) { if(group_lod_visibility == LOD_VISIBILITY_VISIBLE) {
new_active_lod_group = lod_group; new_active_lod_group = lod_group;
} }
*/ */
lod_group->setLODVisibility(group_lod_visibility); lod_group->setLODVisibility(group_lod_visibility);
} }
@@ -101,8 +102,8 @@ void KRLODSet::updateLODVisibility(const KRViewport& viewport)
if (streamer_ready) { if (streamer_ready) {
// Upgrade and downgrade LOD groups as needed // Upgrade and downgrade LOD groups as needed
for (std::list<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { for (KRNode* childNode = m_firstChildNode; childNode != nullptr; childNode = childNode->m_nextNode) {
KRLODGroup* lod_group = dynamic_cast<KRLODGroup*>(*itr); KRLODGroup* lod_group = dynamic_cast<KRLODGroup*>(childNode);
assert(lod_group != NULL); assert(lod_group != NULL);
LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible); LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible);
lod_group->setLODVisibility(group_lod_visibility); lod_group->setLODVisibility(group_lod_visibility);
@@ -131,8 +132,8 @@ kraken_stream_level KRLODSet::getStreamLevel(const KRViewport& viewport)
KRLODGroup* new_active_lod_group = NULL; KRLODGroup* new_active_lod_group = NULL;
// Upgrade and downgrade LOD groups as needed // Upgrade and downgrade LOD groups as needed
for (std::list<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { for (KRNode* childNode = m_firstChildNode; childNode != nullptr; childNode = childNode->m_nextNode) {
KRLODGroup* lod_group = dynamic_cast<KRLODGroup*>(*itr); KRLODGroup* lod_group = dynamic_cast<KRLODGroup*>(childNode);
assert(lod_group != NULL); assert(lod_group != NULL);
if (lod_group->calcLODVisibility(viewport) == LOD_VISIBILITY_VISIBLE) { if (lod_group->calcLODVisibility(viewport) == LOD_VISIBILITY_VISIBLE) {
new_active_lod_group = lod_group; new_active_lod_group = lod_group;

View File

@@ -123,7 +123,12 @@ KRNode::KRNode(KRScene& scene, std::string name) : KRContextObject(scene.getCont
m_initialPreRotation = Vector3::Zero(); m_initialPreRotation = Vector3::Zero();
m_initialPostRotation = Vector3::Zero(); m_initialPostRotation = Vector3::Zero();
m_parentNode = NULL; m_parentNode = nullptr;
m_previousNode = nullptr;
m_nextNode = nullptr;
m_firstChildNode = nullptr;
m_lastChildNode = nullptr;
m_pScene = &scene; m_pScene = &scene;
m_modelMatrixValid = false; m_modelMatrixValid = false;
m_inverseModelMatrixValid = false; m_inverseModelMatrixValid = false;
@@ -143,25 +148,44 @@ KRNode::KRNode(KRScene& scene, std::string name) : KRContextObject(scene.getCont
} }
} }
void KRNode::makeOrphan()
{
if (m_parentNode == nullptr) {
// Already an orphan
return;
}
if (m_nextNode != nullptr) {
m_nextNode->m_previousNode = m_previousNode;
}
if (m_previousNode != nullptr) {
m_previousNode->m_nextNode = m_nextNode;
}
if (m_previousNode == nullptr) {
m_parentNode->m_firstChildNode = m_nextNode;
}
if (m_nextNode == nullptr) {
m_parentNode->m_lastChildNode = m_previousNode;
}
m_parentNode->childRemoved(this);
m_parentNode = nullptr;
m_nextNode = nullptr;
m_previousNode = nullptr;
}
KRNode::~KRNode() KRNode::~KRNode()
{ {
while (m_firstChildNode != nullptr) {
delete m_firstChildNode;
while (m_childNodes.size() > 0) {
delete* m_childNodes.begin();
} }
makeOrphan();
for (std::set<KRBehavior*>::iterator itr = m_behaviors.begin(); itr != m_behaviors.end(); itr++) { for (std::set<KRBehavior*>::iterator itr = m_behaviors.begin(); itr != m_behaviors.end(); itr++) {
delete* itr; delete* itr;
} }
m_behaviors.clear(); m_behaviors.clear();
if (m_parentNode) {
m_parentNode->childDeleted(this);
}
getScene().notify_sceneGraphDelete(this); getScene().notify_sceneGraphDelete(this);
} }
void KRNode::setScaleCompensation(bool scale_compensation) void KRNode::setScaleCompensation(bool scale_compensation)
@@ -177,54 +201,71 @@ bool KRNode::getScaleCompensation()
return m_scale_compensation; return m_scale_compensation;
} }
void KRNode::childDeleted(KRNode* child_node) void KRNode::childRemoved(KRNode* child_node)
{ {
// TODO - We should give KRNode's linked list pointers directly and eliminate m_childNodes so that we don't need
// to perform slow std::find operations like this one.
// TODO - FIXME - This is a slow operation...
std::list<KRNode*>::iterator itr = std::find(m_childNodes.begin(), m_childNodes.end(), child_node);
if (itr != m_childNodes.end()) {
m_childNodes.erase(itr);
}
invalidateBounds(); invalidateBounds();
getScene().notify_sceneGraphModify(this); getScene().notify_sceneGraphModify(this);
} }
bool KRNode::isFirstSibling() const
{
return m_previousNode == nullptr;
}
bool KRNode::isLastSibling() const
{
return m_nextNode == nullptr;
}
void KRNode::appendChild(KRNode* child) void KRNode::appendChild(KRNode* child)
{ {
assert(child->m_parentNode == NULL); child->makeOrphan();
child->m_parentNode = this; child->m_parentNode = this;
m_childNodes.push_back(child); if (m_firstChildNode == nullptr) {
m_firstChildNode = child;
m_lastChildNode = child;
} else {
m_lastChildNode->m_nextNode = child;
child->m_previousNode = m_lastChildNode;
m_lastChildNode = child;
}
child->setLODVisibility(m_lod_visible); // Child node inherits LOD visibility status from parent child->setLODVisibility(m_lod_visible); // Child node inherits LOD visibility status from parent
} }
void KRNode::prependChild(KRNode* child) void KRNode::prependChild(KRNode* child)
{ {
assert(child->m_parentNode == NULL); child->makeOrphan();
child->m_parentNode = this; child->m_parentNode = this;
m_childNodes.push_front(child); if (m_firstChildNode == nullptr) {
m_firstChildNode = child;
m_lastChildNode = child;
} else {
m_firstChildNode->m_previousNode = child;
child->m_nextNode = m_firstChildNode;
m_firstChildNode = child;
}
child->setLODVisibility(m_lod_visible); // Child node inherits LOD visibility status from parent child->setLODVisibility(m_lod_visible); // Child node inherits LOD visibility status from parent
} }
void KRNode::insertBefore(KRNode* child) void KRNode::insertBefore(KRNode* child)
{ {
assert(m_parentNode != NULL); // There can only be one root node assert(m_parentNode != NULL); // There can only be one root node
assert(child->m_parentNode == NULL); child->makeOrphan();
child->m_parentNode = m_parentNode; child->m_parentNode = m_parentNode;
std::list<KRNode*>::iterator itr = std::find(m_parentNode->m_childNodes.begin(), m_parentNode->m_childNodes.end(), this); child->m_nextNode = this;
assert(itr != m_parentNode->m_childNodes.end()); child->m_previousNode = m_previousNode;
m_previousNode = child;
m_parentNode->m_childNodes.insert(itr, child);
child->setLODVisibility(m_lod_visible); // Child node inherits LOD visibility status from parent child->setLODVisibility(m_lod_visible); // Child node inherits LOD visibility status from parent
} }
void KRNode::insertAfter(KRNode* child) void KRNode::insertAfter(KRNode* child)
{ {
assert(m_parentNode != NULL); // There can only be one root node assert(m_parentNode != NULL); // There can only be one root node
assert(child->m_parentNode == NULL); child->makeOrphan();
child->m_parentNode = m_parentNode; child->m_parentNode = m_parentNode;
std::list<KRNode*>::iterator itr = std::find(m_parentNode->m_childNodes.begin(), m_parentNode->m_childNodes.end(), this); child->m_previousNode = this;
assert(itr != m_parentNode->m_childNodes.end()); child->m_nextNode = m_nextNode;
itr++; m_nextNode = child;
m_parentNode->m_childNodes.insert(itr, child);
child->setLODVisibility(m_lod_visible); // Child node inherits LOD visibility status from parent child->setLODVisibility(m_lod_visible); // Child node inherits LOD visibility status from parent
} }
@@ -244,8 +285,7 @@ tinyxml2::XMLElement* KRNode::saveXML(tinyxml2::XMLNode* parent)
kraken::setXMLAttribute("pre_rotate", e, (m_preRotation * (180.0f / (float)M_PI)), Vector3::Zero()); kraken::setXMLAttribute("pre_rotate", e, (m_preRotation * (180.0f / (float)M_PI)), Vector3::Zero());
kraken::setXMLAttribute("post_rotate", e, (m_postRotation * (180.0f / (float)M_PI)), Vector3::Zero()); kraken::setXMLAttribute("post_rotate", e, (m_postRotation * (180.0f / (float)M_PI)), Vector3::Zero());
for (std::list<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) {
KRNode* child = (*itr);
child->saveXML(n); child->saveXML(n);
} }
return e; return e;
@@ -642,11 +682,6 @@ void KRNode::render(const RenderInfo& ri)
m_lastRenderFrame = getContext().getCurrentFrame(); m_lastRenderFrame = getContext().getCurrentFrame();
} }
const std::list<KRNode*>& KRNode::getChildren()
{
return m_childNodes;
}
KRNode* KRNode::getParent() KRNode* KRNode::getParent()
{ {
return m_parentNode; return m_parentNode;
@@ -667,12 +702,9 @@ AABB KRNode::getBounds()
if (!m_boundsValid) { if (!m_boundsValid) {
AABB bounds = AABB::Zero(); AABB bounds = AABB::Zero();
bool first_child = true; for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) {
for (std::list<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRNode* child = (*itr);
if (child->getBounds() != AABB::Zero()) { if (child->getBounds() != AABB::Zero()) {
if (first_child) { if (child->isFirstSibling()) {
first_child = false;
bounds = child->getBounds(); bounds = child->getBounds();
} else { } else {
bounds.encapsulate(child->getBounds()); bounds.encapsulate(child->getBounds());
@@ -691,8 +723,7 @@ void KRNode::invalidateModelMatrix()
m_modelMatrixValid = false; m_modelMatrixValid = false;
m_activePoseMatrixValid = false; m_activePoseMatrixValid = false;
m_inverseModelMatrixValid = false; m_inverseModelMatrixValid = false;
for (std::list<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) {
KRNode* child = (*itr);
child->invalidateModelMatrix(); child->invalidateModelMatrix();
} }
@@ -704,8 +735,7 @@ void KRNode::invalidateBindPoseMatrix()
{ {
m_bindPoseMatrixValid = false; m_bindPoseMatrixValid = false;
m_inverseBindPoseMatrixValid = false; m_inverseBindPoseMatrixValid = false;
for (std::list<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) {
KRNode* child = (*itr);
child->invalidateBindPoseMatrix(); child->invalidateBindPoseMatrix();
} }
} }
@@ -1083,8 +1113,8 @@ void KRNode::addToOctreeNode(KROctreeNode* octree_node)
void KRNode::updateLODVisibility(const KRViewport& viewport) void KRNode::updateLODVisibility(const KRViewport& viewport)
{ {
if (m_lod_visible >= LOD_VISIBILITY_PRESTREAM) { if (m_lod_visible >= LOD_VISIBILITY_PRESTREAM) {
for (std::list<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) {
(*itr)->updateLODVisibility(viewport); child->updateLODVisibility(viewport);
} }
} }
} }
@@ -1100,8 +1130,8 @@ void KRNode::setLODVisibility(KRNode::LodVisibility lod_visibility)
m_lod_visible = lod_visibility; m_lod_visible = lod_visibility;
for (std::list<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) {
(*itr)->setLODVisibility(lod_visibility); child->setLODVisibility(lod_visibility);
} }
} }
} }
@@ -1137,8 +1167,8 @@ kraken_stream_level KRNode::getStreamLevel(const KRViewport& viewport)
{ {
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ; kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
for (std::list<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) {
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel(viewport)); stream_level = KRMIN(stream_level, child->getStreamLevel(viewport));
} }
return stream_level; return stream_level;

View File

@@ -126,7 +126,6 @@ public:
void prependChild(KRNode* child); void prependChild(KRNode* child);
void insertBefore(KRNode* child); void insertBefore(KRNode* child);
void insertAfter(KRNode* child); void insertAfter(KRNode* child);
const std::list<KRNode*>& getChildren();
KRNode* getParent(); KRNode* getParent();
void setLocalTranslation(const Vector3& v, bool set_original = false); void setLocalTranslation(const Vector3& v, bool set_original = false);
@@ -241,6 +240,15 @@ public:
virtual void setLODVisibility(LodVisibility lod_visibility); virtual void setLODVisibility(LodVisibility lod_visibility);
public:
bool isFirstSibling() const;
bool isLastSibling() const;
KRNode* m_parentNode;
KRNode* m_previousNode;
KRNode* m_nextNode;
KRNode* m_firstChildNode;
KRNode* m_lastChildNode;
protected: protected:
Vector3 m_localTranslation; Vector3 m_localTranslation;
Vector3 m_localScale; Vector3 m_localScale;
@@ -266,12 +274,10 @@ protected:
LodVisibility m_lod_visible; LodVisibility m_lod_visible;
KRNode* m_parentNode;
std::list<KRNode*> m_childNodes;
bool m_animation_mask[KRENGINE_NODE_ATTRIBUTE_COUNT]; bool m_animation_mask[KRENGINE_NODE_ATTRIBUTE_COUNT];
private: private:
void makeOrphan();
long m_lastRenderFrame; long m_lastRenderFrame;
void invalidateModelMatrix(); void invalidateModelMatrix();
void invalidateBindPoseMatrix(); void invalidateBindPoseMatrix();
@@ -315,7 +321,7 @@ public:
} }
void removeFromOctreeNodes(); void removeFromOctreeNodes();
void addToOctreeNode(KROctreeNode* octree_node); void addToOctreeNode(KROctreeNode* octree_node);
void childDeleted(KRNode* child_node); void childRemoved(KRNode* child_node);
template <class T> T* find() template <class T> T* find()
{ {
@@ -324,8 +330,8 @@ public:
return match; return match;
} }
for (std::list<KRNode*>::const_iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) {
match = (*itr)->find<T>(); match = child->find<T>();
if (match) { if (match) {
return match; return match;
} }
@@ -336,6 +342,7 @@ public:
template <class T> T* find(const std::string& name) template <class T> T* find(const std::string& name)
{ {
// TODO - KRScene should maintain a global node-name map for rapid searching
T* match = dynamic_cast<T*>(this); T* match = dynamic_cast<T*>(this);
if (match) { if (match) {
if (name.compare(match->getName()) == 0) { if (name.compare(match->getName()) == 0) {
@@ -343,8 +350,8 @@ public:
} }
} }
for (std::list<KRNode*>::const_iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) {
match = (*itr)->find<T>(name); match = child->find<T>(name);
if (match) { if (match) {
return match; return match;
} }