mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 18:44:00 +02:00
change the loadBitstreamBuffer method to accommodate absence of childMask variable
This commit is contained in:
parent
9cd314d3c4
commit
287775e0f9
2 changed files with 211 additions and 127 deletions
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue