change the loadBitstreamBuffer method to accommodate absence of childMask variable

This commit is contained in:
Stephen Birarda 2013-03-28 14:35:45 -07:00
parent 9cd314d3c4
commit 287775e0f9
2 changed files with 211 additions and 127 deletions

View file

@ -12,10 +12,35 @@
#include "OctalCode.h"
#include "VoxelTree.h"
const int TREE_SCALE = 10;
int boundaryDistanceForRenderLevel(unsigned int renderLevel) {
switch (renderLevel) {
case 1:
return 100;
break;
case 2:
return 50;
break;
case 3:
return 25;
break;
case 4:
return 12;
break;
case 5:
return 6;
break;
default:
return 3;
break;
}
}
VoxelTree::VoxelTree() {
rootNode = new VoxelNode();
rootNode->octalCode = new unsigned char[1];
*rootNode->octalCode = (char)0;
*rootNode->octalCode = 0;
}
VoxelTree::~VoxelTree() {
@ -26,22 +51,6 @@ VoxelTree::~VoxelTree() {
}
}
int VoxelTree::levelForViewerPosition(float *position) {
// get the distance to the viewer
// for now the voxel tree starts at 0,0,0
float distance = sqrtf(powf(position[0] + 30, 2) + powf(position[2] + 30, 2));
// go through the if else branch to return the right level
// this is a gross way to do this for now for a friday demo
if (distance >= 50) {
return 3;
} else if (distance >= 20) {
return 4;
} else {
return 5;
}
}
VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode) {
// find the appropriate branch index based on this ancestorNode
if (*needleCode > 0) {
@ -77,45 +86,39 @@ VoxelNode * VoxelTree::createMissingNode(VoxelNode *lastParentNode, unsigned cha
}
}
/// If node has color & <= 4 children then prune children
// if node has color & <= 4 children then prune children
void VoxelTree::pruneTree(VoxelNode* pruneAt) {
int childCount = 0;
// determine how many children we have
for (int i = 0; i < 8; i++)
{
if (pruneAt->children[i])
{
for (int i = 0; i < 8; i++) {
if (pruneAt->children[i]) {
childCount++;
}
}
// if appropriate, prune them
if (pruneAt->color[3] && childCount <= 4)
{
for (int i = 0; i < 8; i++)
{
if (pruneAt->children[i])
{
if (pruneAt->color[3] && childCount <= 4) {
for (int i = 0; i < 8; i++) {
if (pruneAt->children[i]) {
delete pruneAt->children[i];
pruneAt->children[i]=NULL;
}
}
}
else
{
} else {
// Otherwise, iterate the children and recursively call
// prune on all of them
for (int i = 0; i < 8; i++)
{
if (pruneAt->children[i])
{
for (int i = 0; i < 8; i++) {
if (pruneAt->children[i]) {
this->pruneTree(pruneAt->children[i]);
}
}
}
}
int VoxelTree::readNodeData(VoxelNode *destinationNode, unsigned char * nodeData, int bytesLeftToRead) {
int VoxelTree::readNodeData(VoxelNode *destinationNode,
unsigned char * nodeData,
int bytesLeftToRead) {
// instantiate variable for bytes already read
int bytesRead = 1;
@ -147,7 +150,7 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode, unsigned char * nodeData
destinationNode->setColorFromAverageOfChildren(colorArray);
// give this destination node the child mask from the packet
destinationNode->childMask = *(nodeData + bytesRead);
unsigned char childMask = *(nodeData + bytesRead);
int childIndex = 0;
bytesRead++;
@ -155,14 +158,16 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode, unsigned char * nodeData
while (bytesLeftToRead - bytesRead > 0 && childIndex < 8) {
// check the exists mask to see if we have a child to traverse into
if (oneAtBit(destinationNode->childMask, childIndex)) {
if (oneAtBit(childMask, childIndex)) {
if (destinationNode->children[childIndex] == NULL) {
// add a child at that index, if it doesn't exist
destinationNode->addChildAtIndex(childIndex);
}
// tell the child to read the subsequent data
bytesRead += readNodeData(destinationNode->children[childIndex], nodeData + bytesRead, bytesLeftToRead - bytesRead);
bytesRead += readNodeData(destinationNode->children[childIndex],
nodeData + bytesRead,
bytesLeftToRead - bytesRead);
}
childIndex++;
@ -200,97 +205,164 @@ void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer) {
}
unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
unsigned char * stopOctalCode,
VoxelNode *currentVoxelNode,
int deepestLevel)
MarkerNode *currentMarkerNode,
float * agentPosition,
float thisNodePosition[3],
unsigned char * stopOctalCode)
{
static unsigned char *initialBitstreamPos = bitstreamBuffer;
int firstIndexToCheck = 0;
// we'll only be writing data if we're lower than
// or at the same level as the stopOctalCode
if (*currentVoxelNode->octalCode >= *stopOctalCode) {
if ((bitstreamBuffer - initialBitstreamPos) + MAX_TREE_SLICE_BYTES > MAX_VOXEL_PACKET_SIZE) {
// we can't send this packet, not enough room
// return our octal code as the stop
return currentVoxelNode->octalCode;
}
if (strcmp((char *)stopOctalCode, (char *)currentVoxelNode->octalCode) == 0) {
// this is is the root node for this packet
// add the leading V
*(bitstreamBuffer++) = 'V';
// add its octal code to the packet
int octalCodeBytes = bytesRequiredForCodeLength(*currentVoxelNode->octalCode);
memcpy(bitstreamBuffer, currentVoxelNode->octalCode, octalCodeBytes);
bitstreamBuffer += octalCodeBytes;
}
// default color mask is 0, increment pointer for colors
*bitstreamBuffer = 0;
// keep a colorPointer so we can check how many colors were added
unsigned char *colorPointer = bitstreamBuffer + 1;
for (int i = 0; i < 8; i++) {
// check if the child exists and is not transparent
if (currentVoxelNode->children[i] != NULL
&& currentVoxelNode->children[i]->color[3] != 0) {
// copy in the childs color to bitstreamBuffer
memcpy(colorPointer, currentVoxelNode->children[i]->color, 3);
colorPointer += 3;
// set the colorMask by bitshifting the value of childExists
*bitstreamBuffer += (1 << (7 - i));
}
}
// push the bitstreamBuffer forwards for the number of added colors
bitstreamBuffer += (colorPointer - bitstreamBuffer);
// copy the childMask to the current position of the bitstreamBuffer
// and push the buffer pointer forwards
*(bitstreamBuffer++) = *currentVoxelNode->octalCode < deepestLevel - 1
? currentVoxelNode->childMask
: 0;
} else {
firstIndexToCheck = *stopOctalCode > 0
? branchIndexWithDescendant(currentVoxelNode->octalCode, stopOctalCode)
: 0;
}
unsigned char * childStopOctalCode = NULL;
if (currentVoxelNode->childMask == 0) {
leavesWrittenToBitstream++;
if (stopOctalCode == NULL) {
stopOctalCode = rootNode->octalCode;
}
if (*currentVoxelNode->octalCode < deepestLevel - 1) {
for (int i = firstIndexToCheck; i < 8; i ++) {
// check if we have any children
bool hasAtLeastOneChild;
for (int i = 0; i < 8; i++) {
if (currentVoxelNode->children[i] != NULL) {
hasAtLeastOneChild = true;
}
}
// if we have at least one child, check if it will be worth recursing into our children
if (hasAtLeastOneChild) {
int firstIndexToCheck = 0;
unsigned char * childMaskPointer = NULL;
float halfUnitForVoxel = powf(0.5, *currentVoxelNode->octalCode) * (0.5 * TREE_SCALE);
float distanceToVoxelCenter = sqrtf(powf(agentPosition[0] - thisNodePosition[0] - halfUnitForVoxel, 2) +
powf(agentPosition[1] - thisNodePosition[1] - halfUnitForVoxel, 2) +
powf(agentPosition[2] - thisNodePosition[2] - halfUnitForVoxel, 2));
// if the distance to this voxel's center is less than the threshold
// distance for its children, we should send the children
if (distanceToVoxelCenter < boundaryDistanceForRenderLevel(*currentVoxelNode->octalCode + 1)) {
// ask the child to load this bitstream buffer
// if they or their descendants fill the MTU we will receive the childStopOctalCode back
if (currentVoxelNode->children[i] != NULL) {
if (*currentVoxelNode->octalCode < *stopOctalCode
&& i > firstIndexToCheck
&& childStopOctalCode == NULL) {
return currentVoxelNode->children[i]->octalCode;
} else {
if (oneAtBit(currentVoxelNode->childMask, i)) {
childStopOctalCode = loadBitstreamBuffer(bitstreamBuffer, stopOctalCode, currentVoxelNode->children[i], deepestLevel);
} else {
childStopOctalCode = NULL;
// write this voxel's data if we're below or at
// or at the same level as the stopOctalCode
if (*currentVoxelNode->octalCode >= *stopOctalCode) {
if ((bitstreamBuffer - initialBitstreamPos) + MAX_TREE_SLICE_BYTES > MAX_VOXEL_PACKET_SIZE) {
// we can't send this packet, not enough room
// return our octal code as the stop
return currentVoxelNode->octalCode;
}
if (strcmp((char *)stopOctalCode, (char *)currentVoxelNode->octalCode) == 0) {
// this is is the root node for this packet
// add the leading V
*(bitstreamBuffer++) = 'V';
// add its octal code to the packet
int octalCodeBytes = bytesRequiredForCodeLength(*currentVoxelNode->octalCode);
memcpy(bitstreamBuffer, currentVoxelNode->octalCode, octalCodeBytes);
bitstreamBuffer += octalCodeBytes;
}
// default color mask is 0, increment pointer for colors
*bitstreamBuffer = 0;
// keep a colorPointer so we can check how many colors were added
unsigned char *colorPointer = bitstreamBuffer + 1;
for (int i = 0; i < 8; i++) {
// check if the child exists and is not transparent
if (currentVoxelNode->children[i] != NULL
&& currentVoxelNode->children[i]->color[3] != 0) {
// copy in the childs color to bitstreamBuffer
memcpy(colorPointer, currentVoxelNode->children[i]->color, 3);
colorPointer += 3;
// set the colorMask by bitshifting the value of childExists
*bitstreamBuffer += (1 << (7 - i));
}
}
}
// push the bitstreamBuffer forwards for the number of added colors
bitstreamBuffer += (colorPointer - bitstreamBuffer);
// maintain a pointer to this spot in the buffer so we can set our child mask
// depending on the results of the recursion below
childMaskPointer = bitstreamBuffer++;
// reset the childMaskPointer for this node to 0
*childMaskPointer = 0;
} else {
firstIndexToCheck = *stopOctalCode > 0
? branchIndexWithDescendant(currentVoxelNode->octalCode, stopOctalCode)
: 0;
}
if (childStopOctalCode != NULL) {
break;
unsigned char * arrBufferBeforeChild = bitstreamBuffer;
for (int i = firstIndexToCheck; i < 8; i ++) {
// ask the child to load this bitstream buffer
// if they or their descendants fill the MTU we will receive the childStopOctalCode back
if (currentVoxelNode->children[i] != NULL) {
if (!oneAtBit(currentMarkerNode->childrenVisitedMask, i)) {
// create the marker node for this child if it does not yet exist
if (currentMarkerNode->children[i] == NULL) {
currentMarkerNode->children[i] = new MarkerNode();
}
// calculate the child's position based on the parent position
float childNodePosition[3];
for (int j = 0; j < 3; j++) {
childNodePosition[j] = thisNodePosition[j];
if (oneAtBit(branchIndexWithDescendant(currentVoxelNode->octalCode,
currentVoxelNode->children[i]->octalCode),
(7 - j))) {
childNodePosition[j] -= (powf(0.5, *currentVoxelNode->children[i]->octalCode) * TREE_SCALE);
}
}
// ask the child to load the bitstream buffer with their data
childStopOctalCode = loadBitstreamBuffer(bitstreamBuffer,
currentVoxelNode->children[i],
currentMarkerNode->children[i],
agentPosition,
childNodePosition,
stopOctalCode);
if (bitstreamBuffer - arrBufferBeforeChild > 0) {
// this child added data to the packet - add it to our child mask
if (childMaskPointer != NULL) {
*childMaskPointer += (1 << (7 - i));
}
arrBufferBeforeChild = bitstreamBuffer;
}
}
}
if (childStopOctalCode != NULL) {
break;
} else {
// this child node has been covered
// add the appropriate bit to the childrenVisitedMask for the current marker node
currentMarkerNode->childrenVisitedMask += 1 << (7 - i);
// if we are above the stopOctal and we got a NULL code
// we cannot go to the next child
// so break and return the NULL stop code
if (*currentVoxelNode->octalCode < *stopOctalCode) {
break;
}
}
}
}
}
@ -319,13 +391,23 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
}
}
outputBits(startNode->childMask);
unsigned char childMask = 0;
// ask children to recursively output their trees
// if they aren't a leaf
for (int k = 0; k < 8; k++) {
if (startNode->children[k] != NULL) {
printTreeForDebugging(startNode->children[k]);
childMask += (1 << (7 - k));
}
}
outputBits(childMask);
if (childMask > 0) {
// ask children to recursively output their trees
// if they aren't a leaf
for (int l = 0; l < 8; l++) {
if (startNode->children[l] != NULL) {
printTreeForDebugging(startNode->children[l]);
}
}
}
}

View file

@ -11,6 +11,7 @@
#include <iostream>
#include "VoxelNode.h"
#include "MarkerNode.h"
const int MAX_VOXEL_PACKET_SIZE = 1492;
const int MAX_TREE_SLICE_BYTES = 26;
@ -26,14 +27,15 @@ public:
VoxelNode *rootNode;
int leavesWrittenToBitstream;
int levelForViewerPosition(float * position);
void readBitstreamToTree(unsigned char * bitstream, int bufferSizeBytes);
void readCodeColorBufferToTree(unsigned char *codeColorBuffer);
unsigned char * loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
unsigned char * octalCode,
VoxelNode *currentVoxelNode,
int deepestLevel);
void printTreeForDebugging(VoxelNode *startNode);
unsigned char * loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
VoxelNode *currentVoxelNode,
MarkerNode *currentMarkerNode,
float * agentPosition,
float thisNodePosition[3],
unsigned char * octalCode = NULL);
void pruneTree(VoxelNode* pruneAt);
};