From ef2d27aba6b339555b7c2d9cccbd8cc6bfde952e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 21 May 2013 10:43:31 -0700 Subject: [PATCH] getting closer to working delete --- interface/src/VoxelSystem.cpp | 12 ----- libraries/voxels/src/VoxelNode.cpp | 27 +++++++++++ libraries/voxels/src/VoxelNode.h | 6 ++- libraries/voxels/src/VoxelTree.cpp | 77 +++++++----------------------- voxel-server/src/main.cpp | 7 ++- 5 files changed, 55 insertions(+), 74 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index be79acae0f..5ead332fbf 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -104,15 +104,8 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { switch(command) { case PACKET_HEADER_VOXEL_DATA: { -//printLog("PACKET_HEADER_VOXEL_DATA voxelData="); -//outputBufferBits(sourceBuffer, numBytes); - PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()"); // ask the VoxelTree to read the bitstream into the tree -// printLog("PACKET_HEADER_VOXEL_DATA = \n"); -// outputBufferBits(sourceBuffer, numBytes); - - _tree->readBitstreamToTree(voxelData, numBytes - 1, true, _wantsExistBits); } break; @@ -123,11 +116,6 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { _tree->readBitstreamToTree(voxelData, numBytes - 1, false, _wantsExistBits); } break; - case PACKET_HEADER_ERASE_VOXEL: - // ask the tree to read the "remove" bitstream - //_tree->processRemoveVoxelBitstream(sourceBuffer, numBytes); - //printLog("ignoring PACKET_HEADER_ERASE_VOXEL\n"); - break; case PACKET_HEADER_Z_COMMAND: // the Z command is a special command that allows the sender to send high level semantic diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 37abc3505b..d33b7c1051 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -119,6 +119,33 @@ void VoxelNode::addChildAtIndex(int childIndex) { } } +// handles staging or deletion of all deep children +void VoxelNode::safeDeepDeleteChildAtIndex(int childIndex, bool& stagedForDeletion) { + VoxelNode* childToDelete = getChildAtIndex(childIndex); + if (childToDelete) { + // If the child is not a leaf, then call ourselves recursively on all the children + if (!childToDelete->isLeaf()) { + // delete all it's children + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + childToDelete->safeDeepDeleteChildAtIndex(i, stagedForDeletion); + } + } + // if this node has a BufferIndex then we need to stage it for deletion + // instead of actually deleting it from the tree + if (childToDelete->isKnownBufferIndex()) { + stagedForDeletion = true; + } + if (stagedForDeletion) { + childToDelete->stageForDeletion(); + _isDirty = true; + } else { + deleteChildAtIndex(childIndex); + _isDirty = true; + } + } +} + + // will average the child colors... void VoxelNode::setColorFromAverageOfChildren() { int colorArray[4] = {0,0,0,0}; diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 10ad889ba3..710963b5b8 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -43,10 +43,12 @@ public: ~VoxelNode(); unsigned char* getOctalCode() const { return _octalCode; }; - VoxelNode* getChildAtIndex(int i) const { return _children[i]; }; + VoxelNode* getChildAtIndex(int childIndex) const { return _children[childIndex]; }; void deleteChildAtIndex(int childIndex); VoxelNode* removeChildAtIndex(int childIndex); void addChildAtIndex(int childIndex); + void safeDeepDeleteChildAtIndex(int childIndex, bool& stagedForDeletion); // handles staging or deletion of all descendents + void setColorFromAverageOfChildren(); void setRandomColor(int minimumBrightness); bool collapseIdenticalLeaves(); @@ -80,7 +82,7 @@ public: bool getShouldRender() const { return _shouldRender; } // Used by VoxelSystem to mark a node as to be deleted on next render pass - void stageForDeletion() { _isStagedForDeletion = true; }; + void stageForDeletion() { _isStagedForDeletion = true; _isDirty = true; }; bool isStagedForDeletion() const { return _isStagedForDeletion; } #ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index b26a70e365..ea77d0175f 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -128,11 +128,6 @@ VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, int bytesLeftToRead, bool includeColor, bool includeExistsBits) { - - -if (includeExistsBits) { - //printLog("readNodeData() expecting includeExistsBits\n"); -} // give this destination node the child mask from the packet const unsigned char ALL_CHILDREN_ASSUMED_TO_EXIST = 0xFF; unsigned char colorInPacketMask = *nodeData; @@ -145,9 +140,6 @@ if (includeExistsBits) { if (oneAtBit(colorInPacketMask, i)) { // create the child if it doesn't exist if (!destinationNode->getChildAtIndex(i)) { -//printLog(">>>>>>>> readNodeData() colorInPacketMask area -- calling addChildAtIndex() at %d colorInTreeBitSet=%s<<<<<<<\n",i, -// debugHelpers::booleanValue(oneAtBit(colorInTreeMask, i))); - destinationNode->addChildAtIndex(i); if (destinationNode->isDirty()) { _isDirty = true; @@ -175,19 +167,6 @@ if (includeExistsBits) { this->voxelsColored++; this->voxelsColoredStats.updateAverage(1); } - - // now also check the colorInTreeMask, if the mask is missing the bit, then it means we need to delete this child - // node, because it shouldn't actually exist in the tree. - /** - if (!oneAtBit(colorInTreeMask, i) && destinationNode->getChildAtIndex(i) && - destinationNode->getChildAtIndex(i)->isColored()) { - - destinationNode->printDebugDetails("colorInTreeMask mismatch "); - // we should delete this node!!! - printLog("colorInTreeMask for child %d missing, should delete this node? colorInTreeMask=",i); - outputBits(colorInTreeMask, true); - } - **/ } // give this destination node the child mask from the packet @@ -204,10 +183,6 @@ if (includeExistsBits) { if (!destinationNode->getChildAtIndex(childIndex)) { // add a child at that index, if it doesn't exist bool nodeWasDirty = destinationNode->isDirty(); -//printLog(">>>>>>>> readNodeData() childMask area -- calling addChildAtIndex() at %d colorInTreeBitSet=%s<<<<<<<\n",childIndex, -// debugHelpers::booleanValue(oneAtBit(childrenInTreeMask, childIndex))); - - destinationNode->addChildAtIndex(childIndex); bool nodeIsDirty = destinationNode->isDirty(); if (nodeIsDirty) { @@ -226,29 +201,19 @@ if (includeExistsBits) { } childIndex++; } - - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - // now also check the childrenInTreeMask, if the mask is missing the bit, then it means we need to delete this child - // subtree/node, because it shouldn't actually exist in the tree. - if (!oneAtBit(childrenInTreeMask, i) && destinationNode->getChildAtIndex(i)) { - // we should delete this node!!! - //destinationNode->printDebugDetails("childrenInTreeMask mismatch "); - //printLog("childrenInTreeMask for child %d missing, should delete this node? childrenInTreeMask=",i); - //outputBits(childrenInTreeMask, true); - - // If this node has a VBO index, then we can only stage it for deletion, otherwise delete away! - if (destinationNode->getChildAtIndex(i)->isKnownBufferIndex()) { - printLog("childrenInTreeMask for child %d missing, staging for deletion\n",i); - destinationNode->getChildAtIndex(i)->stageForDeletion(); - _isDirty = true; - } else { - printLog("childrenInTreeMask for child %d missing, deleting now\n",i); - destinationNode->deleteChildAtIndex(i); - _isDirty = true; - } - } - } + + if (includeExistsBits) { + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + // now also check the childrenInTreeMask, if the mask is missing the bit, then it means we need to delete this child + // subtree/node, because it shouldn't actually exist in the tree. + if (!oneAtBit(childrenInTreeMask, i) && destinationNode->getChildAtIndex(i)) { + bool stagedForDeletion = false; // assume staging is not needed + destinationNode->safeDeepDeleteChildAtIndex(i, stagedForDeletion); + _isDirty = true; // by definition! + } + } + } return bytesRead; } @@ -303,10 +268,8 @@ void VoxelTree::deleteVoxelAt(float x, float y, float z, float s, bool stage) { // Note: uses the codeColorBuffer format, but the color's are ignored, because // this only finds and deletes the node from the tree. void VoxelTree::deleteVoxelCodeFromTree(unsigned char* codeBuffer, bool stage) { - VoxelNode* parentNode = NULL; VoxelNode* nodeToDelete = nodeForOctalCode(rootNode, codeBuffer, &parentNode); - // If the node exists... int lengthInBytes = bytesRequiredForCodeLength(*codeBuffer); // includes octet count, not color! @@ -314,24 +277,20 @@ void VoxelTree::deleteVoxelCodeFromTree(unsigned char* codeBuffer, bool stage) { if (0 == memcmp(nodeToDelete->getOctalCode(), codeBuffer, lengthInBytes)) { if (parentNode) { int childIndex = branchIndexWithDescendant(parentNode->getOctalCode(), codeBuffer); - if (stage) { nodeToDelete->stageForDeletion(); } else { parentNode->deleteChildAtIndex(childIndex); } - - // ok, also make sure, that if this is the last child of this parent, then we should - // delete the parent also... is that right? - if (parentNode->getChildCount() < 2) { - printLog("deleteVoxelCodeFromTree()... parentNode->getChildCount() = %d\n", parentNode->getChildCount() ); - parentNode->printDebugDetails("deleteVoxelCodeFromTree()"); - if (parentNode->getChildCount() == 0 && !parentNode->isColored()) { - printLog("deleteVoxelCodeFromTree()... no more children and not colored... deleting parentNode\n" ); + + // If we're not a colored leaf, and we have no children, then delete ourselves + // This will collapse the empty tree above us. + if (parentNode->getChildCount() == 0 && !parentNode->isColored()) { + // Can't delete the root this way. + if (parentNode != rootNode) { deleteVoxelCodeFromTree(parentNode->getOctalCode(),stage); } } - reaverageVoxelColors(rootNode); // Fix our colors!! Need to call it on rootNode _isDirty = true; } diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 4cfe492baf..e5d70567ca 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -257,6 +257,10 @@ void deepestLevelVoxelDistributor(AgentList* agentList, // the current view frustum for things to send. if (viewFrustumChanged || agentData->nodeBag.isEmpty()) { + // just add the rootNode, to see if this addresses the delete problem + agentData->nodeBag.insert(randomTree.rootNode); + +/*** //printf("bag empty, search for stuff in view...\n"); // If the bag was empty, then send everything in view, not just the delta maxLevelReached = randomTree.searchForColoredNodes(INT_MAX, randomTree.rootNode, agentData->getCurrentViewFrustum(), @@ -264,10 +268,11 @@ void deepestLevelVoxelDistributor(AgentList* agentList, // if nothing was found in view, send the root node. if (agentData->nodeBag.isEmpty()){ -//printf("huh... bag STILL empty, what to do? Add the root?...\n"); +printf("huh... bag STILL empty, what to do? Add the root?...\n"); agentData->nodeBag.insert(randomTree.rootNode); } agentData->setViewSent(false); +**/ } double end = usecTimestampNow();