diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index b5dab29029..e473961c8e 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -232,7 +232,7 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { bool inChildBoundary = (distanceToNode <= childBoundary); shouldRender = (node->isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary); } - node->setShouldRender(shouldRender); + node->setShouldRender(shouldRender && !node->isStagedForDeletion()); // let children figure out their renderness for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { if (node->getChildAtIndex(i)) { @@ -244,6 +244,15 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { } else { voxelsUpdated += updateNodeInArraysAsPartialVBO(node); } + + // If the node has been asked to be deleted, but we've gotten to here, after updateNodeInArraysXXX() + // then it means our VBOs are "clean" and our vertices have been removed or not added. So we can now + // safely remove the node from the tree and actually delete it. + // otherwise honor our calculated shouldRender + if (node->isStagedForDeletion()) { + _tree->deleteVoxelCodeFromTree(node->getOctalCode()); + } + node->clearDirtyBit(); // always clear the dirty bit, even if it doesn't need to be rendered return voxelsUpdated; } @@ -901,9 +910,19 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { void VoxelSystem::deleteVoxelAt(float x, float y, float z, float s) { - //printLog("VoxelSystem::deleteVoxelAt(%f,%f,%f,%f)\n",x,y,z,s); - _tree->deleteVoxelAt(x, y, z, s); - setupNewVoxelsForDrawing(); + printLog("VoxelSystem::deleteVoxelAt(%f,%f,%f,%f)\n",x,y,z,s); + + VoxelNode* node = _tree->getVoxelAt(x, y, z, s); + if (node) { + // tell the node we want it deleted + node->stageForDeletion(); + + // tree is now dirty + _tree->setDirtyBit(); + + // redraw! + setupNewVoxelsForDrawing(); // do we even need to do this? Or will the next network receive kick in? + } }; VoxelNode* VoxelSystem::getVoxelAt(float x, float y, float z, float s) const { diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 5af7f09ea2..19e6a12aa5 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -44,6 +44,7 @@ void VoxelNode::init(unsigned char * octalCode) { _glBufferIndex = GLBUFFER_INDEX_UNKNOWN; _isDirty = true; _shouldRender = false; + _isStagedForDeletion = false; calculateAABox(); } diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 51af8f6379..c07cb528e6 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -27,6 +27,7 @@ private: glBufferIndex _glBufferIndex; bool _isDirty; bool _shouldRender; + bool _isStagedForDeletion; AABox _box; unsigned char* _octalCode; VoxelNode* _children[8]; @@ -66,9 +67,15 @@ public: glBufferIndex getBufferIndex() const { return _glBufferIndex; }; bool isKnownBufferIndex() const { return (_glBufferIndex != GLBUFFER_INDEX_UNKNOWN); }; void setBufferIndex(glBufferIndex index) { _glBufferIndex = index; }; + + // Used by VoxelSystem for rendering in/out of view and LOD void setShouldRender(bool shouldRender); bool getShouldRender() const { return _shouldRender; } + // Used by VoxelSystem to mark a node as to be deleted on next render pass + void stageForDeletion() { _isStagedForDeletion = true; }; + bool isStagedForDeletion() const { return _isStagedForDeletion; } + #ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color void setFalseColor(colorPart red, colorPart green, colorPart blue); void setFalseColored(bool isFalseColored);