mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 18:01:15 +02:00
Added PointerStack class, and implemented support for monochrome in VoxelTree
This commit is contained in:
parent
af7057619a
commit
777dd6dc53
4 changed files with 133 additions and 28 deletions
42
libraries/shared/src/PointerStack.cpp
Normal file
42
libraries/shared/src/PointerStack.cpp
Normal 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++;
|
||||||
|
}
|
||||||
|
|
59
libraries/shared/src/PointerStack.h
Normal file
59
libraries/shared/src/PointerStack.h
Normal 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__) */
|
|
@ -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
|
// instantiate variable for bytes already read
|
||||||
int bytesRead = 1;
|
int bytesRead = 1;
|
||||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
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
|
// pull the color for this child
|
||||||
nodeColor newColor;
|
nodeColor newColor = { 128, 128, 128, 1};
|
||||||
memcpy(newColor, nodeData + bytesRead, 3);
|
if (includeColor) {
|
||||||
newColor[3] = 1;
|
memcpy(newColor, nodeData + bytesRead, 3);
|
||||||
|
bytesRead += 3;
|
||||||
|
}
|
||||||
bool nodeWasDirty = destinationNode->getChildAtIndex(i)->isDirty();
|
bool nodeWasDirty = destinationNode->getChildAtIndex(i)->isDirty();
|
||||||
destinationNode->getChildAtIndex(i)->setColor(newColor);
|
destinationNode->getChildAtIndex(i)->setColor(newColor);
|
||||||
bool nodeIsDirty = destinationNode->getChildAtIndex(i)->isDirty();
|
bool nodeIsDirty = destinationNode->getChildAtIndex(i)->isDirty();
|
||||||
|
@ -147,8 +149,6 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData,
|
||||||
}
|
}
|
||||||
this->voxelsColored++;
|
this->voxelsColored++;
|
||||||
this->voxelsColoredStats.updateAverage(1);
|
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
|
// tell the child to read the subsequent data
|
||||||
bytesRead += readNodeData(destinationNode->getChildAtIndex(childIndex),
|
bytesRead += readNodeData(destinationNode->getChildAtIndex(childIndex),
|
||||||
nodeData + bytesRead,
|
nodeData + bytesRead,
|
||||||
bytesLeftToRead - bytesRead);
|
bytesLeftToRead - bytesRead, includeColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
childIndex++;
|
childIndex++;
|
||||||
|
@ -189,7 +189,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData,
|
||||||
return bytesRead;
|
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;
|
int bytesRead = 0;
|
||||||
unsigned char* bitstreamAt = bitstream;
|
unsigned char* bitstreamAt = bitstream;
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int
|
||||||
int theseBytesRead = 0;
|
int theseBytesRead = 0;
|
||||||
theseBytesRead += octalCodeBytes;
|
theseBytesRead += octalCodeBytes;
|
||||||
theseBytesRead += readNodeData(bitstreamRootNode, bitstreamAt + octalCodeBytes,
|
theseBytesRead += readNodeData(bitstreamRootNode, bitstreamAt + octalCodeBytes,
|
||||||
bufferSizeBytes - (bytesRead + octalCodeBytes));
|
bufferSizeBytes - (bytesRead + octalCodeBytes), includeColor);
|
||||||
|
|
||||||
// skip bitstream to new startPoint
|
// skip bitstream to new startPoint
|
||||||
bitstreamAt += theseBytesRead;
|
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,
|
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;
|
// How many bytes have we written so far at this level;
|
||||||
int bytesWritten = 0;
|
int bytesWritten = 0;
|
||||||
|
@ -739,14 +739,14 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned
|
||||||
|
|
||||||
int currentEncodeLevel = 0;
|
int currentEncodeLevel = 0;
|
||||||
int childBytesWritten = encodeTreeBitstreamRecursion(maxEncodeLevel, currentEncodeLevel,
|
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
|
// if childBytesWritten == 1 then something went wrong... that's not possible
|
||||||
assert(childBytesWritten != 1);
|
assert(childBytesWritten != 1);
|
||||||
|
|
||||||
// if childBytesWritten == 2, then it can only mean that the lower level trees don't exist or for some reason
|
// 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...
|
// couldn't be written... so reset them here... This isn't true for the non-color included case
|
||||||
if (childBytesWritten == 2) {
|
if (includeColor && childBytesWritten == 2) {
|
||||||
childBytesWritten = 0;
|
childBytesWritten = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,7 +762,7 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned
|
||||||
|
|
||||||
int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
||||||
VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
|
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;
|
// How many bytes have we written so far at this level;
|
||||||
int bytesAtThisLevel = 0;
|
int bytesAtThisLevel = 0;
|
||||||
|
|
||||||
|
@ -847,11 +847,13 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
||||||
bytesAtThisLevel += sizeof(childrenColoredBits); // keep track of byte count
|
bytesAtThisLevel += sizeof(childrenColoredBits); // keep track of byte count
|
||||||
|
|
||||||
// write the color data...
|
// write the color data...
|
||||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
if (includeColor) {
|
||||||
if (oneAtBit(childrenColoredBits, i)) {
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
memcpy(writeToThisLevelBuffer, &node->getChildAtIndex(i)->getColor(), BYTES_PER_COLOR);
|
if (oneAtBit(childrenColoredBits, i)) {
|
||||||
writeToThisLevelBuffer += BYTES_PER_COLOR; // move the pointer for color
|
memcpy(writeToThisLevelBuffer, &node->getChildAtIndex(i)->getColor(), BYTES_PER_COLOR);
|
||||||
bytesAtThisLevel += BYTES_PER_COLOR; // keep track of byte count for 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
|
// write the child exist bits
|
||||||
|
@ -894,7 +896,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
||||||
|
|
||||||
int thisLevel = currentEncodeLevel;
|
int thisLevel = currentEncodeLevel;
|
||||||
int childTreeBytesOut = encodeTreeBitstreamRecursion(maxEncodeLevel, thisLevel, childNode,
|
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,
|
// 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.
|
// 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!!
|
// 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
|
// 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
|
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.
|
// read the entire file into a buffer, WHAT!? Why not.
|
||||||
unsigned char* entireFile = new unsigned char[fileLength];
|
unsigned char* entireFile = new unsigned char[fileLength];
|
||||||
file.read((char*)entireFile, fileLength);
|
file.read((char*)entireFile, fileLength);
|
||||||
readBitstreamToTree(entireFile, fileLength);
|
readBitstreamToTree(entireFile, fileLength, true);
|
||||||
delete[] entireFile;
|
delete[] entireFile;
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
@ -971,7 +974,8 @@ void VoxelTree::writeToFileV2(const char* fileName) const {
|
||||||
|
|
||||||
while (!nodeBag.isEmpty()) {
|
while (!nodeBag.isEmpty()) {
|
||||||
VoxelNode* subTree = nodeBag.extract();
|
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);
|
file.write((const char*)&outputBuffer[0], bytesWritten);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ public:
|
||||||
void eraseAllVoxels();
|
void eraseAllVoxels();
|
||||||
|
|
||||||
void processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes);
|
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 readCodeColorBufferToTree(unsigned char *codeColorBuffer);
|
||||||
void deleteVoxelCodeFromTree(unsigned char *codeBuffer);
|
void deleteVoxelCodeFromTree(unsigned char *codeBuffer);
|
||||||
void printTreeForDebugging(VoxelNode *startNode);
|
void printTreeForDebugging(VoxelNode *startNode);
|
||||||
|
@ -55,7 +55,7 @@ public:
|
||||||
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
|
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
|
||||||
|
|
||||||
int encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
|
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);
|
int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag);
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ public:
|
||||||
private:
|
private:
|
||||||
int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
||||||
VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
|
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,
|
int searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel,
|
||||||
VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag);
|
VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag);
|
||||||
|
@ -89,7 +89,7 @@ private:
|
||||||
void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData);
|
void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData);
|
||||||
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const;
|
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const;
|
||||||
VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate);
|
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;
|
bool _isDirty;
|
||||||
unsigned long int _nodesChangedFromBitstream;
|
unsigned long int _nodesChangedFromBitstream;
|
||||||
|
|
Loading…
Reference in a new issue