diff --git a/libraries/shared/src/PointerStack.cpp b/libraries/shared/src/PointerStack.cpp new file mode 100644 index 0000000000..2098312298 --- /dev/null +++ b/libraries/shared/src/PointerStack.cpp @@ -0,0 +1,42 @@ +// +// PointerStack.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 5/11/2013 +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include "PointerStack.h" +#include + +PointerStack::~PointerStack() { + deleteAll(); +} + +void PointerStack::deleteAll() { + if (_elements) { + delete[] _elements; + } + _elements = NULL; + _elementsInUse = 0; + _sizeOfElementsArray = 0; +} + +const int GROW_BY = 100; + +void PointerStack::growAndPush(void* element) { + //printf("PointerStack::growAndPush() _sizeOfElementsArray=%d",_sizeOfElementsArray); + void** oldElements = _elements; + _elements = new void* [_sizeOfElementsArray + GROW_BY]; + _sizeOfElementsArray += GROW_BY; + + // If we had an old stack... + if (oldElements) { + // copy old elements into the new stack + memcpy(_elements, oldElements, _elementsInUse * sizeof(void*)); + delete[] oldElements; + } + _elements[_elementsInUse] = element; + _elementsInUse++; +} + diff --git a/libraries/shared/src/PointerStack.h b/libraries/shared/src/PointerStack.h new file mode 100644 index 0000000000..a9066c54fc --- /dev/null +++ b/libraries/shared/src/PointerStack.h @@ -0,0 +1,59 @@ +// +// PointerStack.h +// hifi +// +// Created by Brad Hefta-Gaub on 4/25/2013 +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// +// + +#ifndef __hifi__PointerStack__ +#define __hifi__PointerStack__ + +#include // for NULL + +class PointerStack { + +public: + PointerStack() : + _elements(NULL), + _elementsInUse(0), + _sizeOfElementsArray(0) {}; + + ~PointerStack(); + + void push(void* element) { + if (_sizeOfElementsArray < _elementsInUse + 1) { + return growAndPush(element); + } + _elements[_elementsInUse] = element; + _elementsInUse++; + }; + + void* pop() { + if (_elementsInUse) { + // get the last element + void* element = _elements[_elementsInUse - 1]; + // reduce the count + _elementsInUse--; + return element; + } + return NULL; + }; + + + void* top() const { return (_elementsInUse) ? _elements[_elementsInUse - 1] : NULL; } + bool isEmpty() const { return (_elementsInUse == 0); }; + bool empty() const { return (_elementsInUse == 0); }; + int count() const { return _elementsInUse; }; + int size() const { return _elementsInUse; }; + +private: + void growAndPush(void* element); + void deleteAll(); + void** _elements; + int _elementsInUse; + int _sizeOfElementsArray; +}; + +#endif /* defined(__hifi__PointerStack__) */ diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 0120c7bfe1..f7da5f443f 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -115,7 +115,7 @@ VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char } } -int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, int bytesLeftToRead) { +int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, int bytesLeftToRead, bool includeColor) { // instantiate variable for bytes already read int bytesRead = 1; for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { @@ -133,9 +133,11 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, } // pull the color for this child - nodeColor newColor; - memcpy(newColor, nodeData + bytesRead, 3); - newColor[3] = 1; + nodeColor newColor = { 128, 128, 128, 1}; + if (includeColor) { + memcpy(newColor, nodeData + bytesRead, 3); + bytesRead += 3; + } bool nodeWasDirty = destinationNode->getChildAtIndex(i)->isDirty(); destinationNode->getChildAtIndex(i)->setColor(newColor); bool nodeIsDirty = destinationNode->getChildAtIndex(i)->isDirty(); @@ -147,8 +149,6 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, } this->voxelsColored++; this->voxelsColoredStats.updateAverage(1); - - bytesRead += 3; } } @@ -180,7 +180,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, // tell the child to read the subsequent data bytesRead += readNodeData(destinationNode->getChildAtIndex(childIndex), nodeData + bytesRead, - bytesLeftToRead - bytesRead); + bytesLeftToRead - bytesRead, includeColor); } childIndex++; @@ -189,7 +189,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, return bytesRead; } -void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes) { +void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, bool includeColor) { int bytesRead = 0; unsigned char* bitstreamAt = bitstream; @@ -218,7 +218,7 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int int theseBytesRead = 0; theseBytesRead += octalCodeBytes; theseBytesRead += readNodeData(bitstreamRootNode, bitstreamAt + octalCodeBytes, - bufferSizeBytes - (bytesRead + octalCodeBytes)); + bufferSizeBytes - (bytesRead + octalCodeBytes), includeColor); // skip bitstream to new startPoint bitstreamAt += theseBytesRead; @@ -719,7 +719,7 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe } int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes, - VoxelNodeBag& bag, const ViewFrustum* viewFrustum) const { + VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor) const { // How many bytes have we written so far at this level; int bytesWritten = 0; @@ -739,14 +739,14 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned int currentEncodeLevel = 0; int childBytesWritten = encodeTreeBitstreamRecursion(maxEncodeLevel, currentEncodeLevel, - node, outputBuffer, availableBytes, bag, viewFrustum); + node, outputBuffer, availableBytes, bag, viewFrustum, includeColor); // if childBytesWritten == 1 then something went wrong... that's not possible assert(childBytesWritten != 1); - // if childBytesWritten == 2, then it can only mean that the lower level trees don't exist or for some reason - // couldn't be written... so reset them here... - if (childBytesWritten == 2) { + // if includeColor and childBytesWritten == 2, then it can only mean that the lower level trees don't exist or for some reason + // couldn't be written... so reset them here... This isn't true for the non-color included case + if (includeColor && childBytesWritten == 2) { childBytesWritten = 0; } @@ -762,7 +762,7 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes, - VoxelNodeBag& bag, const ViewFrustum* viewFrustum) const { + VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor) const { // How many bytes have we written so far at this level; int bytesAtThisLevel = 0; @@ -847,11 +847,13 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco bytesAtThisLevel += sizeof(childrenColoredBits); // keep track of byte count // write the color data... - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - if (oneAtBit(childrenColoredBits, i)) { - memcpy(writeToThisLevelBuffer, &node->getChildAtIndex(i)->getColor(), BYTES_PER_COLOR); - writeToThisLevelBuffer += BYTES_PER_COLOR; // move the pointer for color - bytesAtThisLevel += BYTES_PER_COLOR; // keep track of byte count for color + if (includeColor) { + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + if (oneAtBit(childrenColoredBits, i)) { + memcpy(writeToThisLevelBuffer, &node->getChildAtIndex(i)->getColor(), BYTES_PER_COLOR); + writeToThisLevelBuffer += BYTES_PER_COLOR; // move the pointer for color + bytesAtThisLevel += BYTES_PER_COLOR; // keep track of byte count for color + } } } // write the child exist bits @@ -894,7 +896,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco int thisLevel = currentEncodeLevel; int childTreeBytesOut = encodeTreeBitstreamRecursion(maxEncodeLevel, thisLevel, childNode, - outputBuffer, availableBytes, bag, viewFrustum); + outputBuffer, availableBytes, bag, + viewFrustum, includeColor); // if the child wrote 0 bytes, it means that nothing below exists or was in view, or we ran out of space, // basically, the children below don't contain any info. @@ -912,7 +915,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco // so, if the child returns 2 bytes out, we can actually consider that an empty tree also!! // // we can make this act like no bytes out, by just resetting the bytes out in this case - if (childTreeBytesOut == 2) { + if (includeColor && childTreeBytesOut == 2) { childTreeBytesOut = 0; // this is the degenerate case of a tree with no colors and no child trees } @@ -947,7 +950,7 @@ bool VoxelTree::readFromFileV2(const char* fileName) { // read the entire file into a buffer, WHAT!? Why not. unsigned char* entireFile = new unsigned char[fileLength]; file.read((char*)entireFile, fileLength); - readBitstreamToTree(entireFile, fileLength); + readBitstreamToTree(entireFile, fileLength, true); delete[] entireFile; file.close(); @@ -971,7 +974,8 @@ void VoxelTree::writeToFileV2(const char* fileName) const { while (!nodeBag.isEmpty()) { VoxelNode* subTree = nodeBag.extract(); - bytesWritten = encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, nodeBag, NULL); + bytesWritten = encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0], + MAX_VOXEL_PACKET_SIZE - 1, nodeBag, NULL, true); file.write((const char*)&outputBuffer[0], bytesWritten); } diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 8cecff035d..fc3b44f413 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -40,7 +40,7 @@ public: void eraseAllVoxels(); void processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes); - void readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes); + void readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, bool includeColor = true); void readCodeColorBufferToTree(unsigned char *codeColorBuffer); void deleteVoxelCodeFromTree(unsigned char *codeBuffer); void printTreeForDebugging(VoxelNode *startNode); @@ -55,7 +55,7 @@ public: void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL); int encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes, - VoxelNodeBag& bag, const ViewFrustum* viewFrustum) const; + VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor = true) const; int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag); @@ -79,7 +79,7 @@ public: private: int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes, - VoxelNodeBag& bag, const ViewFrustum* viewFrustum) const; + VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor) const; int searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag); @@ -89,7 +89,7 @@ private: void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData); VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const; VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate); - int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes); + int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes, bool includeColor = true); bool _isDirty; unsigned long int _nodesChangedFromBitstream;