mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 10:55:41 +02:00
Code cleanup, change readBitstreamToTree() to support multiple trees, first cut at new loadBitstream()
- some small tweaks to cod to match coding standard for pointers - changed readBitstreamToTree() to handle multiple trees in a single packet - first cut at new version of loadBitstream() which is currently not in use
This commit is contained in:
parent
9bc2f667b6
commit
785ef88820
2 changed files with 362 additions and 41 deletions
|
@ -5,6 +5,48 @@
|
|||
// Created by Stephen Birarda on 3/13/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Oct-Tree in bits, and child ordinals
|
||||
//
|
||||
// Location Decimal Bit Child in Array
|
||||
// ------------------- ------- --- ---------------
|
||||
// Bottom Right Near 128 8th 0
|
||||
// Bottom Right Far 64 7th 1
|
||||
// Top Right Near 32 6th 2
|
||||
// Top Right Far 16 5th 3
|
||||
// Bottom Left Near 8 4th 4
|
||||
// Bottom Left Far 4 3rd 5
|
||||
// Top Left Near 2 2nd 6
|
||||
// Top Left Far 1 1st 7
|
||||
//
|
||||
// ^
|
||||
// +-------|------+ + Y
|
||||
// / / | /|
|
||||
// / 1 / | 16 / |
|
||||
// /------/-------+ |
|
||||
// / / | /|16|
|
||||
// / 2 / 32 | / | |
|
||||
// / / |/ | /| / +Z
|
||||
// +--------------+ 32|/ | /
|
||||
// | | | / | /
|
||||
// | | | /| | /
|
||||
// | 2 | 32 | / |64| /
|
||||
// 4----| | |/ | |/
|
||||
// +------|------ + | /
|
||||
// | | | | /
|
||||
// | | |128|/
|
||||
// | 8 | 128 | /
|
||||
// | | | /
|
||||
// | | | /
|
||||
// < - - - +------+-------+/ - - - - - - >
|
||||
// +X (0,0,0) -X
|
||||
// /|
|
||||
// / |
|
||||
// / |
|
||||
// -Z / V -Y
|
||||
//
|
||||
//
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _USE_MATH_DEFINES
|
||||
|
@ -117,12 +159,14 @@ VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char *
|
|||
return ancestorNode;
|
||||
}
|
||||
|
||||
VoxelNode * VoxelTree::createMissingNode(VoxelNode *lastParentNode, unsigned char *codeToReach) {
|
||||
// returns the node created!
|
||||
VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char* codeToReach) {
|
||||
|
||||
int indexOfNewChild = branchIndexWithDescendant(lastParentNode->octalCode, codeToReach);
|
||||
lastParentNode->addChildAtIndex(indexOfNewChild);
|
||||
|
||||
|
||||
if (*lastParentNode->children[indexOfNewChild]->octalCode == *codeToReach) {
|
||||
return lastParentNode;
|
||||
return lastParentNode->children[indexOfNewChild];
|
||||
} else {
|
||||
return createMissingNode(lastParentNode->children[indexOfNewChild], codeToReach);
|
||||
}
|
||||
|
@ -134,24 +178,24 @@ VoxelNode * VoxelTree::createMissingNode(VoxelNode *lastParentNode, unsigned cha
|
|||
int VoxelTree::readNodeData(VoxelNode *destinationNode,
|
||||
unsigned char * nodeData,
|
||||
int bytesLeftToRead) {
|
||||
|
||||
|
||||
// instantiate variable for bytes already read
|
||||
int bytesRead = 1;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
// check the colors mask to see if we have a child to color in
|
||||
if (oneAtBit(*nodeData, i)) {
|
||||
|
||||
// create the child if it doesn't exist
|
||||
if (destinationNode->children[i] == NULL) {
|
||||
destinationNode->addChildAtIndex(i);
|
||||
this->voxelsCreated++;
|
||||
this->voxelsCreatedStats.updateAverage(1);
|
||||
}
|
||||
|
||||
|
||||
// pull the color for this child
|
||||
nodeColor newColor;
|
||||
memcpy(newColor, nodeData + bytesRead, 3);
|
||||
newColor[3] = 1;
|
||||
|
||||
destinationNode->children[i]->setColor(newColor);
|
||||
this->voxelsColored++;
|
||||
this->voxelsColoredStats.updateAverage(1);
|
||||
|
@ -193,17 +237,33 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode,
|
|||
}
|
||||
|
||||
void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeBytes) {
|
||||
VoxelNode *bitstreamRootNode = nodeForOctalCode(rootNode, (unsigned char *)bitstream, NULL);
|
||||
int bytesRead = 0;
|
||||
|
||||
// Keep looping through the buffer calling readNodeData() this allows us to pack multiple root-relative Octal codes
|
||||
// into a single network packet. readNodeData() basically goes down a tree from the root, and fills things in from there
|
||||
// if there are more bytes after that, it's assumed to be another root relative tree
|
||||
|
||||
if (*bitstream != *bitstreamRootNode->octalCode) {
|
||||
// if the octal code returned is not on the same level as
|
||||
// the code being searched for, we have VoxelNodes to create
|
||||
bitstreamRootNode = createMissingNode(bitstreamRootNode, (unsigned char *)bitstream);
|
||||
while (bytesRead < bufferSizeBytes) {
|
||||
VoxelNode* bitstreamRootNode = nodeForOctalCode(rootNode, (unsigned char *)bitstream, NULL);
|
||||
|
||||
if (*bitstream != *bitstreamRootNode->octalCode) {
|
||||
// if the octal code returned is not on the same level as
|
||||
// the code being searched for, we have VoxelNodes to create
|
||||
|
||||
// Note: we need to create this node relative to root, because we're assuming that the bitstream for the initial
|
||||
// octal code is always relative to root!
|
||||
bitstreamRootNode = createMissingNode(rootNode, (unsigned char *)bitstream);
|
||||
}
|
||||
|
||||
int octalCodeBytes = bytesRequiredForCodeLength(*bitstream);
|
||||
|
||||
bytesRead += octalCodeBytes;
|
||||
bytesRead += readNodeData(bitstreamRootNode, bitstream + octalCodeBytes, bufferSizeBytes - octalCodeBytes);
|
||||
|
||||
// skip bitstream to new startPoint
|
||||
bitstream += bytesRead;
|
||||
}
|
||||
|
||||
int octalCodeBytes = bytesRequiredForCodeLength(*bitstream);
|
||||
readNodeData(bitstreamRootNode, bitstream + octalCodeBytes, bufferSizeBytes - octalCodeBytes);
|
||||
|
||||
this->voxelsBytesRead += bufferSizeBytes;
|
||||
this->voxelsBytesReadStats.updateAverage(bufferSizeBytes);
|
||||
}
|
||||
|
@ -247,12 +307,11 @@ void VoxelTree::eraseAllVoxels() {
|
|||
}
|
||||
|
||||
void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer) {
|
||||
VoxelNode *lastCreatedNode = nodeForOctalCode(rootNode, codeColorBuffer, NULL);
|
||||
VoxelNode* lastCreatedNode = nodeForOctalCode(rootNode, codeColorBuffer, NULL);
|
||||
|
||||
// create the node if it does not exist
|
||||
if (*lastCreatedNode->octalCode != *codeColorBuffer) {
|
||||
VoxelNode *parentNode = createMissingNode(lastCreatedNode, codeColorBuffer);
|
||||
lastCreatedNode = parentNode->children[branchIndexWithDescendant(parentNode->octalCode, codeColorBuffer)];
|
||||
lastCreatedNode = createMissingNode(lastCreatedNode, codeColorBuffer);
|
||||
}
|
||||
|
||||
// give this node its color
|
||||
|
@ -325,15 +384,13 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
|||
bool voxelIsClose = (distanceToVoxelCenter < boundaryDistanceForRenderLevel(*currentVoxelNode->octalCode + 1));
|
||||
bool sendVoxel = voxelIsClose && voxelInView;
|
||||
|
||||
//printf("VoxelTree::loadBitstreamBuffer() sendVoxel=%d, voxelIsClose=%d, voxelInView=%d, viewFrustumCulling=%d\n",
|
||||
// sendVoxel, voxelIsClose, voxelInView, viewFrustumCulling);
|
||||
|
||||
if (sendVoxel) {
|
||||
|
||||
// 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
|
||||
|
@ -359,13 +416,11 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
|||
unsigned char *colorPointer = bitstreamBuffer + 1;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
|
||||
// Rules for including a child:
|
||||
// 1) child must exists
|
||||
if ((currentVoxelNode->children[i] != NULL)) {
|
||||
// 2) child must have a color...
|
||||
if (currentVoxelNode->children[i]->isColored()) {
|
||||
|
||||
unsigned char* childOctalCode = currentVoxelNode->children[i]->octalCode;
|
||||
|
||||
float childPosition[3];
|
||||
|
@ -384,9 +439,6 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
|||
childBox.setBox(glm::vec3(childPosition[0], childPosition[1], childPosition[2]),
|
||||
fullChildVoxel, fullChildVoxel, fullChildVoxel);
|
||||
|
||||
//printf("VoxelTree::loadBitstreamBuffer() childBox.corner=(%f,%f,%f) x=%f \n",
|
||||
// childBox.getCorner().x,childBox.getCorner().y,childBox.getCorner().z, childBox.getSize().x);
|
||||
|
||||
// XXXBHG - not sure we want to do this "distance/LOD culling" at this level.
|
||||
//bool childIsClose = (distanceToChildCenter < boundaryDistanceForRenderLevel(*childOctalCode + 1));
|
||||
|
||||
|
@ -401,9 +453,6 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
|||
// removed childIsClose - until we determine if we want to include that
|
||||
bool sendChild = (childInView) || falseColorInsteadOfCulling;
|
||||
|
||||
//printf("VoxelTree::loadBitstreamBuffer() childIsClose=%d, childInView=%d\n",
|
||||
// childIsClose, childInView);
|
||||
|
||||
// if we sendAnyway, we'll do false coloring of the voxels based on childIsClose && childInView
|
||||
if (sendChild) {
|
||||
|
||||
|
@ -449,15 +498,13 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
|||
? branchIndexWithDescendant(currentVoxelNode->octalCode, stopOctalCode)
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@ -488,7 +535,7 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
|||
}
|
||||
}
|
||||
**** disabled *****************************************************************************************/
|
||||
|
||||
|
||||
// ask the child to load the bitstream buffer with their data
|
||||
childStopOctalCode = loadBitstreamBuffer(bitstreamBuffer,
|
||||
currentVoxelNode->children[i],
|
||||
|
@ -756,3 +803,274 @@ void VoxelTree::createSphere(float r,float xc, float yc, float zc, float s, bool
|
|||
}
|
||||
this->reaverageVoxelColors(this->rootNode);
|
||||
}
|
||||
|
||||
|
||||
int VoxelTree::bhgLoadBitstream(VoxelNode* node, const ViewFrustum& viewFrustum,
|
||||
unsigned char*& lastOctalCode, bool& startedWriting,
|
||||
unsigned char*& outputBuffer, int availableBytes) const {
|
||||
|
||||
// Some debugging code... where are we in the tree..
|
||||
AABox box;
|
||||
node->getAABox(box);
|
||||
printf("bhgLoadBitstream() box.corner=(%f,%f,%f) size=%f node=",
|
||||
box.getCorner().x, box.getCorner().y, box.getCorner().z,box.getSize().x);
|
||||
printOctalCode(node->octalCode);
|
||||
|
||||
// How many bytes have we written so far at this level;
|
||||
int bytesAtThisLevel = 0;
|
||||
|
||||
// remember our prior writing state, because we might need to do something special with this information below
|
||||
bool priorWritingState = startedWriting;
|
||||
|
||||
// If we're at a node that is out of view, then we can return, because no nodes below us will be in view!
|
||||
if (!node->isInView(viewFrustum)) {
|
||||
printf("bhgLoadBitstream() node NOT IN VIEW\n");
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
bool keepDiggingDeeper = true; // Assuming we're in view we have a great work ethic, we're always ready for more!
|
||||
|
||||
// At any given point in writing the bitstream, the largest minimum we might need to flesh out the current level
|
||||
// is 1 byte for child colors + 3*8 bytes for the actual colors + 1 byte for child trees. There could be sub trees
|
||||
// below this point, which might take many more bytes, but that's ok, because we can always mark our subtrees as
|
||||
// not existing and stop the packet at this point, then start up with a new packet for the remaining sub trees.
|
||||
const int CHILD_COLOR_MASK_BYTES = 1;
|
||||
const int MAX_CHILDREN = 8;
|
||||
const int BYTES_PER_COLOR = 3;
|
||||
const int CHILD_TREE_EXISTS_BYTES = 1;
|
||||
const int MAX_LEVEL_BYTES = CHILD_COLOR_MASK_BYTES + MAX_CHILDREN * BYTES_PER_COLOR + CHILD_TREE_EXISTS_BYTES;
|
||||
|
||||
// If we haven't yet started writing we may also need to write an octcode for this level. Which we can determine
|
||||
// the size of by looking at this node's octcode.
|
||||
int thisLevelOctcodeSize = startedWriting ? 0 : bytesRequiredForCodeLength(*node->octalCode);
|
||||
|
||||
// Some degenerate cases... If for some reason, we haven't started writing, and the available bytes left are less
|
||||
// than what it would take to even write our octcode, we need to bail at this point
|
||||
if (!startedWriting && (availableBytes < thisLevelOctcodeSize)) {
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
// Make our local buffer large enough to handle writing at this level in case we need to.
|
||||
unsigned char thisLevelBuffer[thisLevelOctcodeSize+MAX_LEVEL_BYTES];
|
||||
unsigned char* writeToThisLevelBuffer = &thisLevelBuffer[0];
|
||||
|
||||
// XXXBHG - We are not yet using this. But we plan to soon... this is how we determine if we've previously sent out
|
||||
// content at this level or not. In theory, if we're more shallow than where we left off, then we don't actually want
|
||||
// to send data. If we're deeper than where we left off, then we want to be prepared to send data
|
||||
bool sendData = compareOctalCodes(node->octalCode,lastOctalCode);
|
||||
|
||||
VoxelNode* inViewChildren[MAX_CHILDREN];
|
||||
float distancesToChildren[MAX_CHILDREN];
|
||||
int positionOfChildren[MAX_CHILDREN];
|
||||
int inViewCount = 0;
|
||||
int inViewNotLeafCount = 0;
|
||||
int inViewWithColorCount = 0;
|
||||
|
||||
unsigned char childrenExistBits = 0;
|
||||
unsigned char childrenColoredBits = 0;
|
||||
|
||||
// for each child node, check to see if they exist, are colored, and in view, and if so
|
||||
// add them to our distance ordered array of children
|
||||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||
VoxelNode* childNode = node->children[i];
|
||||
bool childExists = (childNode != NULL);
|
||||
|
||||
if (childExists) {
|
||||
AABox childBox;
|
||||
childNode->getAABox(childBox);
|
||||
printf("child[%d] childBox.corner=(%f,%f,%f) size=%f \n", i ,
|
||||
childBox.getCorner().x, childBox.getCorner().y, childBox.getCorner().z, childBox.getSize().x);
|
||||
}
|
||||
|
||||
bool childIsColored = (childExists && childNode->isColored());
|
||||
bool childIsInView = (childExists && childNode->isInView(viewFrustum));
|
||||
bool childIsLeaf = (childExists && childNode->isLeaf());
|
||||
|
||||
printf("childExists=%s childIsColored=%s childIsInView=%s childIsLeaf=%s \n",
|
||||
(childExists ? "yes" : "no"), (childIsColored ? "yes" : "no"),
|
||||
(childIsInView ? "yes" : "no"), (childIsLeaf ? "yes" : "no") );
|
||||
|
||||
// colored not important??
|
||||
if (childExists && childIsInView) {
|
||||
|
||||
// track children in view as existing and not a leaf
|
||||
if (!childIsLeaf) {
|
||||
childrenExistBits += (1 << (7 - i));
|
||||
inViewNotLeafCount++;
|
||||
}
|
||||
|
||||
// track children with actual color
|
||||
if (childIsColored) {
|
||||
childrenColoredBits += (1 << (7 - i));
|
||||
inViewWithColorCount++;
|
||||
}
|
||||
|
||||
float distance = childNode->distanceToCamera(viewFrustum);
|
||||
|
||||
printf("child[%d] distance=%f\n",i,distance);
|
||||
|
||||
inViewCount = insertIntoSortedArrays((void*)childNode, distance, i,
|
||||
(void**)&inViewChildren, (float*)&distancesToChildren, (int*)&positionOfChildren,
|
||||
inViewCount, MAX_CHILDREN);
|
||||
}
|
||||
}
|
||||
printf("bhgLoadBitstream() child nodes in view... inViewCount=%d\n",inViewCount);
|
||||
printf("bhgLoadBitstream() child nodes in view with color... inViewWithColorCount=%d\n",inViewWithColorCount);
|
||||
printf("bhgLoadBitstream() child nodes in view NOT LEAF... inViewNotLeafCount=%d\n",inViewNotLeafCount);
|
||||
|
||||
// If we have children with color, then we must go ahead and start writing codes,
|
||||
// we can't dig deeper before starting to write.
|
||||
bool wroteOctcodeAtThisLevel = false;
|
||||
if (inViewWithColorCount && !startedWriting) {
|
||||
|
||||
// keep track that we've started writing
|
||||
startedWriting = true;
|
||||
|
||||
// write the octal code
|
||||
int codeLength = bytesRequiredForCodeLength(*node->octalCode);
|
||||
|
||||
printf("bhgLoadBitstream() writing my octal code\n");
|
||||
memcpy(writeToThisLevelBuffer,node->octalCode,codeLength);
|
||||
|
||||
writeToThisLevelBuffer += codeLength; // move the pointer
|
||||
bytesAtThisLevel += codeLength; // keep track of byte count
|
||||
|
||||
// remember we wrote our octcode here
|
||||
wroteOctcodeAtThisLevel = true;
|
||||
}
|
||||
|
||||
// Ok, no matter when we started writing (at this level, or above) if we've got children with color
|
||||
// we need to write them here.
|
||||
if (inViewWithColorCount && startedWriting) {
|
||||
// write the child color bits
|
||||
printf("bhgLoadBitstream() writing child color bits\n");
|
||||
*writeToThisLevelBuffer = childrenColoredBits;
|
||||
|
||||
writeToThisLevelBuffer += sizeof(childrenColoredBits); // move the pointer
|
||||
bytesAtThisLevel += sizeof(childrenColoredBits); // keep track of byte count
|
||||
|
||||
// write the color data...
|
||||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||
if (oneAtBit(childrenColoredBits, i)) {
|
||||
printf("bhgLoadBitstream() writing color for child %d\n",i);
|
||||
memcpy(writeToThisLevelBuffer,&node->children[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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("startedWriting=%s inViewNotLeafCount=%d \n", (startedWriting ? "yes" : "no"), inViewNotLeafCount );
|
||||
|
||||
// If all of our IN VIEW children are LEAVES, then we're done
|
||||
if (startedWriting && (0 == inViewNotLeafCount)) {
|
||||
|
||||
printf("bhgLoadBitstream() writing child trees exist bits of 0\n");
|
||||
|
||||
// write the child color bits
|
||||
*writeToThisLevelBuffer = childrenExistBits;
|
||||
|
||||
writeToThisLevelBuffer += sizeof(childrenExistBits); // move the pointer
|
||||
bytesAtThisLevel += sizeof(childrenExistBits); // keep track of byte count
|
||||
|
||||
keepDiggingDeeper = false;
|
||||
}
|
||||
|
||||
// at this point we need to do a gut check. If we're writing, then we need to check how many bytes we've
|
||||
// written at this level, and how many bytes we have available in the outputBuffer. If we can fit what we've got so far
|
||||
// and room for the no more children terminator, then let's write what we got so far.
|
||||
|
||||
// If we plan to keep digging deeper, we will need at least one more byte. Otherwise, we've got all the bytes we
|
||||
// need to write already written in our thisLevelBuffer. If we have room for this in our outputBuffer, then copy
|
||||
// it and proceed as expected.
|
||||
int potentiallyMoreBytes = keepDiggingDeeper ? CHILD_TREE_EXISTS_BYTES : 0;
|
||||
|
||||
printf("startedWriting=%s availableBytes=%d bytesAtThisLevel=%d keepDiggingDeeper=%s potentiallyMoreBytes=%d\n",
|
||||
(startedWriting ? "yes" : "no"), availableBytes, bytesAtThisLevel,
|
||||
(keepDiggingDeeper ? "yes" : "no"), potentiallyMoreBytes );
|
||||
|
||||
if (startedWriting && (availableBytes > (bytesAtThisLevel + potentiallyMoreBytes))) {
|
||||
memcpy(outputBuffer,&thisLevelBuffer[0],bytesAtThisLevel);
|
||||
availableBytes -= bytesAtThisLevel;
|
||||
|
||||
printf("actually write our local bytes to the outputBuffer bytesAtThisLevel=%d availableBytes=%d\n",
|
||||
bytesAtThisLevel, availableBytes);
|
||||
}
|
||||
|
||||
if (keepDiggingDeeper) {
|
||||
|
||||
printf("keepDiggingDeeper == TRUE... dig deeper!\n");
|
||||
|
||||
// at this point, we need to iterate the children who are in view, even if not colored
|
||||
// and we need to determine if there's a deeper tree below them that we care about. We will iterate
|
||||
// these based on which tree is closer.
|
||||
//
|
||||
// We have potentially a couple of states here, it's possible we haven't started writing at all. In
|
||||
// which case, the lower level trees may start writing. And so when we get back here, we need to check
|
||||
// our writing state, if we had not been writing, and we started writing below, then we basically want
|
||||
// to start a new top level tree. We do that by simply toggling our startedWriting flag, and then call
|
||||
// the child node.
|
||||
//
|
||||
// It's also possible that we did start writing, but we have NOT yet written our childrenExistBits. This
|
||||
// is because we don't really know how big the child tree will be. What we kinda would like to do is
|
||||
// write our childExistsBits as a place holder. Then let each potential tree have a go at it. If they
|
||||
// write something, we keep them in the bits, if they don't, we take them out.
|
||||
//
|
||||
unsigned char* childExistsPlaceHolder = NULL;
|
||||
bool havePlaceHolderChildBits = false;
|
||||
if (startedWriting) {
|
||||
// write the child tree exists "placeholder" bits.
|
||||
childExistsPlaceHolder = outputBuffer;
|
||||
*outputBuffer = childrenExistBits;
|
||||
|
||||
outputBuffer += sizeof(childrenExistBits); // move the pointer
|
||||
bytesAtThisLevel += sizeof(childrenExistBits); // keep track of byte count
|
||||
|
||||
havePlaceHolderChildBits = true;
|
||||
}
|
||||
for (int i = 0; i < inViewCount; i++) {
|
||||
VoxelNode* childNode = inViewChildren[i];
|
||||
int childNodePosition = positionOfChildren[i];
|
||||
|
||||
printf("bhgLoadBitstream() calling inViewChildren[%d] startedWriting=%s\n",i, (startedWriting ? "yes" : "no") );
|
||||
|
||||
printf("about to dig deeper, priorWritingState=%s\n",(priorWritingState ? "yes" : "no"));
|
||||
|
||||
int childTreeBytesOut = bhgLoadBitstream(childNode,viewFrustum,lastOctalCode,startedWriting,
|
||||
outputBuffer,availableBytes);
|
||||
|
||||
printf("back from dig deeper, priorWritingState=%s startedWriting=%s childTreeBytesOut=%d\n",
|
||||
(priorWritingState ? "yes" : "no"), (startedWriting ? "yes" : "no"), childTreeBytesOut);
|
||||
|
||||
bytesAtThisLevel += childTreeBytesOut;
|
||||
|
||||
// If we had previously started writing, and if the child DIDN'T write any bytes,
|
||||
// then we want to remove their bit from the childExistsPlaceHolder bitmask
|
||||
if (havePlaceHolderChildBits && (0 == childTreeBytesOut)) {
|
||||
|
||||
printf("bhgLoadBitstream() child %d orig %d didn't write bytes, removing from bitmask\n",i, childNodePosition );
|
||||
|
||||
// remove this child's bit...
|
||||
childrenExistBits -= (1 << (7 - childNodePosition));
|
||||
|
||||
// repair the child exists mask
|
||||
*childExistsPlaceHolder = childrenExistBits;
|
||||
|
||||
// Note: no need to move the pointer, cause we already stored this
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("bhgLoadBitstream() at bottom, returning... bytesAtThisLevel=%d\n",bytesAtThisLevel );
|
||||
|
||||
// If this was the level that we wrote our octcode at.. AND our prior state was not writing, THEN THIS
|
||||
// is the level we want to switch back to not writing...
|
||||
|
||||
// If before we started this tree, we WEREN'T writing, but after iterating this tree we ARE writing
|
||||
// then we need to reset writing state, so we'll start a new tree when appropriate.
|
||||
if (!priorWritingState && startedWriting) {
|
||||
printf("bhgLoadBitstream() at bottom and returning prior writing state was FALSE, but we did write, so... we want a new tree!\n");
|
||||
startedWriting = false;
|
||||
}
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
const int MAX_VOXEL_PACKET_SIZE = 1492;
|
||||
const int MAX_TREE_SLICE_BYTES = 26;
|
||||
const int TREE_SCALE = 10;
|
||||
|
||||
// Callback function, for recuseTreeWithOperation
|
||||
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, bool down, void* extraData);
|
||||
|
@ -48,25 +47,29 @@ public:
|
|||
void deleteVoxelCodeFromTree(unsigned char *codeBuffer);
|
||||
void printTreeForDebugging(VoxelNode *startNode);
|
||||
void reaverageVoxelColors(VoxelNode *startNode);
|
||||
unsigned char * loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
||||
VoxelNode *currentVoxelNode,
|
||||
MarkerNode *currentMarkerNode,
|
||||
unsigned char * loadBitstreamBuffer(unsigned char*& bitstreamBuffer,
|
||||
VoxelNode* currentVoxelNode,
|
||||
MarkerNode* currentMarkerNode,
|
||||
const glm::vec3& agentPosition,
|
||||
float thisNodePosition[3],
|
||||
const ViewFrustum& viewFrustum,
|
||||
bool viewFrustumCulling,
|
||||
unsigned char * octalCode = NULL);
|
||||
unsigned char* octalCode = NULL);
|
||||
|
||||
void loadVoxelsFile(const char* fileName, bool wantColorRandomizer);
|
||||
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer);
|
||||
|
||||
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
|
||||
|
||||
int bhgLoadBitstream(VoxelNode* node, const ViewFrustum& viewFrustum,
|
||||
unsigned char*& lastOctalCode, bool& startedWriting,
|
||||
unsigned char*& outputBuffer, int availableBytes) const;
|
||||
|
||||
private:
|
||||
void recurseNodeWithOperation(VoxelNode* node,RecurseVoxelTreeOperation operation, void* extraData);
|
||||
VoxelNode * nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode, VoxelNode** parentOfFoundNode);
|
||||
VoxelNode * createMissingNode(VoxelNode *lastParentNode, unsigned char *deepestCodeToCreate);
|
||||
int readNodeData(VoxelNode *destinationNode, unsigned char * nodeData, int bufferSizeBytes);
|
||||
void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData);
|
||||
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode);
|
||||
VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate);
|
||||
int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes);
|
||||
};
|
||||
|
||||
int boundaryDistanceForRenderLevel(unsigned int renderLevel);
|
||||
|
|
Loading…
Reference in a new issue