Added PointerStack class, and implemented support for monochrome in VoxelTree

This commit is contained in:
ZappoMan 2013-05-13 09:57:36 -07:00
parent af7057619a
commit 777dd6dc53
4 changed files with 133 additions and 28 deletions

View file

@ -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 <stdio.h>
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++;
}

View file

@ -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 <cstring> // 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__) */

View file

@ -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);
}

View file

@ -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;