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:
@@ -33,7 +33,8 @@
|
|||||||
#define KRHITINFO_H
|
#define KRHITINFO_H
|
||||||
|
|
||||||
#include "KRVector3.h"
|
#include "KRVector3.h"
|
||||||
#include "KRNode.h"
|
|
||||||
|
class KRNode;
|
||||||
|
|
||||||
class KRHitInfo {
|
class KRHitInfo {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "KRVector3.h"
|
#include "KRVector3.h"
|
||||||
#include "KRViewport.h"
|
#include "KRViewport.h"
|
||||||
#include "tinyxml2.h"
|
#include "tinyxml2.h"
|
||||||
|
#include "KROctreeNode.h"
|
||||||
|
|
||||||
class KRCamera;
|
class KRCamera;
|
||||||
class KRShaderManager;
|
class KRShaderManager;
|
||||||
@@ -131,8 +132,13 @@ private:
|
|||||||
|
|
||||||
KRScene *m_pScene;
|
KRScene *m_pScene;
|
||||||
|
|
||||||
|
std::set<KROctreeNode *> m_octree_nodes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
void removeFromOctreeNodes();
|
||||||
|
void addToOctreeNode(KROctreeNode *octree_node);
|
||||||
|
|
||||||
template <class T> T *find()
|
template <class T> T *find()
|
||||||
{
|
{
|
||||||
T *match = dynamic_cast<T *>(this);
|
T *match = dynamic_cast<T *>(this);
|
||||||
|
|||||||
@@ -32,8 +32,7 @@ void KROctree::add(KRNode *pNode)
|
|||||||
} else {
|
} else {
|
||||||
if(m_pRootNode == NULL) {
|
if(m_pRootNode == NULL) {
|
||||||
// First item inserted, create a node large enough to fit it
|
// First item inserted, create a node large enough to fit it
|
||||||
m_pRootNode = new KROctreeNode(nodeBounds);
|
m_pRootNode = new KROctreeNode(NULL, nodeBounds);
|
||||||
//m_pRootNode = new KROctreeNode(KRAABB(nodeBounds.min - nodeBounds.size() * 0.25f, nodeBounds.max + nodeBounds.size() * 0.25f));
|
|
||||||
m_pRootNode->add(pNode);
|
m_pRootNode->add(pNode);
|
||||||
} else {
|
} else {
|
||||||
// Keep encapsulating the root node until the new root contains the inserted node
|
// 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();
|
KRAABB rootBounds = m_pRootNode->getBounds();
|
||||||
KRVector3 rootSize = rootBounds.size();
|
KRVector3 rootSize = rootBounds.size();
|
||||||
if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) {
|
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) {
|
} 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 {
|
} else {
|
||||||
bInsideRoot = true;
|
bInsideRoot = true;
|
||||||
}
|
}
|
||||||
@@ -58,7 +57,7 @@ void KROctree::remove(KRNode *pNode)
|
|||||||
{
|
{
|
||||||
if(!m_outerSceneNodes.erase(pNode)) {
|
if(!m_outerSceneNodes.erase(pNode)) {
|
||||||
if(m_pRootNode) {
|
if(m_pRootNode) {
|
||||||
m_pRootNode->remove(pNode);
|
pNode->removeFromOctreeNodes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
KROctreeNode *m_pRootNode;
|
KROctreeNode *m_pRootNode;
|
||||||
std::set<KRNode *> m_outerSceneNodes;
|
std::set<KRNode *> m_outerSceneNodes;
|
||||||
//std::set<KRMat4> visibleMVPs;
|
|
||||||
|
|
||||||
void shrink();
|
void shrink();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,8 +10,10 @@
|
|||||||
#include "KRNode.h"
|
#include "KRNode.h"
|
||||||
#include "KRCollider.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;
|
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||||
|
|
||||||
m_occlusionQuery = 0;
|
m_occlusionQuery = 0;
|
||||||
@@ -19,11 +21,14 @@ KROctreeNode::KROctreeNode(const KRAABB &bounds) : m_bounds(bounds)
|
|||||||
m_activeQuery = false;
|
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
|
// 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;
|
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||||
m_children[iChild] = pChild;
|
m_children[iChild] = pChild;
|
||||||
|
pChild->m_parent = this;
|
||||||
|
|
||||||
m_occlusionQuery = 0;
|
m_occlusionQuery = 0;
|
||||||
m_occlusionTested = false;
|
m_occlusionTested = false;
|
||||||
@@ -81,9 +86,10 @@ void KROctreeNode::add(KRNode *pNode)
|
|||||||
int iChild = getChildIndex(pNode);
|
int iChild = getChildIndex(pNode);
|
||||||
if(iChild == -1) {
|
if(iChild == -1) {
|
||||||
m_sceneNodes.insert(pNode);
|
m_sceneNodes.insert(pNode);
|
||||||
|
pNode->addToOctreeNode(this);
|
||||||
} else {
|
} else {
|
||||||
if(m_children[iChild] == NULL) {
|
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);
|
m_children[iChild]->add(pNode);
|
||||||
}
|
}
|
||||||
@@ -115,12 +121,10 @@ int KROctreeNode::getChildIndex(KRNode *pNode)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KROctreeNode::remove(KRNode *pNode)
|
void KROctreeNode::trim()
|
||||||
{
|
{
|
||||||
if(!m_sceneNodes.erase(pNode)) {
|
for(int iChild = 0; iChild < 8; iChild++) {
|
||||||
int iChild = getChildIndex(pNode);
|
|
||||||
if(m_children[iChild]) {
|
if(m_children[iChild]) {
|
||||||
m_children[iChild]->remove(pNode);
|
|
||||||
if(m_children[iChild]->isEmpty()) {
|
if(m_children[iChild]->isEmpty()) {
|
||||||
delete m_children[iChild];
|
delete m_children[iChild];
|
||||||
m_children[iChild] = NULL;
|
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)
|
void KROctreeNode::update(KRNode *pNode)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -162,6 +171,7 @@ KROctreeNode *KROctreeNode::stripChild()
|
|||||||
for(int i=0; i<8; i++) {
|
for(int i=0; i<8; i++) {
|
||||||
if(m_children[i]) {
|
if(m_children[i]) {
|
||||||
KROctreeNode *child = m_children[i];
|
KROctreeNode *child = m_children[i];
|
||||||
|
child->m_parent = NULL;
|
||||||
m_children[i] = NULL;
|
m_children[i] = NULL;
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
@@ -170,6 +180,11 @@ KROctreeNode *KROctreeNode::stripChild()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KROctreeNode *KROctreeNode::getParent()
|
||||||
|
{
|
||||||
|
return m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
KROctreeNode **KROctreeNode::getChildren()
|
KROctreeNode **KROctreeNode::getChildren()
|
||||||
{
|
{
|
||||||
return m_children;
|
return m_children;
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ class KRNode;
|
|||||||
|
|
||||||
class KROctreeNode {
|
class KROctreeNode {
|
||||||
public:
|
public:
|
||||||
KROctreeNode(const KRAABB &bounds);
|
KROctreeNode(KROctreeNode *parent, const KRAABB &bounds);
|
||||||
KROctreeNode(const KRAABB &bounds, int iChild, KROctreeNode *pChild);
|
KROctreeNode(KROctreeNode *parent, const KRAABB &bounds, int iChild, KROctreeNode *pChild);
|
||||||
~KROctreeNode();
|
~KROctreeNode();
|
||||||
|
|
||||||
KROctreeNode **getChildren();
|
KROctreeNode **getChildren();
|
||||||
@@ -31,9 +31,11 @@ public:
|
|||||||
|
|
||||||
KRAABB getBounds();
|
KRAABB getBounds();
|
||||||
|
|
||||||
|
KROctreeNode *getParent();
|
||||||
void setChildNode(int iChild, KROctreeNode *pChild);
|
void setChildNode(int iChild, KROctreeNode *pChild);
|
||||||
int getChildIndex(KRNode *pNode);
|
int getChildIndex(KRNode *pNode);
|
||||||
KRAABB getChildBounds(int iChild);
|
KRAABB getChildBounds(int iChild);
|
||||||
|
void trim();
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
|
|
||||||
bool canShrinkRoot() const;
|
bool canShrinkRoot() const;
|
||||||
@@ -53,6 +55,7 @@ private:
|
|||||||
|
|
||||||
KRAABB m_bounds;
|
KRAABB m_bounds;
|
||||||
|
|
||||||
|
KROctreeNode *m_parent;
|
||||||
KROctreeNode *m_children[8];
|
KROctreeNode *m_children[8];
|
||||||
|
|
||||||
std::set<KRNode *>m_sceneNodes;
|
std::set<KRNode *>m_sceneNodes;
|
||||||
|
|||||||
@@ -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) {
|
void KRScene::render(KRCamera *pCamera, std::map<KRAABB, int> &visibleBounds, const KRViewport &viewport, KRNode::RenderPass renderPass, bool new_frame) {
|
||||||
|
updateOctree();
|
||||||
|
|
||||||
|
|
||||||
if(new_frame) {
|
if(new_frame) {
|
||||||
@@ -97,7 +97,6 @@ void KRScene::render(KRCamera *pCamera, std::map<KRAABB, int> &visibleBounds, co
|
|||||||
|
|
||||||
std::vector<KRLight *> lights;
|
std::vector<KRLight *> lights;
|
||||||
|
|
||||||
updateOctree();
|
|
||||||
pCamera->settings.setSkyBox(m_skyBoxName); // This is temporary until the camera is moved into the scene graph
|
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)
|
void KRScene::notify_sceneGraphCreate(KRNode *pNode)
|
||||||
{
|
{
|
||||||
m_nodeTree.add(pNode);
|
// m_nodeTree.add(pNode);
|
||||||
if(pNode->hasPhysics()) {
|
// if(pNode->hasPhysics()) {
|
||||||
m_physicsNodes.insert(pNode);
|
// m_physicsNodes.insert(pNode);
|
||||||
}
|
// }
|
||||||
// m_newNodes.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)
|
void KRScene::notify_sceneGraphDelete(KRNode *pNode)
|
||||||
{
|
{
|
||||||
m_nodeTree.remove(pNode);
|
m_nodeTree.remove(pNode);
|
||||||
m_physicsNodes.erase(pNode);
|
m_physicsNodes.erase(pNode);
|
||||||
//
|
m_modifiedNodes.erase(pNode);
|
||||||
// m_modifiedNodes.erase(pNode);
|
if(!m_newNodes.erase(pNode)) {
|
||||||
// if(!m_newNodes.erase(pNode)) {
|
m_nodeTree.remove(pNode);
|
||||||
// m_nodeTree.remove(pNode);
|
}
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRScene::notify_sceneGraphModify(KRNode *pNode)
|
|
||||||
{
|
|
||||||
m_nodeTree.update(pNode);
|
|
||||||
// m_modifiedNodes.insert(pNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRScene::updateOctree()
|
void KRScene::updateOctree()
|
||||||
{
|
{
|
||||||
// for(std::set<KRNode *>::iterator itr=m_newNodes.begin(); itr != m_newNodes.end(); itr++) {
|
std::set<KRNode *> newNodes = m_newNodes;
|
||||||
// m_nodeTree.add(*itr);
|
std::set<KRNode *> modifiedNodes = m_modifiedNodes;
|
||||||
// }
|
m_newNodes.clear();
|
||||||
// for(std::set<KRNode *>::iterator itr=m_modifiedNodes.begin(); itr != m_modifiedNodes.end(); itr++) {
|
m_modifiedNodes.clear();
|
||||||
// m_nodeTree.update(*itr);
|
|
||||||
// }
|
for(std::set<KRNode *>::iterator itr=newNodes.begin(); itr != newNodes.end(); itr++) {
|
||||||
// m_newNodes.clear();
|
KRNode *node = *itr;
|
||||||
// m_modifiedNodes.clear();
|
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)
|
void KRScene::physicsUpdate(float deltaTime)
|
||||||
|
|||||||
Reference in New Issue
Block a user