From 66ebb7d01cd230b4816452438e4c3fdb9c851ab9 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 6 Jun 2013 01:39:40 -0700 Subject: [PATCH] Made readCodeColorBufferToTree() use self contained recursion so we can implement color averaging properly --- libraries/shared/src/SharedUtil.cpp | 4 - libraries/voxels/src/VoxelNode.cpp | 3 +- libraries/voxels/src/VoxelNode.h | 2 +- libraries/voxels/src/VoxelTree.cpp | 114 ++++++++++++++++++++-------- libraries/voxels/src/VoxelTree.h | 1 + 5 files changed, 88 insertions(+), 36 deletions(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 08b84e2b7e..cf9e5f9b78 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -188,10 +188,6 @@ bool cmdOptionExists(int argc, const char * argv[],const char* option) { // // HACK ATTACK: Well, what if this is larger than the MTU? That's the caller's problem, we // just truncate the message -// Usage: -// unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue); -// tree->readCodeColorBufferToTree(voxelData); -// delete voxelData; // // Complaints: Brad :) #define GUESS_OF_VOXELCODE_SIZE 10 diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 0a4d813ec7..b5c5b10cac 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -107,13 +107,14 @@ VoxelNode* VoxelNode::removeChildAtIndex(int childIndex) { return returnedChild; } -void VoxelNode::addChildAtIndex(int childIndex) { +VoxelNode* VoxelNode::addChildAtIndex(int childIndex) { if (!_children[childIndex]) { _children[childIndex] = new VoxelNode(childOctalCode(_octalCode, childIndex)); _isDirty = true; markWithChangedTime(); _childCount++; } + return _children[childIndex]; } // handles staging or deletion of all deep children diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 5aa1fe4fa0..997c495693 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -48,7 +48,7 @@ public: VoxelNode* getChildAtIndex(int childIndex) const { return _children[childIndex]; }; void deleteChildAtIndex(int childIndex); VoxelNode* removeChildAtIndex(int childIndex); - void addChildAtIndex(int childIndex); + VoxelNode* addChildAtIndex(int childIndex); void safeDeepDeleteChildAtIndex(int childIndex, bool& stagedForDeletion); // handles staging or deletion of all descendents void setColorFromAverageOfChildren(); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index a9b69d2725..30c61fe4a1 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -401,50 +401,104 @@ void VoxelTree::eraseAllVoxels() { _isDirty = true; } -void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer, bool destructive) { - VoxelNode* lastCreatedNode = nodeForOctalCode(rootNode, codeColorBuffer, NULL); - // create the node if it does not exist - if (*lastCreatedNode->getOctalCode() != *codeColorBuffer) { - lastCreatedNode = createMissingNode(lastCreatedNode, codeColorBuffer); - _isDirty = true; - } else { - // if it does exist, make sure it has no children - for (int i = 0; i < 8; i++) { - if (lastCreatedNode->getChildAtIndex(i)) { - if (destructive) { - lastCreatedNode->deleteChildAtIndex(i); - } else { - printLog("WARNING! operation would require deleting child at index %d, add Voxel ignored!\n ", i); - } +class ReadCodeColorBufferToTreeArgs { +public: + unsigned char* codeColorBuffer; + int lengthOfCode; + bool destructive; + bool pathChanged; +}; + +void VoxelTree::readCodeColorBufferToTree(unsigned char* codeColorBuffer, bool destructive) { + ReadCodeColorBufferToTreeArgs args; + args.codeColorBuffer = codeColorBuffer; + args.lengthOfCode = numberOfThreeBitSectionsInCode(codeColorBuffer); + args.destructive = destructive; + args.pathChanged = false; + + + VoxelNode* node = rootNode; + + readCodeColorBufferToTreeRecursion(node, &args); +} + + +void VoxelTree::readCodeColorBufferToTreeRecursion(VoxelNode* node, void* extraData) { + ReadCodeColorBufferToTreeArgs* args = (ReadCodeColorBufferToTreeArgs*)extraData; + + int lengthOfNodeCode = numberOfThreeBitSectionsInCode(node->getOctalCode()); + + // Since we traverse the tree in code order, we know that if our code + // matches, then we've reached our target node. + if (lengthOfNodeCode == args->lengthOfCode) { + // we've reached our target -- we might have found our node, but that node might have children. + // in this case, we only allow you to set the color if you explicitly asked for a destructive + // write. + if (!node->isLeaf() && args->destructive) { + // if it does exist, make sure it has no children + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + node->deleteChildAtIndex(i); + } + } else { + if (!node->isLeaf()) { + printLog("WARNING! operation would require deleting children, add Voxel ignored!\n "); } } + + // If we get here, then it means, we either had a true leaf to begin with, or we were in + // destructive mode and we deleted all the child trees. So we can color. + if (node->isLeaf()) { + // give this node its color + int octalCodeBytes = bytesRequiredForCodeLength(args->lengthOfCode); + + nodeColor newColor; + memcpy(newColor, args->codeColorBuffer + octalCodeBytes, SIZE_OF_COLOR_DATA); + newColor[SIZE_OF_COLOR_DATA] = 1; + node->setColor(newColor); + + // It's possible we just reset the node to it's exact same color, in + // which case we don't consider this to be dirty... + if (node->isDirty()) { + // track our tree dirtiness + _isDirty = true; + // track that path has changed + args->pathChanged = true; + } + } + return; } - if (lastCreatedNode->isLeaf()) { - // give this node its color - int octalCodeBytes = bytesRequiredForCodeLength(*codeColorBuffer); + // Ok, we know we haven't reached our target node yet, so keep looking + int childIndex = branchIndexWithDescendant(node->getOctalCode(), args->codeColorBuffer); + VoxelNode* childNode = node->getChildAtIndex(childIndex); + + // If the branch we need to traverse does not exist, then create it on the way down... + if (!childNode) { + childNode = node->addChildAtIndex(childIndex); + } - nodeColor newColor; - memcpy(newColor, codeColorBuffer + octalCodeBytes, 3); - newColor[3] = 1; - lastCreatedNode->setColor(newColor); - if (lastCreatedNode->isDirty()) { - _isDirty = true; - } + // recurse... + readCodeColorBufferToTreeRecursion(childNode, args); + + // Unwinding... + + // If the lower level did some work, then we need to track our lastChanged status. + if (args->pathChanged) { + node->markWithChangedTime(); } } void VoxelTree::processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes) { //unsigned short int itemNumber = (*((unsigned short int*)&bitstream[sizeof(PACKET_HEADER)])); int atByte = sizeof(short int) + sizeof(PACKET_HEADER); - unsigned char* pVoxelData = (unsigned char*)&bitstream[atByte]; + unsigned char* voxelCode = (unsigned char*)&bitstream[atByte]; while (atByte < bufferSizeBytes) { - unsigned char octets = (unsigned char)*pVoxelData; - int voxelDataSize = bytesRequiredForCodeLength(octets)+3; // 3 for color! + int codeLength = numberOfThreeBitSectionsInCode(voxelCode); + int voxelDataSize = bytesRequiredForCodeLength(codeLength) + SIZE_OF_COLOR_DATA; - deleteVoxelCodeFromTree(pVoxelData, ACTUALLY_DELETE, COLLAPSE_EMPTY_TREE); + deleteVoxelCodeFromTree(voxelCode, ACTUALLY_DELETE, COLLAPSE_EMPTY_TREE); - pVoxelData+=voxelDataSize; + voxelCode+=voxelDataSize; atByte+=voxelDataSize; } reaverageVoxelColors(rootNode); // Fix our colors!! Need to call it on rootNode diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 16aad9b72b..1158596527 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -101,6 +101,7 @@ public: private: void deleteVoxelCodeFromTreeRecursion(VoxelNode* node, void* extraData); + void readCodeColorBufferToTreeRecursion(VoxelNode* node, void* extraData); int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag,