mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 01:56:54 +02:00
Improved VoxelNode delete callback based on CR feedback
- changed hooks to use a virtual base class approach - switched account of hooks to use a vector instead of home grown solution - added support for VoxelNode to know what VoxelSystem it belongs to
This commit is contained in:
parent
e20f163e0a
commit
1a73485e36
6 changed files with 48 additions and 59 deletions
|
@ -59,15 +59,13 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) :
|
||||||
pthread_mutex_init(&_bufferWriteLock, NULL);
|
pthread_mutex_init(&_bufferWriteLock, NULL);
|
||||||
pthread_mutex_init(&_treeLock, NULL);
|
pthread_mutex_init(&_treeLock, NULL);
|
||||||
|
|
||||||
_hookID = VoxelNode::addDeleteHook(voxelNodeDeleteHook, this);
|
VoxelNode::addDeleteHook(this);
|
||||||
_abandonedVBOSlots = 0;
|
_abandonedVBOSlots = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::voxelNodeDeleteHook(VoxelNode* node, void* extraData) {
|
void VoxelSystem::nodeDeleted(VoxelNode* node) {
|
||||||
VoxelSystem* theSystem = (VoxelSystem*)extraData;
|
if (node->isKnownBufferIndex() && (node->getVoxelSystem() == this)) {
|
||||||
|
freeBufferIndex(node->getBufferIndex());
|
||||||
if (node->isKnownBufferIndex()) {
|
|
||||||
theSystem->freeBufferIndex(node->getBufferIndex());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +97,7 @@ VoxelSystem::~VoxelSystem() {
|
||||||
pthread_mutex_destroy(&_bufferWriteLock);
|
pthread_mutex_destroy(&_bufferWriteLock);
|
||||||
pthread_mutex_destroy(&_treeLock);
|
pthread_mutex_destroy(&_treeLock);
|
||||||
|
|
||||||
VoxelNode::removeDeleteHook(_hookID);
|
VoxelNode::removeDeleteHook(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
|
void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
|
||||||
|
@ -401,11 +399,13 @@ int VoxelSystem::updateNodeInArraysAsFullVBO(VoxelNode* node) {
|
||||||
// and RGB color for each added vertex
|
// and RGB color for each added vertex
|
||||||
updateNodeInArrays(nodeIndex, startVertex, voxelScale, node->getColor());
|
updateNodeInArrays(nodeIndex, startVertex, voxelScale, node->getColor());
|
||||||
node->setBufferIndex(nodeIndex);
|
node->setBufferIndex(nodeIndex);
|
||||||
|
node->setVoxelSystem(this);
|
||||||
_writeVoxelDirtyArray[nodeIndex] = true; // just in case we switch to Partial mode
|
_writeVoxelDirtyArray[nodeIndex] = true; // just in case we switch to Partial mode
|
||||||
_voxelsInWriteArrays++; // our know vertices in the arrays
|
_voxelsInWriteArrays++; // our know vertices in the arrays
|
||||||
return 1; // rendered
|
return 1; // rendered
|
||||||
} else {
|
} else {
|
||||||
node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN);
|
node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN);
|
||||||
|
node->setVoxelSystem(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0; // not-rendered
|
return 0; // not-rendered
|
||||||
|
@ -440,6 +440,7 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) {
|
||||||
} else {
|
} else {
|
||||||
nodeIndex = _voxelsInWriteArrays;
|
nodeIndex = _voxelsInWriteArrays;
|
||||||
node->setBufferIndex(nodeIndex);
|
node->setBufferIndex(nodeIndex);
|
||||||
|
node->setVoxelSystem(this);
|
||||||
_voxelsInWriteArrays++;
|
_voxelsInWriteArrays++;
|
||||||
}
|
}
|
||||||
_writeVoxelDirtyArray[nodeIndex] = true;
|
_writeVoxelDirtyArray[nodeIndex] = true;
|
||||||
|
|
|
@ -28,7 +28,7 @@ class ProgramObject;
|
||||||
|
|
||||||
const int NUM_CHILDREN = 8;
|
const int NUM_CHILDREN = 8;
|
||||||
|
|
||||||
class VoxelSystem : public NodeData {
|
class VoxelSystem : public NodeData, public VoxelNodeDeleteHook {
|
||||||
public:
|
public:
|
||||||
VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = MAX_VOXELS_PER_SYSTEM);
|
VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = MAX_VOXELS_PER_SYSTEM);
|
||||||
~VoxelSystem();
|
~VoxelSystem();
|
||||||
|
@ -92,6 +92,8 @@ public:
|
||||||
|
|
||||||
CoverageMapV2 myCoverageMapV2;
|
CoverageMapV2 myCoverageMapV2;
|
||||||
CoverageMap myCoverageMap;
|
CoverageMap myCoverageMap;
|
||||||
|
|
||||||
|
virtual void nodeDeleted(VoxelNode* node);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float _treeScale;
|
float _treeScale;
|
||||||
|
@ -191,7 +193,6 @@ private:
|
||||||
int _hookID;
|
int _hookID;
|
||||||
std::vector<glBufferIndex> _freeIndexes;
|
std::vector<glBufferIndex> _freeIndexes;
|
||||||
|
|
||||||
static void voxelNodeDeleteHook(VoxelNode* node, void* extraData);
|
|
||||||
void freeBufferIndex(glBufferIndex index);
|
void freeBufferIndex(glBufferIndex index);
|
||||||
void clearFreeBufferIndexes();
|
void clearFreeBufferIndexes();
|
||||||
};
|
};
|
||||||
|
|
|
@ -48,6 +48,7 @@ void VoxelNode::init(unsigned char * octalCode) {
|
||||||
_subtreeLeafNodeCount = 0; // that's me
|
_subtreeLeafNodeCount = 0; // that's me
|
||||||
|
|
||||||
_glBufferIndex = GLBUFFER_INDEX_UNKNOWN;
|
_glBufferIndex = GLBUFFER_INDEX_UNKNOWN;
|
||||||
|
_voxelSystem = NULL;
|
||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
_shouldRender = false;
|
_shouldRender = false;
|
||||||
markWithChangedTime();
|
markWithChangedTime();
|
||||||
|
@ -399,43 +400,23 @@ float VoxelNode::distanceToPoint(const glm::vec3& point) const {
|
||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelNodeDeleteHook VoxelNode::_hooks[VOXEL_NODE_MAX_DELETE_HOOKS];
|
std::vector<VoxelNodeDeleteHook*> VoxelNode::_hooks;
|
||||||
void* VoxelNode::_hooksExtraData[VOXEL_NODE_MAX_DELETE_HOOKS];
|
|
||||||
int VoxelNode::_hooksInUse = 0;
|
|
||||||
|
|
||||||
int VoxelNode::addDeleteHook(VoxelNodeDeleteHook hook, void* extraData) {
|
void VoxelNode::addDeleteHook(VoxelNodeDeleteHook* hook) {
|
||||||
// If first use, initialize the _hooks array
|
_hooks.push_back(hook);
|
||||||
if (_hooksInUse == 0) {
|
|
||||||
memset(_hooks, 0, sizeof(_hooks));
|
|
||||||
memset(_hooksExtraData, 0, sizeof(_hooksExtraData));
|
|
||||||
}
|
|
||||||
// find first available slot
|
|
||||||
for (int i = 0; i < VOXEL_NODE_MAX_DELETE_HOOKS; i++) {
|
|
||||||
if (!_hooks[i]) {
|
|
||||||
_hooks[i] = hook;
|
|
||||||
_hooksExtraData[i] = extraData;
|
|
||||||
_hooksInUse++;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if we got here, then we're out of room in our hooks, return error
|
|
||||||
return VOXEL_NODE_NO_MORE_HOOKS_AVAILABLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelNode::removeDeleteHook(int hookID) {
|
void VoxelNode::removeDeleteHook(VoxelNodeDeleteHook* hook) {
|
||||||
if (_hooks[hookID]) {
|
for (int i = 0; i < _hooks.size(); i++) {
|
||||||
_hooks[hookID] = NULL;
|
if (_hooks[i] == hook) {
|
||||||
_hooksExtraData[hookID] = NULL;
|
_hooks.erase(_hooks.begin() + i);
|
||||||
_hooksInUse--;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelNode::notifyDeleteHooks() {
|
void VoxelNode::notifyDeleteHooks() {
|
||||||
if (_hooksInUse > 0) {
|
for (int i = 0; i < _hooks.size(); i++) {
|
||||||
for (int i = 0; i < VOXEL_NODE_MAX_DELETE_HOOKS; i++) {
|
_hooks[i]->nodeDeleted(this);
|
||||||
if (_hooks[i]) {
|
|
||||||
_hooks[i](this, _hooksExtraData[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,18 +14,19 @@
|
||||||
#include "ViewFrustum.h"
|
#include "ViewFrustum.h"
|
||||||
#include "VoxelConstants.h"
|
#include "VoxelConstants.h"
|
||||||
|
|
||||||
class VoxelTree; // forward delclaration
|
class VoxelTree; // forward declaration
|
||||||
class VoxelNode; // forward delclaration
|
class VoxelNode; // forward declaration
|
||||||
|
class VoxelSystem; // forward declaration
|
||||||
|
|
||||||
typedef unsigned char colorPart;
|
typedef unsigned char colorPart;
|
||||||
typedef unsigned char nodeColor[4];
|
typedef unsigned char nodeColor[4];
|
||||||
typedef unsigned char rgbColor[3];
|
typedef unsigned char rgbColor[3];
|
||||||
|
|
||||||
// Callback function, for delete hook
|
// Callers who want delete hook callbacks should implement this class
|
||||||
typedef void (*VoxelNodeDeleteHook)(VoxelNode* node, void* extraData);
|
class VoxelNodeDeleteHook {
|
||||||
const int VOXEL_NODE_MAX_DELETE_HOOKS = 100;
|
public:
|
||||||
const int VOXEL_NODE_NO_MORE_HOOKS_AVAILABLE = -1;
|
virtual void nodeDeleted(VoxelNode* node) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class VoxelNode {
|
class VoxelNode {
|
||||||
public:
|
public:
|
||||||
|
@ -77,6 +78,9 @@ public:
|
||||||
glBufferIndex getBufferIndex() const { return _glBufferIndex; };
|
glBufferIndex getBufferIndex() const { return _glBufferIndex; };
|
||||||
bool isKnownBufferIndex() const { return (_glBufferIndex != GLBUFFER_INDEX_UNKNOWN); };
|
bool isKnownBufferIndex() const { return (_glBufferIndex != GLBUFFER_INDEX_UNKNOWN); };
|
||||||
void setBufferIndex(glBufferIndex index) { _glBufferIndex = index; };
|
void setBufferIndex(glBufferIndex index) { _glBufferIndex = index; };
|
||||||
|
VoxelSystem* getVoxelSystem() const { return _voxelSystem; };
|
||||||
|
void setVoxelSystem(VoxelSystem* voxelSystem) { _voxelSystem = voxelSystem; };
|
||||||
|
|
||||||
|
|
||||||
// Used by VoxelSystem for rendering in/out of view and LOD
|
// Used by VoxelSystem for rendering in/out of view and LOD
|
||||||
void setShouldRender(bool shouldRender);
|
void setShouldRender(bool shouldRender);
|
||||||
|
@ -101,8 +105,8 @@ public:
|
||||||
const nodeColor& getColor() const { return _trueColor; };
|
const nodeColor& getColor() const { return _trueColor; };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int addDeleteHook(VoxelNodeDeleteHook hook, void* extraData = NULL);
|
static void addDeleteHook(VoxelNodeDeleteHook* hook);
|
||||||
static void removeDeleteHook(int hookID);
|
static void removeDeleteHook(VoxelNodeDeleteHook* hook);
|
||||||
|
|
||||||
void recalculateSubTreeNodeCount();
|
void recalculateSubTreeNodeCount();
|
||||||
unsigned long getSubTreeNodeCount() const { return _subtreeNodeCount; };
|
unsigned long getSubTreeNodeCount() const { return _subtreeNodeCount; };
|
||||||
|
@ -120,6 +124,7 @@ private:
|
||||||
bool _falseColored;
|
bool _falseColored;
|
||||||
#endif
|
#endif
|
||||||
glBufferIndex _glBufferIndex;
|
glBufferIndex _glBufferIndex;
|
||||||
|
VoxelSystem* _voxelSystem;
|
||||||
bool _isDirty;
|
bool _isDirty;
|
||||||
uint64_t _lastChanged;
|
uint64_t _lastChanged;
|
||||||
bool _shouldRender;
|
bool _shouldRender;
|
||||||
|
@ -130,10 +135,8 @@ private:
|
||||||
unsigned long _subtreeNodeCount;
|
unsigned long _subtreeNodeCount;
|
||||||
unsigned long _subtreeLeafNodeCount;
|
unsigned long _subtreeLeafNodeCount;
|
||||||
float _density; // If leaf: density = 1, if internal node: 0-1 density of voxels inside
|
float _density; // If leaf: density = 1, if internal node: 0-1 density of voxels inside
|
||||||
|
|
||||||
static VoxelNodeDeleteHook _hooks[VOXEL_NODE_MAX_DELETE_HOOKS];
|
static std::vector<VoxelNodeDeleteHook*> _hooks;
|
||||||
static void* _hooksExtraData[VOXEL_NODE_MAX_DELETE_HOOKS];
|
|
||||||
static int _hooksInUse;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__VoxelNode__) */
|
#endif /* defined(__hifi__VoxelNode__) */
|
||||||
|
|
|
@ -13,11 +13,11 @@ VoxelNodeBag::VoxelNodeBag() :
|
||||||
_bagElements(NULL),
|
_bagElements(NULL),
|
||||||
_elementsInUse(0),
|
_elementsInUse(0),
|
||||||
_sizeOfElementsArray(0) {
|
_sizeOfElementsArray(0) {
|
||||||
_hookID = VoxelNode::addDeleteHook(voxelNodeDeleteHook, this);
|
VoxelNode::addDeleteHook(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
VoxelNodeBag::~VoxelNodeBag() {
|
VoxelNodeBag::~VoxelNodeBag() {
|
||||||
VoxelNode::removeDeleteHook(_hookID);
|
VoxelNode::removeDeleteHook(this);
|
||||||
deleteAll();
|
deleteAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,9 +125,10 @@ void VoxelNodeBag::remove(VoxelNode* node) {
|
||||||
_elementsInUse--;
|
_elementsInUse--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void VoxelNodeBag::voxelNodeDeleteHook(VoxelNode* node, void* extraData) {
|
|
||||||
VoxelNodeBag* theBag = (VoxelNodeBag*)extraData;
|
|
||||||
theBag->remove(node); // note: remove can safely handle nodes that aren't in it, so we don't need to check contains()
|
void VoxelNodeBag::nodeDeleted(VoxelNode* node) {
|
||||||
|
remove(node); // note: remove can safely handle nodes that aren't in it, so we don't need to check contains()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
#include "VoxelNode.h"
|
#include "VoxelNode.h"
|
||||||
|
|
||||||
class VoxelNodeBag {
|
class VoxelNodeBag : public VoxelNodeDeleteHook {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VoxelNodeBag();
|
VoxelNodeBag();
|
||||||
|
@ -34,6 +34,8 @@ public:
|
||||||
|
|
||||||
static void voxelNodeDeleteHook(VoxelNode* node, void* extraData);
|
static void voxelNodeDeleteHook(VoxelNode* node, void* extraData);
|
||||||
|
|
||||||
|
virtual void nodeDeleted(VoxelNode* node);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
VoxelNode** _bagElements;
|
VoxelNode** _bagElements;
|
||||||
|
|
Loading…
Reference in a new issue