Fixed bug that caused the application to crash when deleting or moving nodes in the Octree

Changes to the Octruee due to adding and updating object positions is now delayed until after the end of the frame
This commit is contained in:
2013-02-21 16:22:56 -08:00
parent 69506798c2
commit cd3627c3d3
8 changed files with 94 additions and 42 deletions

View File

@@ -33,7 +33,8 @@
#define KRHITINFO_H
#include "KRVector3.h"
#include "KRNode.h"
class KRNode;
class KRHitInfo {
public:

View File

@@ -409,3 +409,26 @@ void KRNode::SetAttribute(node_attribute_type attrib, float v)
}
}
void KRNode::removeFromOctreeNodes()
{
for(std::set<KROctreeNode *>::iterator itr=m_octree_nodes.begin(); itr != m_octree_nodes.end(); itr++) {
KROctreeNode *octree_node = *itr;
octree_node->remove(this);
// FINDME, TODO - This should be moved to the KROctree class
while(octree_node) {
octree_node->trim();
if(octree_node->isEmpty()) {
octree_node = octree_node->getParent();
} else {
octree_node = NULL;
}
}
}
m_octree_nodes.clear();
}
void KRNode::addToOctreeNode(KROctreeNode *octree_node)
{
m_octree_nodes.insert(octree_node);
}

View File

