From ecfd4108064b9300c0c117e492e081664a93abad Mon Sep 17 00:00:00 2001 From: kearwood Date: Tue, 4 Oct 2022 22:40:09 -0700 Subject: [PATCH] KRNode::m_childNodes replaced with a double-linked list to allow more efficient insertion. --- kraken/KRLODSet.cpp | 21 +++---- kraken/KRNode.cpp | 136 +++++++++++++++++++++++++++----------------- kraken/KRNode.h | 25 +++++--- 3 files changed, 110 insertions(+), 72 deletions(-) diff --git a/kraken/KRLODSet.cpp b/kraken/KRLODSet.cpp index c2dd333..5fcce9f 100755 --- a/kraken/KRLODSet.cpp +++ b/kraken/KRLODSet.cpp @@ -75,16 +75,17 @@ void KRLODSet::updateLODVisibility(const KRViewport& viewport) */ // Upgrade and downgrade LOD groups as needed - for (std::list::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - KRLODGroup* lod_group = dynamic_cast(*itr); + + for (KRNode* childNode = m_firstChildNode; childNode != nullptr; childNode = childNode->m_nextNode) { + KRLODGroup* lod_group = dynamic_cast(childNode); assert(lod_group != NULL); LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible); /* // FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues: - if(group_lod_visibility == LOD_VISIBILITY_VISIBLE) { - new_active_lod_group = lod_group; - } - */ + if(group_lod_visibility == LOD_VISIBILITY_VISIBLE) { + new_active_lod_group = lod_group; + } + */ lod_group->setLODVisibility(group_lod_visibility); } @@ -101,8 +102,8 @@ void KRLODSet::updateLODVisibility(const KRViewport& viewport) if (streamer_ready) { // Upgrade and downgrade LOD groups as needed - for (std::list::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - KRLODGroup* lod_group = dynamic_cast(*itr); + for (KRNode* childNode = m_firstChildNode; childNode != nullptr; childNode = childNode->m_nextNode) { + KRLODGroup* lod_group = dynamic_cast(childNode); assert(lod_group != NULL); LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible); lod_group->setLODVisibility(group_lod_visibility); @@ -131,8 +132,8 @@ kraken_stream_level KRLODSet::getStreamLevel(const KRViewport& viewport) KRLODGroup* new_active_lod_group = NULL; // Upgrade and downgrade LOD groups as needed - for (std::list::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - KRLODGroup* lod_group = dynamic_cast(*itr); + for (KRNode* childNode = m_firstChildNode; childNode != nullptr; childNode = childNode->m_nextNode) { + KRLODGroup* lod_group = dynamic_cast(childNode); assert(lod_group != NULL); if (lod_group->calcLODVisibility(viewport) == LOD_VISIBILITY_VISIBLE) { new_active_lod_group = lod_group; diff --git a/kraken/KRNode.cpp b/kraken/KRNode.cpp index 538c87d..ca4ebcf 100755 --- a/kraken/KRNode.cpp +++ b/kraken/KRNode.cpp @@ -123,7 +123,12 @@ KRNode::KRNode(KRScene& scene, std::string name) : KRContextObject(scene.getCont m_initialPreRotation = 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_modelMatrixValid = 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() { - - - while (m_childNodes.size() > 0) { - delete* m_childNodes.begin(); + while (m_firstChildNode != nullptr) { + delete m_firstChildNode; } + makeOrphan(); + for (std::set::iterator itr = m_behaviors.begin(); itr != m_behaviors.end(); itr++) { delete* itr; } m_behaviors.clear(); - if (m_parentNode) { - m_parentNode->childDeleted(this); - } - getScene().notify_sceneGraphDelete(this); - } void KRNode::setScaleCompensation(bool scale_compensation) @@ -177,54 +201,71 @@ bool KRNode::getScaleCompensation() 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::iterator itr = std::find(m_childNodes.begin(), m_childNodes.end(), child_node); - if (itr != m_childNodes.end()) { - m_childNodes.erase(itr); - } invalidateBounds(); 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) { - assert(child->m_parentNode == NULL); + child->makeOrphan(); 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 } void KRNode::prependChild(KRNode* child) { - assert(child->m_parentNode == NULL); + child->makeOrphan(); 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 } void KRNode::insertBefore(KRNode* child) { assert(m_parentNode != NULL); // There can only be one root node - assert(child->m_parentNode == NULL); + child->makeOrphan(); child->m_parentNode = m_parentNode; - std::list::iterator itr = std::find(m_parentNode->m_childNodes.begin(), m_parentNode->m_childNodes.end(), this); - assert(itr != m_parentNode->m_childNodes.end()); + child->m_nextNode = this; + 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 } void KRNode::insertAfter(KRNode* child) { assert(m_parentNode != NULL); // There can only be one root node - assert(child->m_parentNode == NULL); + child->makeOrphan(); + child->m_parentNode = m_parentNode; - std::list::iterator itr = std::find(m_parentNode->m_childNodes.begin(), m_parentNode->m_childNodes.end(), this); - assert(itr != m_parentNode->m_childNodes.end()); - itr++; - m_parentNode->m_childNodes.insert(itr, child); + child->m_previousNode = this; + child->m_nextNode = m_nextNode; + m_nextNode = child; + 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("post_rotate", e, (m_postRotation * (180.0f / (float)M_PI)), Vector3::Zero()); - for (std::list::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - KRNode* child = (*itr); + for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) { child->saveXML(n); } return e; @@ -642,11 +682,6 @@ void KRNode::render(const RenderInfo& ri) m_lastRenderFrame = getContext().getCurrentFrame(); } -const std::list& KRNode::getChildren() -{ - return m_childNodes; -} - KRNode* KRNode::getParent() { return m_parentNode; @@ -667,12 +702,9 @@ AABB KRNode::getBounds() if (!m_boundsValid) { AABB bounds = AABB::Zero(); - bool first_child = true; - for (std::list::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - KRNode* child = (*itr); + for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) { if (child->getBounds() != AABB::Zero()) { - if (first_child) { - first_child = false; + if (child->isFirstSibling()) { bounds = child->getBounds(); } else { bounds.encapsulate(child->getBounds()); @@ -691,8 +723,7 @@ void KRNode::invalidateModelMatrix() m_modelMatrixValid = false; m_activePoseMatrixValid = false; m_inverseModelMatrixValid = false; - for (std::list::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - KRNode* child = (*itr); + for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) { child->invalidateModelMatrix(); } @@ -704,8 +735,7 @@ void KRNode::invalidateBindPoseMatrix() { m_bindPoseMatrixValid = false; m_inverseBindPoseMatrixValid = false; - for (std::list::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - KRNode* child = (*itr); + for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) { child->invalidateBindPoseMatrix(); } } @@ -1083,8 +1113,8 @@ void KRNode::addToOctreeNode(KROctreeNode* octree_node) void KRNode::updateLODVisibility(const KRViewport& viewport) { if (m_lod_visible >= LOD_VISIBILITY_PRESTREAM) { - for (std::list::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - (*itr)->updateLODVisibility(viewport); + for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) { + child->updateLODVisibility(viewport); } } } @@ -1100,8 +1130,8 @@ void KRNode::setLODVisibility(KRNode::LodVisibility lod_visibility) m_lod_visible = lod_visibility; - for (std::list::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - (*itr)->setLODVisibility(lod_visibility); + for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) { + 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; - for (std::list::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - stream_level = KRMIN(stream_level, (*itr)->getStreamLevel(viewport)); + for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) { + stream_level = KRMIN(stream_level, child->getStreamLevel(viewport)); } return stream_level; diff --git a/kraken/KRNode.h b/kraken/KRNode.h index 819b176..04e5957 100755 --- a/kraken/KRNode.h +++ b/kraken/KRNode.h @@ -126,7 +126,6 @@ public: void prependChild(KRNode* child); void insertBefore(KRNode* child); void insertAfter(KRNode* child); - const std::list& getChildren(); KRNode* getParent(); void setLocalTranslation(const Vector3& v, bool set_original = false); @@ -241,6 +240,15 @@ public: 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: Vector3 m_localTranslation; Vector3 m_localScale; @@ -266,12 +274,10 @@ protected: LodVisibility m_lod_visible; - KRNode* m_parentNode; - std::list m_childNodes; - bool m_animation_mask[KRENGINE_NODE_ATTRIBUTE_COUNT]; private: + void makeOrphan(); long m_lastRenderFrame; void invalidateModelMatrix(); void invalidateBindPoseMatrix(); @@ -315,7 +321,7 @@ public: } void removeFromOctreeNodes(); void addToOctreeNode(KROctreeNode* octree_node); - void childDeleted(KRNode* child_node); + void childRemoved(KRNode* child_node); template T* find() { @@ -324,8 +330,8 @@ public: return match; } - for (std::list::const_iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - match = (*itr)->find(); + for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) { + match = child->find(); if (match) { return match; } @@ -336,6 +342,7 @@ public: template T* find(const std::string& name) { + // TODO - KRScene should maintain a global node-name map for rapid searching T* match = dynamic_cast(this); if (match) { if (name.compare(match->getName()) == 0) { @@ -343,8 +350,8 @@ public: } } - for (std::list::const_iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - match = (*itr)->find(name); + for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) { + match = child->find(name); if (match) { return match; }