KRNode::m_childNodes replaced with a double-linked list to allow more efficient insertion.
This commit is contained in:
@@ -75,8 +75,9 @@ void KRLODSet::updateLODVisibility(const KRViewport& viewport)
|
||||
*/
|
||||
|
||||
// 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);
|
||||
LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible);
|
||||
/*
|
||||
@@ -101,8 +102,8 @@ void KRLODSet::updateLODVisibility(const KRViewport& viewport)
|
||||
|
||||
if (streamer_ready) {
|
||||
// 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);
|
||||
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<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);
|
||||
if (lod_group->calcLODVisibility(viewport) == LOD_VISIBILITY_VISIBLE) {
|
||||
new_active_lod_group = lod_group;
|
||||
|
||||
@@ -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<KRBehavior*>::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<KRNode*>::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<KRNode*>::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<KRNode*>::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<KRNode*>::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*>& 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<KRNode*>::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<KRNode*>::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<KRNode*>::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<KRNode*>::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<KRNode*>::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<KRNode*>::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;
|
||||
|
||||
@@ -126,7 +126,6 @@ public:
|
||||
void prependChild(KRNode* child);
|
||||
void insertBefore(KRNode* child);
|
||||
void insertAfter(KRNode* child);
|
||||
const std::list<KRNode*>& 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<KRNode*> 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 <class T> T* find()
|
||||
{
|
||||
@@ -324,8 +330,8 @@ public:
|
||||
return match;
|
||||
}
|
||||
|
||||
for (std::list<KRNode*>::const_iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
||||
match = (*itr)->find<T>();
|
||||
for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) {
|
||||
match = child->find<T>();
|
||||
if (match) {
|
||||
return match;
|
||||
}
|
||||
@@ -336,6 +342,7 @@ public:
|
||||
|
||||
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);
|
||||
if (match) {
|
||||
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) {
|
||||
match = (*itr)->find<T>(name);
|
||||
for (KRNode* child = m_firstChildNode; child != nullptr; child = child->m_nextNode) {
|
||||
match = child->find<T>(name);
|
||||
if (match) {
|
||||
return match;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user