@@ -13,6 +13,7 @@
#include "KRVector3.h"
#include "KRViewport.h"
#include "tinyxml2.h"
#include "KROctreeNode.h"
class KRCamera;
class KRShaderManager;
@@ -131,8 +132,13 @@ private:
KRScene *m_pScene;
std::set<KROctreeNode *> m_octree_nodes;
public:
void removeFromOctreeNodes();
void addToOctreeNode(KROctreeNode *octree_node);
template <class T> T *find()
{
T *match = dynamic_cast<T *>(this);

View File

@@ -32,8 +32,7 @@ void KROctree::add(KRNode *pNode)
} else {
if(m_pRootNode == NULL) {
// First item inserted, create a node large enough to fit it
m_pRootNode = new KROctreeNode(nodeBounds);
//m_pRootNode = new KROctreeNode(KRAABB(nodeBounds.min - nodeBounds.size() * 0.25f, nodeBounds.max + nodeBounds.size() * 0.25f));
m_pRootNode = new KROctreeNode(NULL, nodeBounds);
m_pRootNode->add(pNode);
} else {
// Keep encapsulating the root node until the new root contains the inserted node
@@ -42,9 +41,9 @@ void KROctree::add(KRNode *pNode)
KRAABB rootBounds = m_pRootNode->getBounds();
KRVector3 rootSize = rootBounds.size();
if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) {
m_pRootNode = new KROctreeNode(KRAABB(rootBounds.min - rootSize, rootBounds.max), 7, m_pRootNode);
m_pRootNode = new KROctreeNode(NULL, KRAABB(rootBounds.min - rootSize, rootBounds.max), 7, m_pRootNode);
} else if(nodeBounds.max.x > rootBounds.max.x || nodeBounds.max.y > rootBounds.max.y || nodeBounds.max.z > rootBounds.max.z) {
m_pRootNode = new KROctreeNode(KRAABB(rootBounds.min, rootBounds.max + rootSize), 0, m_pRootNode);
m_pRootNode = new KROctreeNode(NULL, KRAABB(rootBounds.min, rootBounds.max + rootSize), 0, m_pRootNode);
} else {
bInsideRoot = true;
}
@@ -58,7 +57,7 @@ void KROctree::remove(KRNode *pNode)
{
if(!m_outerSceneNodes.erase(pNode)) {
if(m_pRootNode) {
m_pRootNode->remove(pNode);
pNode->removeFromOctreeNodes();
}
}

View File

@@ -34,7 +34,6 @@ public:
private:
KROctreeNode *m_pRootNode;
std::set<KRNode *> m_outerSceneNodes;
//std::set<KRMat4> visibleMVPs;
void shrink();
};

View File

@@ -10,8 +10,10 @@
#include "KRNode.h"
#include "KRCollider.h"
KROctreeNode::KROctreeNode(const KRAABB &bounds) : m_bounds(bounds)
KROctreeNode::KROctreeNode(KROctreeNode *parent, const KRAABB &bounds) : m_bounds(bounds)
{
m_parent = parent;
for(int i=0; i<8; i++) m_children[i] = NULL;
m_occlusionQuery = 0;
@@ -19,11 +21,14 @@ KROctreeNode::KROctreeNode(const KRAABB &bounds) : m_bounds(bounds)
m_activeQuery = false;
}
KROctreeNode::KROctreeNode(const KRAABB &bounds, int iChild, KROctreeNode *pChild) : m_bounds(bounds)
KROctreeNode::KROctreeNode(KROctreeNode *parent, const KRAABB &bounds, int iChild, KROctreeNode *pChild) : m_bounds(bounds)
{
// This constructor is used when expanding the octree and replacing the root node with a new root that encapsulates it
m_parent = parent;
for(int i=0; i<8; i++) m_children[i] = NULL;
m_children[iChild] = pChild;
pChild->m_parent = this;
m_occlusionQuery = 0;
m_occlusionTested = false;
@@ -81,9 +86,10 @@ void KROctreeNode::add(KRNode *pNode)
int iChild = getChildIndex(pNode);
if(iChild == -1) {
m_sceneNodes.insert(pNode);
pNode->addToOctreeNode(this);
} else {
if(m_children[iChild] == NULL) {
m_children[iChild] = new KROctreeNode(getChildBounds(iChild));
m_children[iChild] = new KROctreeNode(this, getChildBounds(iChild));
}
m_children[iChild]->add(pNode);
}
@@ -115,12 +121,10 @@ int KROctreeNode::getChildIndex(KRNode *pNode)
return -1;
}
void KROctreeNode::remove(KRNode *pNode)
void KROctreeNode::trim()
{
if(!m_sceneNodes.erase(pNode)) {
int iChild = getChildIndex(pNode);
for(int iChild = 0; iChild < 8; iChild++) {
if(m_children[iChild]) {
m_children[iChild]->remove(pNode);
if(m_children[iChild]->isEmpty()) {
delete m_children[iChild];
m_children[iChild] = NULL;
@@ -129,6 +133,11 @@ void KROctreeNode::remove(KRNode *pNode)
}
}
void KROctreeNode::remove(KRNode *pNode)
{
m_sceneNodes.erase(pNode);
}
void KROctreeNode::update(KRNode *pNode)
{
@@ -162,6 +171,7 @@ KROctreeNode *KROctreeNode::stripChild()
for(int i=0; i<8; i++) {
if(m_children[i]) {
KROctreeNode *child = m_children[i];
child->m_parent = NULL;
m_children[i] = NULL;
return child;
}
@@ -170,6 +180,11 @@ KROctreeNode *KROctreeNode::stripChild()
}
KROctreeNode *KROctreeNode::getParent()
{
return m_parent;
}
KROctreeNode **KROctreeNode::getChildren()
{
return m_children;

View File

@@ -18,8 +18,8 @@ class KRNode;
class KROctreeNode {
public:
KROctreeNode(const KRAABB &bounds);
KROctreeNode(const KRAABB &bounds, int iChild, KROctreeNode *pChild);
KROctreeNode(KROctreeNode *parent, const KRAABB &bounds);
KROctreeNode(KROctreeNode *parent, const KRAABB &bounds, int iChild, KROctreeNode *pChild);
~KROctreeNode();
KROctreeNode **getChildren();
@@ -31,9 +31,11 @@ public:
KRAABB getBounds();
KROctreeNode *getParent();
void setChildNode(int iChild, KROctreeNode *pChild);
int getChildIndex(KRNode *pNode);
KRAABB getChildBounds(int iChild);
void trim();
bool isEmpty() const;
bool canShrinkRoot() const;
@@ -53,6 +55,7 @@ private:
KRAABB m_bounds;
KROctreeNode *m_parent;
KROctreeNode *m_children[8];
std::set<KRNode *>m_sceneNodes;

View File

@@ -73,7 +73,7 @@ void KRScene::renderFrame(float deltaTime, int width, int height) {
}
void KRScene::render(KRCamera *pCamera, std::map<KRAABB, int> &visibleBounds, const KRViewport &viewport, KRNode::RenderPass renderPass, bool new_frame) {
updateOctree();
if(new_frame) {
@@ -97,7 +97,6 @@ void KRScene::render(KRCamera *pCamera, std::map<KRAABB, int> &visibleBounds, co
std::vector<KRLight *> lights;
updateOctree();
pCamera->settings.setSkyBox(m_skyBoxName); // This is temporary until the camera is moved into the scene graph
@@ -383,40 +382,47 @@ KRLight *KRScene::getFirstLight()
void KRScene::notify_sceneGraphCreate(KRNode *pNode)
{
m_nodeTree.add(pNode);
if(pNode->hasPhysics()) {
m_physicsNodes.insert(pNode);
}
// m_newNodes.insert(pNode);
// m_nodeTree.add(pNode);
// if(pNode->hasPhysics()) {
// m_physicsNodes.insert(pNode);
// }
m_newNodes.insert(pNode);
}
void KRScene::notify_sceneGraphModify(KRNode *pNode)
{
// m_nodeTree.update(pNode);
m_modifiedNodes.insert(pNode);
}
void KRScene::notify_sceneGraphDelete(KRNode *pNode)
{
m_nodeTree.remove(pNode);
m_physicsNodes.erase(pNode);
//
// m_modifiedNodes.erase(pNode);
// if(!m_newNodes.erase(pNode)) {
// m_nodeTree.remove(pNode);
// }
}
void KRScene::notify_sceneGraphModify(KRNode *pNode)
{
m_nodeTree.update(pNode);
// m_modifiedNodes.insert(pNode);
m_modifiedNodes.erase(pNode);
if(!m_newNodes.erase(pNode)) {
m_nodeTree.remove(pNode);
}
}
void KRScene::updateOctree()
{
// for(std::set<KRNode *>::iterator itr=m_newNodes.begin(); itr != m_newNodes.end(); itr++) {
// m_nodeTree.add(*itr);
// }
// for(std::set<KRNode *>::iterator itr=m_modifiedNodes.begin(); itr != m_modifiedNodes.end(); itr++) {
// m_nodeTree.update(*itr);
// }
// m_newNodes.clear();
// m_modifiedNodes.clear();
std::set<KRNode *> newNodes = m_newNodes;
std::set<KRNode *> modifiedNodes = m_modifiedNodes;
m_newNodes.clear();
m_modifiedNodes.clear();
for(std::set<KRNode *>::iterator itr=newNodes.begin(); itr != newNodes.end(); itr++) {
KRNode *node = *itr;
m_nodeTree.add(node);
if(node->hasPhysics()) {
m_physicsNodes.insert(node);
}
}
for(std::set<KRNode *>::iterator itr=modifiedNodes.begin(); itr != modifiedNodes.end(); itr++) {
KRNode *node = *itr;
m_nodeTree.update(node);
}
}
void KRScene::physicsUpdate(float deltaTime)