From 2c8c6a2600c4804e8f01b1b5e147106128206297 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 5 May 2013 10:17:02 -0700 Subject: [PATCH] Coding standard cleanup and VoxelNode optimization - make octalCode and children members private - add public getters for accessing these private members - change constructor to require an OctalCode for all non-roots - default constructor constructs a rootNode - make primary access for deleting, adding, and accessing children through public methods that do bookkeeping - calculate AABox on voxel creation so that we don't need to do all the math when we deal with voxels - added methods on VoxelNode for common items like getCorner(), getCenter(), getLevel(), etc --- interface/src/VoxelSystem.cpp | 12 +-- libraries/voxels/src/AABox.cpp | 2 + libraries/voxels/src/AABox.h | 2 + libraries/voxels/src/VoxelConstants.h | 2 + libraries/voxels/src/VoxelNode.cpp | 86 ++++++++++++--------- libraries/voxels/src/VoxelNode.h | 24 ++++-- libraries/voxels/src/VoxelNodeBag.cpp | 2 +- libraries/voxels/src/VoxelTree.cpp | 106 ++++++++++++-------------- voxel-server/src/main.cpp | 8 +- 9 files changed, 132 insertions(+), 112 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 989ab8ff3d..258b604b0c 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -221,8 +221,8 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { assert(_viewFrustum); // you must set up _viewFrustum before calling this int voxelsUpdated = 0; float distanceToNode = node->distanceToCamera(*_viewFrustum); - float boundary = boundaryDistanceForRenderLevel(*node->octalCode + 1); - float childBoundary = boundaryDistanceForRenderLevel(*node->octalCode + 2); + float boundary = boundaryDistanceForRenderLevel(node->getLevel()); + float childBoundary = boundaryDistanceForRenderLevel(node->getLevel() + 1); bool inBoundary = (distanceToNode <= boundary); bool inChildBoundary = (distanceToNode <= childBoundary); bool shouldRender = node->isColored() && ((node->isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary)); @@ -230,8 +230,8 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { node->setShouldRender(shouldRender); // let children figure out their renderness for (int i = 0; i < 8; i++) { - if (node->children[i]) { - voxelsUpdated += newTreeToArrays(node->children[i]); + if (node->getChildAtIndex(i)) { + voxelsUpdated += newTreeToArrays(node->getChildAtIndex(i)); } } @@ -242,8 +242,8 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { // If we're should render, use our legit location and scale, if (node->getShouldRender()) { - copyFirstVertexForCode(node->octalCode, (float*)&startVertex); - voxelScale = (1 / powf(2, *node->octalCode)); + startVertex = node->getCorner(); + voxelScale = node->getScale(); } else { // if we shouldn't render then set out location to some infinitely distant location, // and our scale as infinitely small diff --git a/libraries/voxels/src/AABox.cpp b/libraries/voxels/src/AABox.cpp index 0187bae853..00cace6ae5 100755 --- a/libraries/voxels/src/AABox.cpp +++ b/libraries/voxels/src/AABox.cpp @@ -14,6 +14,7 @@ void AABox::scale(float scale) { _corner = _corner*scale; _size = _size*scale; + _center = _center*scale; } @@ -34,6 +35,7 @@ void AABox::setBox(const glm::vec3& corner, const glm::vec3& size) { _size.z = -size.z; _corner.z -= _size.z; } + _center = _corner + (_size * 0.5f); } glm::vec3 AABox::getVertexP(const glm::vec3 &normal) const { diff --git a/libraries/voxels/src/AABox.h b/libraries/voxels/src/AABox.h index 0a69b8608d..fd399a95e6 100755 --- a/libraries/voxels/src/AABox.h +++ b/libraries/voxels/src/AABox.h @@ -34,9 +34,11 @@ public: const glm::vec3& getCorner() const { return _corner; }; const glm::vec3& getSize() const { return _size; }; + const glm::vec3& getCenter() const { return _center; }; private: glm::vec3 _corner; + glm::vec3 _center; glm::vec3 _size; }; diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 16bab45e4f..f278017f23 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -14,6 +14,8 @@ #include +const int NUMBER_OF_CHILDREN = 8; + const int MAX_VOXEL_PACKET_SIZE = 1492; const int MAX_TREE_SLICE_BYTES = 26; const int TREE_SCALE = 10; diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 3d0e400782..30d8ea1f68 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -20,7 +20,17 @@ using voxels_lib::printLog; // using voxels_lib::printLog; VoxelNode::VoxelNode() { - octalCode = NULL; + unsigned char* rootCode = new unsigned char[1]; + *rootCode = 0; + init(rootCode); +} + +VoxelNode::VoxelNode(unsigned char * octalCode) { + init(octalCode); +} + +void VoxelNode::init(unsigned char * octalCode) { + _octalCode = octalCode; #ifdef HAS_FALSE_COLOR _falseColored = false; // assume true color @@ -28,21 +38,23 @@ VoxelNode::VoxelNode() { // default pointers to child nodes to NULL for (int i = 0; i < 8; i++) { - children[i] = NULL; + _children[i] = NULL; } _glBufferIndex = GLBUFFER_INDEX_UNKNOWN; _isDirty = true; _shouldRender = false; + + calculateAABox(); } VoxelNode::~VoxelNode() { - delete[] octalCode; + delete[] _octalCode; // delete all of this node's children for (int i = 0; i < 8; i++) { - if (children[i]) { - delete children[i]; + if (_children[i]) { + delete _children[i]; } } } @@ -55,33 +67,38 @@ void VoxelNode::setShouldRender(bool shouldRender) { } } -void VoxelNode::getAABox(AABox& box) const { +void VoxelNode::calculateAABox() { glm::vec3 corner; glm::vec3 size; // copy corner into box - copyFirstVertexForCode(octalCode,(float*)&corner); + copyFirstVertexForCode(_octalCode,(float*)&corner); // this tells you the "size" of the voxel - float voxelScale = 1 / powf(2, *octalCode); + float voxelScale = 1 / powf(2, *_octalCode); size = glm::vec3(voxelScale,voxelScale,voxelScale); - box.setBox(corner,size); + _box.setBox(corner,size); +} + +void VoxelNode::deleteChildAtIndex(int childIndex) { + if (_children[childIndex]) { + delete _children[childIndex]; + _children[childIndex] = NULL; + } } void VoxelNode::addChildAtIndex(int childIndex) { - if (!children[childIndex]) { - children[childIndex] = new VoxelNode(); + if (!_children[childIndex]) { + _children[childIndex] = new VoxelNode(childOctalCode(_octalCode, childIndex)); // XXXBHG - When the node is constructed, it should be cleanly set up as // true colored, but for some reason, not so much. I've added a a basecamp // to-do to research this. But for now we'll use belt and suspenders and set // it to not-false-colored here! - children[childIndex]->setFalseColored(false); + _children[childIndex]->setFalseColored(false); - // give this child its octal code - children[childIndex]->octalCode = childOctalCode(octalCode, childIndex); _isDirty = true; } } @@ -90,9 +107,9 @@ void VoxelNode::addChildAtIndex(int childIndex) { void VoxelNode::setColorFromAverageOfChildren() { int colorArray[4] = {0,0,0,0}; for (int i = 0; i < 8; i++) { - if (children[i] != NULL && children[i]->isColored()) { + if (_children[i] != NULL && _children[i]->isColored()) { for (int j = 0; j < 3; j++) { - colorArray[j] += children[i]->getTrueColor()[j]; // color averaging should always be based on true colors + colorArray[j] += _children[i]->getTrueColor()[j]; // color averaging should always be based on true colors } colorArray[3]++; } @@ -170,17 +187,17 @@ bool VoxelNode::collapseIdenticalLeaves() { int red,green,blue; for (int i = 0; i < 8; i++) { // if no child, or child doesn't have a color - if (children[i] == NULL || !children[i]->isColored()) { + if (_children[i] == NULL || !_children[i]->isColored()) { allChildrenMatch=false; //printLog("SADNESS child missing or not colored! i=%d\n",i); break; } else { if (i==0) { - red = children[i]->getColor()[0]; - green = children[i]->getColor()[1]; - blue = children[i]->getColor()[2]; - } else if (red != children[i]->getColor()[0] || - green != children[i]->getColor()[1] || blue != children[i]->getColor()[2]) { + red = _children[i]->getColor()[0]; + green = _children[i]->getColor()[1]; + blue = _children[i]->getColor()[2]; + } else if (red != _children[i]->getColor()[0] || + green != _children[i]->getColor()[1] || blue != _children[i]->getColor()[2]) { allChildrenMatch=false; break; } @@ -191,8 +208,8 @@ bool VoxelNode::collapseIdenticalLeaves() { if (allChildrenMatch) { //printLog("allChildrenMatch: pruning tree\n"); for (int i = 0; i < 8; i++) { - delete children[i]; // delete all the child nodes - children[i]=NULL; // set it to NULL + delete _children[i]; // delete all the child nodes + _children[i]=NULL; // set it to NULL } nodeColor collapsedColor; collapsedColor[0]=red; @@ -216,7 +233,7 @@ void VoxelNode::setRandomColor(int minimumBrightness) { bool VoxelNode::isLeaf() const { for (int i = 0; i < 8; i++) { - if (children[i]) { + if (_children[i]) { return false; } } @@ -224,27 +241,22 @@ bool VoxelNode::isLeaf() const { } void VoxelNode::printDebugDetails(const char* label) const { - AABox box; - getAABox(box); printLog("%s - Voxel at corner=(%f,%f,%f) size=%f octcode=", label, - box.getCorner().x, box.getCorner().y, box.getCorner().z, box.getSize().x); - printOctalCode(octalCode); + _box.getCorner().x, _box.getCorner().y, _box.getCorner().z, _box.getSize().x); + printOctalCode(_octalCode); } bool VoxelNode::isInView(const ViewFrustum& viewFrustum) const { - AABox box; - getAABox(box); + AABox box = _box; // use temporary box so we can scale it box.scale(TREE_SCALE); bool inView = (ViewFrustum::OUTSIDE != viewFrustum.boxInFrustum(box)); return inView; } float VoxelNode::distanceToCamera(const ViewFrustum& viewFrustum) const { - AABox box; - getAABox(box); - box.scale(TREE_SCALE); - float distanceToVoxelCenter = sqrtf(powf(viewFrustum.getPosition().x - (box.getCorner().x + box.getSize().x), 2) + - powf(viewFrustum.getPosition().y - (box.getCorner().y + box.getSize().y), 2) + - powf(viewFrustum.getPosition().z - (box.getCorner().z + box.getSize().z), 2)); + glm::vec3 center = _box.getCenter() * (float)TREE_SCALE; + float distanceToVoxelCenter = sqrtf(powf(viewFrustum.getPosition().x - center.x, 2) + + powf(viewFrustum.getPosition().y - center.y, 2) + + powf(viewFrustum.getPosition().z - center.z, 2)); return distanceToVoxelCenter; } diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 90ee3bf730..8e3fa1b4d6 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -27,23 +27,37 @@ private: glBufferIndex _glBufferIndex; bool _isDirty; bool _shouldRender; + AABox _box; + unsigned char* _octalCode; + VoxelNode* _children[8]; + + void calculateAABox(); + + void init(unsigned char * octalCode); + public: - VoxelNode(); + VoxelNode(); // root node constructor + VoxelNode(unsigned char * octalCode); // regular constructor ~VoxelNode(); + unsigned char* getOctalCode() const { return _octalCode; }; + VoxelNode* getChildAtIndex(int i) const { return _children[i]; }; + void deleteChildAtIndex(int childIndex); void addChildAtIndex(int childIndex); void setColorFromAverageOfChildren(); void setRandomColor(int minimumBrightness); bool collapseIdenticalLeaves(); - - unsigned char *octalCode; - VoxelNode *children[8]; + + const AABox& getAABox() const { return _box; }; + const glm::vec3& getCenter() const { return _box.getCenter(); }; + const glm::vec3& getCorner() const { return _box.getCorner(); }; + float getScale() const { return _box.getSize().x; /* voxelScale = (1 / powf(2, *node->getOctalCode())); */ }; + int getLevel() const { return *_octalCode + 1; /* one based or zero based? */ }; bool isColored() const { return (_trueColor[3]==1); }; bool isInView(const ViewFrustum& viewFrustum) const; float distanceToCamera(const ViewFrustum& viewFrustum) const; bool isLeaf() const; - void getAABox(AABox& box) const; void printDebugDetails(const char* label) const; bool isDirty() const { return _isDirty; }; void clearDirtyBit() { _isDirty = false; }; diff --git a/libraries/voxels/src/VoxelNodeBag.cpp b/libraries/voxels/src/VoxelNodeBag.cpp index e6b20cbf4b..132405ba6e 100644 --- a/libraries/voxels/src/VoxelNodeBag.cpp +++ b/libraries/voxels/src/VoxelNodeBag.cpp @@ -34,7 +34,7 @@ void VoxelNodeBag::insert(VoxelNode* node) { for (int i = 0; i < _elementsInUse; i++) { // compare the newNode to the elements already in the bag - OctalCodeComparison comparison = compareOctalCodes(_bagElements[i]->octalCode, node->octalCode); + OctalCodeComparison comparison = compareOctalCodes(_bagElements[i]->getOctalCode(), node->getOctalCode()); // If we found a code in the bag that matches, then just return, since the element is already in the bag. if (comparison == EXACT_MATCH) { diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index fee0c698bb..519d87d430 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -37,17 +37,14 @@ VoxelTree::VoxelTree() : voxelsColoredStats(100), voxelsBytesReadStats(100), _isDirty(true) { - rootNode = new VoxelNode(); - rootNode->octalCode = new unsigned char[1]; - *rootNode->octalCode = 0; } VoxelTree::~VoxelTree() { // delete the children of the root node // this recursively deletes the tree for (int i = 0; i < 8; i++) { - delete rootNode->children[i]; + delete rootNode->getChildAtIndex(i); } } @@ -60,8 +57,8 @@ void VoxelTree::recurseTreeWithOperation(RecurseVoxelTreeOperation operation, vo // Recurses voxel node with an operation function void VoxelTree::recurseNodeWithOperation(VoxelNode* node,RecurseVoxelTreeOperation operation, void* extraData) { if (operation(node, extraData)) { - for (int i = 0; i < sizeof(node->children) / sizeof(node->children[0]); i++) { - VoxelNode* child = node->children[i]; + for (int i = 0; i < 8; i++) { + VoxelNode* child = node->getChildAtIndex(i); if (child) { recurseNodeWithOperation(child, operation, extraData); } @@ -72,11 +69,11 @@ void VoxelTree::recurseNodeWithOperation(VoxelNode* node,RecurseVoxelTreeOperati VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode, VoxelNode** parentOfFoundNode) const { // find the appropriate branch index based on this ancestorNode if (*needleCode > 0) { - int branchForNeedle = branchIndexWithDescendant(ancestorNode->octalCode, needleCode); - VoxelNode *childNode = ancestorNode->children[branchForNeedle]; + int branchForNeedle = branchIndexWithDescendant(ancestorNode->getOctalCode(), needleCode); + VoxelNode *childNode = ancestorNode->getChildAtIndex(branchForNeedle); - if (childNode != NULL) { - if (*childNode->octalCode == *needleCode) { + if (childNode) { + if (*childNode->getOctalCode() == *needleCode) { // If the caller asked for the parent, then give them that too... if (parentOfFoundNode) { @@ -101,18 +98,18 @@ VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * // returns the node created! VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char* codeToReach) { - int indexOfNewChild = branchIndexWithDescendant(lastParentNode->octalCode, codeToReach); + int indexOfNewChild = branchIndexWithDescendant(lastParentNode->getOctalCode(), codeToReach); // we could be coming down a branch that was already created, so don't stomp on it. - if (lastParentNode->children[indexOfNewChild] == NULL) { + if (!lastParentNode->getChildAtIndex(indexOfNewChild)) { lastParentNode->addChildAtIndex(indexOfNewChild); } // This works because we know we traversed down the same tree so if the length is the same, then the whole code is the same - if (*lastParentNode->children[indexOfNewChild]->octalCode == *codeToReach) { - return lastParentNode->children[indexOfNewChild]; + if (*lastParentNode->getChildAtIndex(indexOfNewChild)->getOctalCode() == *codeToReach) { + return lastParentNode->getChildAtIndex(indexOfNewChild); } else { - return createMissingNode(lastParentNode->children[indexOfNewChild], codeToReach); + return createMissingNode(lastParentNode->getChildAtIndex(indexOfNewChild), codeToReach); } } @@ -124,11 +121,11 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, int bytesLeftToRead) { // instantiate variable for bytes already read int bytesRead = 1; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < NUMBER_OF_CHILDREN; 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]) { + if (!destinationNode->getChildAtIndex(i)) { destinationNode->addChildAtIndex(i); if (destinationNode->isDirty()) { _isDirty = true; @@ -142,9 +139,9 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, nodeColor newColor; memcpy(newColor, nodeData + bytesRead, 3); newColor[3] = 1; - bool nodeWasDirty = destinationNode->children[i]->isDirty(); - destinationNode->children[i]->setColor(newColor); - bool nodeIsDirty = destinationNode->children[i]->isDirty(); + bool nodeWasDirty = destinationNode->getChildAtIndex(i)->isDirty(); + destinationNode->getChildAtIndex(i)->setColor(newColor); + bool nodeIsDirty = destinationNode->getChildAtIndex(i)->isDirty(); if (nodeIsDirty) { _isDirty = true; } @@ -168,7 +165,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, // check the exists mask to see if we have a child to traverse into if (oneAtBit(childMask, childIndex)) { - if (!destinationNode->children[childIndex]) { + if (!destinationNode->getChildAtIndex(childIndex)) { // add a child at that index, if it doesn't exist bool nodeWasDirty = destinationNode->isDirty(); destinationNode->addChildAtIndex(childIndex); @@ -184,7 +181,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, } // tell the child to read the subsequent data - bytesRead += readNodeData(destinationNode->children[childIndex], + bytesRead += readNodeData(destinationNode->getChildAtIndex(childIndex), nodeData + bytesRead, bytesLeftToRead - bytesRead); } @@ -207,7 +204,7 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int while (bitstreamAt < bitstream + bufferSizeBytes) { VoxelNode* bitstreamRootNode = nodeForOctalCode(rootNode, (unsigned char *)bitstreamAt, NULL); - if (*bitstreamAt != *bitstreamRootNode->octalCode) { + if (*bitstreamAt != *bitstreamRootNode->getOctalCode()) { // if the octal code returned is not on the same level as // the code being searched for, we have VoxelNodes to create @@ -251,12 +248,11 @@ void VoxelTree::deleteVoxelCodeFromTree(unsigned char *codeBuffer) { // If the node exists... int lengthInBytes = bytesRequiredForCodeLength(*codeBuffer); // includes octet count, not color! - if (0 == memcmp(nodeToDelete->octalCode,codeBuffer,lengthInBytes)) { + if (0 == memcmp(nodeToDelete->getOctalCode(),codeBuffer,lengthInBytes)) { if (parentNode) { - int childIndex = branchIndexWithDescendant(parentNode->octalCode, codeBuffer); + int childIndex = branchIndexWithDescendant(parentNode->getOctalCode(), codeBuffer); - delete parentNode->children[childIndex]; // delete the child nodes - parentNode->children[childIndex] = NULL; // set it to NULL + parentNode->deleteChildAtIndex(childIndex); reaverageVoxelColors(rootNode); // Fix our colors!! Need to call it on rootNode _isDirty = true; @@ -268,8 +264,6 @@ void VoxelTree::eraseAllVoxels() { // XXXBHG Hack attack - is there a better way to erase the voxel tree? delete rootNode; // this will recurse and delete all children rootNode = new VoxelNode(); - rootNode->octalCode = new unsigned char[1]; - *rootNode->octalCode = 0; _isDirty = true; } @@ -277,7 +271,7 @@ void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer) { VoxelNode* lastCreatedNode = nodeForOctalCode(rootNode, codeColorBuffer, NULL); // create the node if it does not exist - if (*lastCreatedNode->octalCode != *codeColorBuffer) { + if (*lastCreatedNode->getOctalCode() != *codeColorBuffer) { lastCreatedNode = createMissingNode(lastCreatedNode, codeColorBuffer); _isDirty = true; } @@ -320,7 +314,7 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) { // create the color mask for (int i = 0; i < 8; i++) { - if (startNode->children[i] != NULL && startNode->children[i]->isColored()) { + if (startNode->getChildAtIndex(i) && startNode->getChildAtIndex(i)->isColored()) { colorMask += (1 << (7 - i)); } } @@ -330,19 +324,19 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) { // output the colors we have for (int j = 0; j < 8; j++) { - if (startNode->children[j] != NULL && startNode->children[j]->isColored()) { + if (startNode->getChildAtIndex(j) && startNode->getChildAtIndex(j)->isColored()) { printLog("color %d : ",j); for (int c = 0; c < 3; c++) { - outputBits(startNode->children[j]->getTrueColor()[c],false); + outputBits(startNode->getChildAtIndex(j)->getTrueColor()[c],false); } - startNode->children[j]->printDebugDetails(""); + startNode->getChildAtIndex(j)->printDebugDetails(""); } } unsigned char childMask = 0; for (int k = 0; k < 8; k++) { - if (startNode->children[k] != NULL) { + if (startNode->getChildAtIndex(k)) { childMask += (1 << (7 - k)); } } @@ -354,8 +348,8 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) { // 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]); + if (startNode->getChildAtIndex(l)) { + printTreeForDebugging(startNode->getChildAtIndex(l)); } } } @@ -365,8 +359,8 @@ void VoxelTree::reaverageVoxelColors(VoxelNode *startNode) { bool hasChildren = false; for (int i = 0; i < 8; i++) { - if (startNode->children[i] != NULL) { - reaverageVoxelColors(startNode->children[i]); + if (startNode->getChildAtIndex(i)) { + reaverageVoxelColors(startNode->getChildAtIndex(i)); hasChildren = true; } } @@ -437,7 +431,7 @@ void VoxelTree::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) { VoxelNode* VoxelTree::getVoxelAt(float x, float y, float z, float s) const { unsigned char* octalCode = pointToVoxel(x,y,z,s,0,0,0); VoxelNode* node = nodeForOctalCode(rootNode, octalCode, NULL); - if (*node->octalCode != *octalCode) { + if (*node->getOctalCode() != *octalCode) { node = NULL; } delete octalCode; // cleanup memory @@ -587,11 +581,10 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe // 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); - bool childIsColored = (childExists && childNode->isColored()); - bool childIsInView = (childExists && childNode->isInView(viewFrustum)); - bool childIsLeaf = (childExists && childNode->isLeaf()); + VoxelNode* childNode = node->getChildAtIndex(i); + bool childIsColored = (childNode && childNode->isColored()); + bool childIsInView = (childNode && childNode->isInView(viewFrustum)); + bool childIsLeaf = (childNode && childNode->isLeaf()); if (childIsInView) { @@ -607,7 +600,7 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe float distance = childNode->distanceToCamera(viewFrustum); - if (distance < boundaryDistanceForRenderLevel(*childNode->octalCode + 1)) { + if (distance < boundaryDistanceForRenderLevel(*childNode->getOctalCode() + 1)) { inViewCount = insertIntoSortedArrays((void*)childNode, distance, i, (void**)&inViewChildren, (float*)&distancesToChildren, (int*)&positionOfChildren, inViewCount, MAX_CHILDREN); @@ -648,8 +641,8 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned } // write the octal code - int codeLength = bytesRequiredForCodeLength(*node->octalCode); - memcpy(outputBuffer,node->octalCode,codeLength); + int codeLength = bytesRequiredForCodeLength(*node->getOctalCode()); + memcpy(outputBuffer,node->getOctalCode(),codeLength); outputBuffer += codeLength; // move the pointer bytesWritten += codeLength; // keep track of byte count @@ -695,7 +688,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco // caller can pass NULL as viewFrustum if they want everything if (viewFrustum) { float distance = node->distanceToCamera(*viewFrustum); - float boundaryDistance = boundaryDistanceForRenderLevel(*node->octalCode + 1); + float boundaryDistance = boundaryDistanceForRenderLevel(*node->getOctalCode() + 1); // If we're too far away for our render level, then just return if (distance >= boundaryDistance) { @@ -735,13 +728,12 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco // 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); - bool childIsInView = (childExists && (!viewFrustum || childNode->isInView(*viewFrustum))); + VoxelNode* childNode = node->getChildAtIndex(i); + bool childIsInView = (childNode && (!viewFrustum || childNode->isInView(*viewFrustum))); if (childIsInView) { // Before we determine consider this further, let's see if it's in our LOD scope... float distance = viewFrustum ? childNode->distanceToCamera(*viewFrustum) : 0; - float boundaryDistance = viewFrustum ? boundaryDistanceForRenderLevel(*childNode->octalCode + 1) : 1; + float boundaryDistance = viewFrustum ? boundaryDistanceForRenderLevel(*childNode->getOctalCode() + 1) : 1; if (distance < boundaryDistance) { inViewCount++; @@ -749,13 +741,13 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco // track children in view as existing and not a leaf, if they're a leaf, // we don't care about recursing deeper on them, and we don't consider their // subtree to exist - if (!(childExists && childNode->isLeaf())) { + if (!(childNode && childNode->isLeaf())) { childrenExistBits += (1 << (7 - i)); inViewNotLeafCount++; } // track children with actual color - if (childExists && childNode->isColored()) { + if (childNode && childNode->isColored()) { childrenColoredBits += (1 << (7 - i)); inViewWithColorCount++; } @@ -769,7 +761,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco // write the color data... for (int i = 0; i < MAX_CHILDREN; i++) { if (oneAtBit(childrenColoredBits, i)) { - memcpy(writeToThisLevelBuffer, &node->children[i]->getColor(), BYTES_PER_COLOR); + 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 } @@ -810,7 +802,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco for (int i = 0; i < MAX_CHILDREN; i++) { if (oneAtBit(childrenExistBits, i)) { - VoxelNode* childNode = node->children[i]; + VoxelNode* childNode = node->getChildAtIndex(i); int thisLevel = currentEncodeLevel; int childTreeBytesOut = encodeTreeBitstreamRecursion(maxEncodeLevel, thisLevel, childNode, diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index eec5bb308a..366b81ad6d 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -153,12 +153,8 @@ void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { for (int i = 0; i < 8; i++) { if (true) { // create a new VoxelNode to put here - currentRootNode->children[i] = new VoxelNode(); - - // give this child it's octal code - currentRootNode->children[i]->octalCode = childOctalCode(currentRootNode->octalCode, i); - - randomlyFillVoxelTree(levelsToGo - 1, currentRootNode->children[i]); + currentRootNode->addChildAtIndex(i); + randomlyFillVoxelTree(levelsToGo - 1, currentRootNode->getChildAtIndex(i)); createdChildren = true; } }