cleanup old references to node which are really elements

This commit is contained in:
ZappoMan 2014-05-06 15:47:18 -07:00
parent cde583452a
commit 91e4a89573
9 changed files with 182 additions and 194 deletions

View file

@ -2032,7 +2032,7 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData
// if this node is fully OUTSIDE the view, but previously intersected and/or was inside the last view, then
// we need to hide it. Additionally we know that ALL of it's children are also fully OUTSIDE so we can recurse
// the children and simply mark them as hidden
args->tree->recurseNodeWithOperation(voxel, hideAllSubTreeOperation, args );
args->tree->recurseElementWithOperation(voxel, hideAllSubTreeOperation, args );
return false;
} break;
@ -2049,7 +2049,7 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData
// if this node is fully INSIDE the view, but previously INTERSECTED and/or was OUTSIDE the last view, then
// we need to show it. Additionally we know that ALL of it's children are also fully INSIDE so we can recurse
// the children and simply mark them as visible (as appropriate based on LOD)
args->tree->recurseNodeWithOperation(voxel, showAllSubTreeOperation, args);
args->tree->recurseElementWithOperation(voxel, showAllSubTreeOperation, args);
return false;
} break;
case ViewFrustum::INTERSECT: {

View file

@ -12,7 +12,7 @@
#include "ModelTree.h"
ModelTree::ModelTree(bool shouldReaverage) : Octree(shouldReaverage) {
_rootNode = createNewElement();
_rootElement = createNewElement();
}
ModelTreeElement* ModelTree::createNewElement(unsigned char * octalCode) {
@ -132,6 +132,7 @@ public:
FindAndUpdateModelWithIDandPropertiesOperator(const ModelItemID& modelID, const ModelItemProperties& properties);
virtual bool PreRecursion(OctreeElement* element);
virtual bool PostRecursion(OctreeElement* element);
bool wasFound() const { return _found; }
private:
const ModelItemID& _modelID;
const ModelItemProperties& _properties;
@ -167,6 +168,9 @@ void ModelTree::updateModel(const ModelItemID& modelID, const ModelItemPropertie
// Look for the existing model in the tree..
FindAndUpdateModelWithIDandPropertiesOperator theOperator(modelID, properties);
recurseTreeWithOperator(&theOperator);
if (theOperator.wasFound()) {
_isDirty = true;
}
}
void ModelTree::addModel(const ModelItemID& modelID, const ModelItemProperties& properties) {

View file

@ -29,7 +29,7 @@ public:
virtual ModelTreeElement* createNewElement(unsigned char * octalCode = NULL);
/// Type safe version of getRoot()
ModelTreeElement* getRoot() { return (ModelTreeElement*)_rootNode; }
ModelTreeElement* getRoot() { return static_cast<ModelTreeElement*>(_rootElement); }
// These methods will allow the OctreeServer to send your tree inbound edit packets of your

View file

@ -40,7 +40,7 @@ float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeSc
}
Octree::Octree(bool shouldReaverage) :
_rootNode(NULL),
_rootElement(NULL),
_isDirty(true),
_shouldReaverage(shouldReaverage),
_stopImport(false),
@ -52,25 +52,25 @@ Octree::Octree(bool shouldReaverage) :
Octree::~Octree() {
// delete the children of the root element
// this recursively deletes the tree
delete _rootNode;
delete _rootElement;
}
// Recurses voxel tree calling the RecurseOctreeOperation function for each element.
// stops recursion if operation function returns false.
void Octree::recurseTreeWithOperation(RecurseOctreeOperation operation, void* extraData) {
recurseNodeWithOperation(_rootNode, operation, extraData);
recurseElementWithOperation(_rootElement, operation, extraData);
}
// Recurses voxel tree calling the RecurseOctreePostFixOperation function for each element in post-fix order.
void Octree::recurseTreeWithPostOperation(RecurseOctreeOperation operation, void* extraData) {
recurseNodeWithPostOperation(_rootNode, operation, extraData);
recurseElementWithPostOperation(_rootElement, operation, extraData);
}
// Recurses voxel element with an operation function
void Octree::recurseNodeWithOperation(OctreeElement* element, RecurseOctreeOperation operation, void* extraData,
void Octree::recurseElementWithOperation(OctreeElement* element, RecurseOctreeOperation operation, void* extraData,
int recursionCount) {
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
qDebug() << "Octree::recurseNodeWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
qDebug() << "Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
return;
}
@ -78,24 +78,24 @@ void Octree::recurseNodeWithOperation(OctreeElement* element, RecurseOctreeOpera
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
OctreeElement* child = element->getChildAtIndex(i);
if (child) {
recurseNodeWithOperation(child, operation, extraData, recursionCount+1);
recurseElementWithOperation(child, operation, extraData, recursionCount+1);
}
}
}
}
// Recurses voxel element with an operation function
void Octree::recurseNodeWithPostOperation(OctreeElement* element, RecurseOctreeOperation operation, void* extraData,
void Octree::recurseElementWithPostOperation(OctreeElement* element, RecurseOctreeOperation operation, void* extraData,
int recursionCount) {
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
qDebug() << "Octree::recurseNodeWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!\n";
qDebug() << "Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!\n";
return;
}
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
OctreeElement* child = element->getChildAtIndex(i);
if (child) {
recurseNodeWithPostOperation(child, operation, extraData, recursionCount+1);
recurseElementWithPostOperation(child, operation, extraData, recursionCount+1);
}
}
operation(element, extraData);
@ -106,15 +106,15 @@ void Octree::recurseNodeWithPostOperation(OctreeElement* element, RecurseOctreeO
void Octree::recurseTreeWithOperationDistanceSorted(RecurseOctreeOperation operation,
const glm::vec3& point, void* extraData) {
recurseNodeWithOperationDistanceSorted(_rootNode, operation, point, extraData);
recurseElementWithOperationDistanceSorted(_rootElement, operation, point, extraData);
}
// Recurses voxel element with an operation function
void Octree::recurseNodeWithOperationDistanceSorted(OctreeElement* element, RecurseOctreeOperation operation,
void Octree::recurseElementWithOperationDistanceSorted(OctreeElement* element, RecurseOctreeOperation operation,
const glm::vec3& point, void* extraData, int recursionCount) {
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
qDebug() << "Octree::recurseNodeWithOperationDistanceSorted() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
qDebug() << "Octree::recurseElementWithOperationDistanceSorted() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
return;
}
@ -126,36 +126,36 @@ void Octree::recurseNodeWithOperationDistanceSorted(OctreeElement* element, Recu
int currentCount = 0;
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
OctreeElement* childNode = element->getChildAtIndex(i);
if (childNode) {
OctreeElement* childElement = element->getChildAtIndex(i);
if (childElement) {
// chance to optimize, doesn't need to be actual distance!! Could be distance squared
float distanceSquared = childNode->distanceSquareToPoint(point);
//qDebug("recurseNodeWithOperationDistanceSorted() CHECKING child[%d] point=%f,%f center=%f,%f distance=%f...\n", i, point.x, point.y, center.x, center.y, distance);
//childNode->printDebugDetails("");
currentCount = insertIntoSortedArrays((void*)childNode, distanceSquared, i,
float distanceSquared = childElement->distanceSquareToPoint(point);
//qDebug("recurseElementWithOperationDistanceSorted() CHECKING child[%d] point=%f,%f center=%f,%f distance=%f...\n", i, point.x, point.y, center.x, center.y, distance);
//childElement->printDebugDetails("");
currentCount = insertIntoSortedArrays((void*)childElement, distanceSquared, i,
(void**)&sortedChildren, (float*)&distancesToChildren,
(int*)&indexOfChildren, currentCount, NUMBER_OF_CHILDREN);
}
}
for (int i = 0; i < currentCount; i++) {
OctreeElement* childNode = sortedChildren[i];
if (childNode) {
//qDebug("recurseNodeWithOperationDistanceSorted() PROCESSING child[%d] distance=%f...\n", i, distancesToChildren[i]);
//childNode->printDebugDetails("");
recurseNodeWithOperationDistanceSorted(childNode, operation, point, extraData);
OctreeElement* childElement = sortedChildren[i];
if (childElement) {
//qDebug("recurseElementWithOperationDistanceSorted() PROCESSING child[%d] distance=%f...\n", i, distancesToChildren[i]);
//childElement->printDebugDetails("");
recurseElementWithOperationDistanceSorted(childElement, operation, point, extraData);
}
}
}
}
void Octree::recurseTreeWithOperator(RecurseOctreeOperator* operatorObject) {
recurseNodeWithOperator(_rootNode, operatorObject);
recurseElementWithOperator(_rootElement, operatorObject);
}
bool Octree::recurseNodeWithOperator(OctreeElement* element, RecurseOctreeOperator* operatorObject, int recursionCount) {
bool Octree::recurseElementWithOperator(OctreeElement* element, RecurseOctreeOperator* operatorObject, int recursionCount) {
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
qDebug() << "Octree::recurseNodeWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
qDebug() << "Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
return false;
}
@ -163,7 +163,7 @@ bool Octree::recurseNodeWithOperator(OctreeElement* element, RecurseOctreeOperat
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
OctreeElement* child = element->getChildAtIndex(i);
if (child) {
if (!recurseNodeWithOperator(child, operatorObject, recursionCount + 1)) {
if (!recurseElementWithOperator(child, operatorObject, recursionCount + 1)) {
break; // stop recursing if operator returns false...
}
}
@ -174,62 +174,62 @@ bool Octree::recurseNodeWithOperator(OctreeElement* element, RecurseOctreeOperat
}
OctreeElement* Octree::nodeForOctalCode(OctreeElement* ancestorNode,
const unsigned char* needleCode, OctreeElement** parentOfFoundNode) const {
OctreeElement* Octree::nodeForOctalCode(OctreeElement* ancestorElement,
const unsigned char* needleCode, OctreeElement** parentOfFoundElement) const {
// special case for NULL octcode
if (!needleCode) {
return _rootNode;
return _rootElement;
}
// find the appropriate branch index based on this ancestorNode
// find the appropriate branch index based on this ancestorElement
if (*needleCode > 0) {
int branchForNeedle = branchIndexWithDescendant(ancestorNode->getOctalCode(), needleCode);
OctreeElement* childNode = ancestorNode->getChildAtIndex(branchForNeedle);
int branchForNeedle = branchIndexWithDescendant(ancestorElement->getOctalCode(), needleCode);
OctreeElement* childElement = ancestorElement->getChildAtIndex(branchForNeedle);
if (childNode) {
if (*childNode->getOctalCode() == *needleCode) {
if (childElement) {
if (*childElement->getOctalCode() == *needleCode) {
// If the caller asked for the parent, then give them that too...
if (parentOfFoundNode) {
*parentOfFoundNode = ancestorNode;
if (parentOfFoundElement) {
*parentOfFoundElement = ancestorElement;
}
// the fact that the number of sections is equivalent does not always guarantee
// that this is the same element, however due to the recursive traversal
// we know that this is our element
return childNode;
return childElement;
} else {
// we need to go deeper
return nodeForOctalCode(childNode, needleCode, parentOfFoundNode);
return nodeForOctalCode(childElement, needleCode, parentOfFoundElement);
}
}
}
// we've been given a code we don't have a element for
// return this element as the last created parent
return ancestorNode;
return ancestorElement;
}
// returns the element created!
OctreeElement* Octree::createMissingNode(OctreeElement* lastParentNode, const unsigned char* codeToReach) {
int indexOfNewChild = branchIndexWithDescendant(lastParentNode->getOctalCode(), codeToReach);
OctreeElement* Octree::createMissingElement(OctreeElement* lastParentElement, const unsigned char* codeToReach) {
int indexOfNewChild = branchIndexWithDescendant(lastParentElement->getOctalCode(), codeToReach);
// If this parent element is a leaf, then you know the child path doesn't exist, so deal with
// breaking up the leaf first, which will also create a child path
if (lastParentNode->requiresSplit()) {
lastParentNode->splitChildren();
} else if (!lastParentNode->getChildAtIndex(indexOfNewChild)) {
if (lastParentElement->requiresSplit()) {
lastParentElement->splitChildren();
} else if (!lastParentElement->getChildAtIndex(indexOfNewChild)) {
// we could be coming down a branch that was already created, so don't stomp on it.
lastParentNode->addChildAtIndex(indexOfNewChild);
lastParentElement->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->getChildAtIndex(indexOfNewChild)->getOctalCode() == *codeToReach) {
return lastParentNode->getChildAtIndex(indexOfNewChild);
if (*lastParentElement->getChildAtIndex(indexOfNewChild)->getOctalCode() == *codeToReach) {
return lastParentElement->getChildAtIndex(indexOfNewChild);
} else {
return createMissingNode(lastParentNode->getChildAtIndex(indexOfNewChild), codeToReach);
return createMissingElement(lastParentElement->getChildAtIndex(indexOfNewChild), codeToReach);
}
}
int Octree::readNodeData(OctreeElement* destinationNode, const unsigned char* nodeData, int bytesLeftToRead,
int Octree::readElementData(OctreeElement* destinationElement, const unsigned char* nodeData, int bytesLeftToRead,
ReadBitstreamToTreeParams& args) {
// give this destination element the child mask from the packet
const unsigned char ALL_CHILDREN_ASSUMED_TO_EXIST = 0xFF;
@ -241,26 +241,26 @@ int Octree::readNodeData(OctreeElement* destinationNode, const unsigned char* no
// check the colors mask to see if we have a child to color in
if (oneAtBit(colorInPacketMask, i)) {
// create the child if it doesn't exist
if (!destinationNode->getChildAtIndex(i)) {
destinationNode->addChildAtIndex(i);
if (destinationNode->isDirty()) {
if (!destinationElement->getChildAtIndex(i)) {
destinationElement->addChildAtIndex(i);
if (destinationElement->isDirty()) {
_isDirty = true;
}
}
OctreeElement* childNodeAt = destinationNode->getChildAtIndex(i);
OctreeElement* childElementAt = destinationElement->getChildAtIndex(i);
bool nodeIsDirty = false;
if (childNodeAt) {
bytesRead += childNodeAt->readElementDataFromBuffer(nodeData + bytesRead, bytesLeftToRead, args);
childNodeAt->setSourceUUID(args.sourceUUID);
if (childElementAt) {
bytesRead += childElementAt->readElementDataFromBuffer(nodeData + bytesRead, bytesLeftToRead, args);
childElementAt->setSourceUUID(args.sourceUUID);
// if we had a local version of the element already, it's possible that we have it already but
// with the same color data, so this won't count as a change. To address this we check the following
if (!childNodeAt->isDirty() && childNodeAt->getShouldRender() && !childNodeAt->isRendered()) {
childNodeAt->setDirtyBit(); // force dirty!
if (!childElementAt->isDirty() && childElementAt->getShouldRender() && !childElementAt->isRendered()) {
childElementAt->setDirtyBit(); // force dirty!
}
nodeIsDirty = childNodeAt->isDirty();
nodeIsDirty = childElementAt->isDirty();
}
if (nodeIsDirty) {
_isDirty = true;
@ -279,17 +279,17 @@ int Octree::readNodeData(OctreeElement* destinationNode, const unsigned char* no
// check the exists mask to see if we have a child to traverse into
if (oneAtBit(childMask, childIndex)) {
if (!destinationNode->getChildAtIndex(childIndex)) {
if (!destinationElement->getChildAtIndex(childIndex)) {
// add a child at that index, if it doesn't exist
destinationNode->addChildAtIndex(childIndex);
bool nodeIsDirty = destinationNode->isDirty();
destinationElement->addChildAtIndex(childIndex);
bool nodeIsDirty = destinationElement->isDirty();
if (nodeIsDirty) {
_isDirty = true;
}
}
// tell the child to read the subsequent data
bytesRead += readNodeData(destinationNode->getChildAtIndex(childIndex),
bytesRead += readElementData(destinationElement->getChildAtIndex(childIndex),
nodeData + bytesRead, bytesLeftToRead - bytesRead, args);
}
childIndex++;
@ -299,8 +299,8 @@ int Octree::readNodeData(OctreeElement* destinationNode, const unsigned char* no
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
// now also check the childrenInTreeMask, if the mask is missing the bit, then it means we need to delete this child
// subtree/element, because it shouldn't actually exist in the tree.
if (!oneAtBit(childrenInTreeMask, i) && destinationNode->getChildAtIndex(i)) {
destinationNode->safeDeepDeleteChildAtIndex(i);
if (!oneAtBit(childrenInTreeMask, i) && destinationElement->getChildAtIndex(i)) {
destinationElement->safeDeepDeleteChildAtIndex(i);
_isDirty = true; // by definition!
}
}
@ -314,24 +314,24 @@ void Octree::readBitstreamToTree(const unsigned char * bitstream, unsigned long
const unsigned char* bitstreamAt = bitstream;
// If destination element is not included, set it to root
if (!args.destinationNode) {
args.destinationNode = _rootNode;
if (!args.destinationElement) {
args.destinationElement = _rootElement;
}
// 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
// Keep looping through the buffer calling readElementData() this allows us to pack multiple root-relative Octal codes
// into a single network packet. readElementData() 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
while (bitstreamAt < bitstream + bufferSizeBytes) {
OctreeElement* bitstreamRootNode = nodeForOctalCode(args.destinationNode, (unsigned char *)bitstreamAt, NULL);
if (*bitstreamAt != *bitstreamRootNode->getOctalCode()) {
OctreeElement* bitstreamRootElement = nodeForOctalCode(args.destinationElement, (unsigned char *)bitstreamAt, NULL);
if (*bitstreamAt != *bitstreamRootElement->getOctalCode()) {
// if the octal code returned is not on the same level as
// the code being searched for, we have OctreeElements to create
// Note: we need to create this element relative to root, because we're assuming that the bitstream for the initial
// octal code is always relative to root!
bitstreamRootNode = createMissingNode(args.destinationNode, (unsigned char*) bitstreamAt);
if (bitstreamRootNode->isDirty()) {
bitstreamRootElement = createMissingElement(args.destinationElement, (unsigned char*) bitstreamAt);
if (bitstreamRootElement->isDirty()) {
_isDirty = true;
}
}
@ -340,7 +340,7 @@ void Octree::readBitstreamToTree(const unsigned char * bitstream, unsigned long
int theseBytesRead = 0;
theseBytesRead += octalCodeBytes;
theseBytesRead += readNodeData(bitstreamRootNode, bitstreamAt + octalCodeBytes,
theseBytesRead += readElementData(bitstreamRootElement, bitstreamAt + octalCodeBytes,
bufferSizeBytes - (bytesRead + octalCodeBytes), args);
// skip bitstream to new startPoint
@ -382,17 +382,17 @@ void Octree::deleteOctalCodeFromTree(const unsigned char* codeBuffer, bool colla
args.deleteLastChild = false;
args.pathChanged = false;
deleteOctalCodeFromTreeRecursion(_rootNode, &args);
deleteOctalCodeFromTreeRecursion(_rootElement, &args);
}
void Octree::deleteOctalCodeFromTreeRecursion(OctreeElement* element, void* extraData) {
DeleteOctalCodeFromTreeArgs* args = (DeleteOctalCodeFromTreeArgs*)extraData;
int lengthOfNodeCode = numberOfThreeBitSectionsInCode(element->getOctalCode());
int lengthOfElementCode = numberOfThreeBitSectionsInCode(element->getOctalCode());
// Since we traverse the tree in code order, we know that if our code
// matches, then we've reached our target element.
if (lengthOfNodeCode == args->lengthOfCode) {
if (lengthOfElementCode == args->lengthOfCode) {
// we've reached our target, depending on how we're called we may be able to operate on it
// it here, we need to recurse up, and delete it there. So we handle these cases the same to keep
// the logic consistent.
@ -402,30 +402,30 @@ void Octree::deleteOctalCodeFromTreeRecursion(OctreeElement* element, void* extr
// Ok, we know we haven't reached our target element yet, so keep looking
int childIndex = branchIndexWithDescendant(element->getOctalCode(), args->codeBuffer);
OctreeElement* childNode = element->getChildAtIndex(childIndex);
OctreeElement* childElement = element->getChildAtIndex(childIndex);
// If there is no child at the target location, and the current parent element is a colored leaf,
// then it means we were asked to delete a child out of a larger leaf voxel.
// We support this by breaking up the parent voxel into smaller pieces.
if (!childNode && element->requiresSplit()) {
if (!childElement && element->requiresSplit()) {
// we need to break up ancestors until we get to the right level
OctreeElement* ancestorNode = element;
OctreeElement* ancestorElement = element;
while (true) {
int index = branchIndexWithDescendant(ancestorNode->getOctalCode(), args->codeBuffer);
int index = branchIndexWithDescendant(ancestorElement->getOctalCode(), args->codeBuffer);
// we end up with all the children, even the one we want to delete
ancestorNode->splitChildren();
ancestorElement->splitChildren();
int lengthOfAncestorNode = numberOfThreeBitSectionsInCode(ancestorNode->getOctalCode());
int lengthOfAncestorElement = numberOfThreeBitSectionsInCode(ancestorElement->getOctalCode());
// If we've reached the parent of the target, then stop breaking up children
if (lengthOfAncestorNode == (args->lengthOfCode - 1)) {
if (lengthOfAncestorElement == (args->lengthOfCode - 1)) {
// since we created all the children when we split, we need to delete this target one
ancestorNode->deleteChildAtIndex(index);
ancestorElement->deleteChildAtIndex(index);
break;
}
ancestorNode = ancestorNode->getChildAtIndex(index);
ancestorElement = ancestorElement->getChildAtIndex(index);
}
_isDirty = true;
args->pathChanged = true;
@ -437,13 +437,13 @@ void Octree::deleteOctalCodeFromTreeRecursion(OctreeElement* element, void* extr
// if we don't have a child and we reach this point, then we actually know that the parent
// isn't a colored leaf, and the child branch doesn't exist, so there's nothing to do below and
// we can safely return, ending the recursion and unwinding
if (!childNode) {
if (!childElement) {
return;
}
// If we got this far then we have a child for the branch we're looking for, but we're not there yet
// recurse till we get there
deleteOctalCodeFromTreeRecursion(childNode, args);
deleteOctalCodeFromTreeRecursion(childElement, args);
// If the lower level determined it needs to be deleted, then we should delete now.
if (args->deleteLastChild) {
@ -459,7 +459,7 @@ void Octree::deleteOctalCodeFromTreeRecursion(OctreeElement* element, void* extr
// to delete this element. This will collapse the empty tree above us.
if (args->collapseEmptyTrees && element->getChildCount() == 0) {
// Can't delete the root this way.
if (element == _rootNode) {
if (element == _rootElement) {
args->deleteLastChild = false; // reset so that further up the unwinding chain we don't do anything
}
} else {
@ -475,8 +475,8 @@ void Octree::deleteOctalCodeFromTreeRecursion(OctreeElement* element, void* extr
}
void Octree::eraseAllOctreeElements() {
delete _rootNode; // this will recurse and delete all children
_rootNode = createNewElement();
delete _rootElement; // this will recurse and delete all children
_rootElement = createNewElement();
_isDirty = true;
}
@ -512,15 +512,15 @@ void Octree::processRemoveOctreeElementsBitstream(const unsigned char* bitstream
}
}
// Note: this is an expensive call. Don't call it unless you really need to reaverage the entire tree (from startNode)
void Octree::reaverageOctreeElements(OctreeElement* startNode) {
if (!startNode) {
startNode = getRoot();
// Note: this is an expensive call. Don't call it unless you really need to reaverage the entire tree (from startElement)
void Octree::reaverageOctreeElements(OctreeElement* startElement) {
if (!startElement) {
startElement = getRoot();
}
// if our tree is a reaveraging tree, then we do this, otherwise we don't do anything
if (_shouldReaverage) {
static int recursionCount;
if (startNode == _rootNode) {
if (startElement == _rootElement) {
recursionCount = 0;
} else {
recursionCount++;
@ -534,16 +534,16 @@ void Octree::reaverageOctreeElements(OctreeElement* startNode) {
bool hasChildren = false;
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
if (startNode->getChildAtIndex(i)) {
reaverageOctreeElements(startNode->getChildAtIndex(i));
if (startElement->getChildAtIndex(i)) {
reaverageOctreeElements(startElement->getChildAtIndex(i));
hasChildren = true;
}
}
// collapseIdenticalLeaves() returns true if it collapses the leaves
// in which case we don't need to set the average color
if (hasChildren && !startNode->collapseChildren()) {
startNode->calculateAverageFromChildren();
if (hasChildren && !startElement->collapseChildren()) {
startElement->calculateAverageFromChildren();
}
recursionCount--;
}
@ -551,7 +551,7 @@ void Octree::reaverageOctreeElements(OctreeElement* startNode) {
OctreeElement* Octree::getOctreeElementAt(float x, float y, float z, float s) const {
unsigned char* octalCode = pointToOctalCode(x,y,z,s);
OctreeElement* element = nodeForOctalCode(_rootNode, octalCode, NULL);
OctreeElement* element = nodeForOctalCode(_rootElement, octalCode, NULL);
if (*element->getOctalCode() != *octalCode) {
element = NULL;
}
@ -566,7 +566,7 @@ OctreeElement* Octree::getOctreeElementAt(float x, float y, float z, float s) co
OctreeElement* Octree::getOctreeEnclosingElementAt(float x, float y, float z, float s) const {
unsigned char* octalCode = pointToOctalCode(x,y,z,s);
OctreeElement* element = nodeForOctalCode(_rootNode, octalCode, NULL);
OctreeElement* element = nodeForOctalCode(_rootElement, octalCode, NULL);
delete[] octalCode; // cleanup memory
#ifdef HAS_AUDIT_CHILDREN
@ -1160,7 +1160,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
int currentCount = 0;
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
OctreeElement* childNode = element->getChildAtIndex(i);
OctreeElement* childElement = element->getChildAtIndex(i);
// if the caller wants to include childExistsBits, then include them even if not in view, if however,
// we're in a portion of the tree that's not our responsibility, then we assume the child nodes exist
@ -1171,61 +1171,61 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
}
if (params.includeExistsBits) {
// If the child is known to exist, OR, it's not my jurisdiction, then we mark the bit as existing
if (childNode || notMyJurisdiction) {
if (childElement || notMyJurisdiction) {
childrenExistInTreeBits += (1 << (7 - i));
}
}
if (params.wantOcclusionCulling) {
if (childNode) {
float distance = params.viewFrustum ? childNode->distanceToCamera(*params.viewFrustum) : 0;
if (childElement) {
float distance = params.viewFrustum ? childElement->distanceToCamera(*params.viewFrustum) : 0;
currentCount = insertIntoSortedArrays((void*)childNode, distance, i,
currentCount = insertIntoSortedArrays((void*)childElement, distance, i,
(void**)&sortedChildren, (float*)&distancesToChildren,
(int*)&indexOfChildren, currentCount, NUMBER_OF_CHILDREN);
}
} else {
sortedChildren[i] = childNode;
sortedChildren[i] = childElement;
indexOfChildren[i] = i;
distancesToChildren[i] = 0.0f;
currentCount++;
}
// track stats
// must check childNode here, because it could be we got here with no childNode
if (params.stats && childNode) {
params.stats->traversed(childNode);
// must check childElement here, because it could be we got here with no childElement
if (params.stats && childElement) {
params.stats->traversed(childElement);
}
}
// for each child element in Distance sorted order..., 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 < currentCount; i++) {
OctreeElement* childNode = sortedChildren[i];
OctreeElement* childElement = sortedChildren[i];
int originalIndex = indexOfChildren[i];
bool childIsInView = (childNode &&
bool childIsInView = (childElement &&
( !params.viewFrustum || // no view frustum was given, everything is assumed in view
(nodeLocationThisView == ViewFrustum::INSIDE) || // the parent was fully in view, we can assume ALL children are
(nodeLocationThisView == ViewFrustum::INTERSECT && childNode->isInView(*params.viewFrustum)) // the parent intersects and the child is in view
(nodeLocationThisView == ViewFrustum::INTERSECT && childElement->isInView(*params.viewFrustum)) // the parent intersects and the child is in view
));
if (!childIsInView) {
// must check childNode here, because it could be we got here because there was no childNode
if (params.stats && childNode) {
params.stats->skippedOutOfView(childNode);
// must check childElement here, because it could be we got here because there was no childElement
if (params.stats && childElement) {
params.stats->skippedOutOfView(childElement);
}
} else {
// Before we determine consider this further, let's see if it's in our LOD scope...
float distance = distancesToChildren[i]; // params.viewFrustum ? childNode->distanceToCamera(*params.viewFrustum) : 0;
float distance = distancesToChildren[i]; // params.viewFrustum ? childElement->distanceToCamera(*params.viewFrustum) : 0;
float boundaryDistance = !params.viewFrustum ? 1 :
boundaryDistanceForRenderLevel(childNode->getLevel() + params.boundaryLevelAdjust,
boundaryDistanceForRenderLevel(childElement->getLevel() + params.boundaryLevelAdjust,
params.octreeElementSizeScale);
if (!(distance < boundaryDistance)) {
// don't need to check childNode here, because we can't get here with no childNode
// don't need to check childElement here, because we can't get here with no childElement
if (params.stats) {
params.stats->skippedDistance(childNode);
params.stats->skippedDistance(childElement);
}
} else {
inViewCount++;
@ -1233,7 +1233,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
// 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 (!(childNode && childNode->isLeaf())) {
if (!(childElement && childElement->isLeaf())) {
childrenExistInPacketBits += (1 << (7 - originalIndex));
inViewNotLeafCount++;
}
@ -1241,10 +1241,10 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
bool childIsOccluded = false; // assume it's not occluded
// If the user also asked for occlusion culling, check if this element is occluded
if (params.wantOcclusionCulling && childNode->isLeaf()) {
if (params.wantOcclusionCulling && childElement->isLeaf()) {
// Don't check occlusion here, just add them to our distance ordered array...
AABox voxelBox = childNode->getAABox();
AABox voxelBox = childElement->getAABox();
voxelBox.scale(TREE_SCALE);
OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon(
params.viewFrustum->getProjectedPolygon(voxelBox));
@ -1273,18 +1273,18 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
bool shouldRender = !params.viewFrustum
? true
: childNode->calculateShouldRender(params.viewFrustum,
: childElement->calculateShouldRender(params.viewFrustum,
params.octreeElementSizeScale, params.boundaryLevelAdjust);
// track some stats
if (params.stats) {
// don't need to check childNode here, because we can't get here with no childNode
if (!shouldRender && childNode->isLeaf()) {
params.stats->skippedDistance(childNode);
// don't need to check childElement here, because we can't get here with no childElement
if (!shouldRender && childElement->isLeaf()) {
params.stats->skippedDistance(childElement);
}
// don't need to check childNode here, because we can't get here with no childNode
// don't need to check childElement here, because we can't get here with no childElement
if (childIsOccluded) {
params.stats->skippedOccluded(childNode);
params.stats->skippedOccluded(childElement);
}
}
@ -1292,11 +1292,11 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
if (shouldRender && !childIsOccluded) {
bool childWasInView = false;
if (childNode && params.deltaViewFrustum && params.lastViewFrustum) {
ViewFrustum::location location = childNode->inFrustum(*params.lastViewFrustum);
if (childElement && params.deltaViewFrustum && params.lastViewFrustum) {
ViewFrustum::location location = childElement->inFrustum(*params.lastViewFrustum);
// If we're a leaf, then either intersect or inside is considered "formerly in view"
if (childNode->isLeaf()) {
if (childElement->isLeaf()) {
childWasInView = location != ViewFrustum::OUTSIDE;
} else {
childWasInView = location == ViewFrustum::INSIDE;
@ -1308,18 +1308,18 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
// need to send it.
if (!childWasInView ||
(params.deltaViewFrustum &&
childNode->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))){
childElement->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))){
childrenColoredBits += (1 << (7 - originalIndex));
inViewWithColorCount++;
} else {
// otherwise just track stats of the items we discarded
// don't need to check childNode here, because we can't get here with no childNode
// don't need to check childElement here, because we can't get here with no childElement
if (params.stats) {
if (childWasInView) {
params.stats->skippedWasInView(childNode);
params.stats->skippedWasInView(childElement);
} else {
params.stats->skippedNoChange(childNode);
params.stats->skippedNoChange(childElement);
}
}
}
@ -1342,10 +1342,10 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
if (continueThisLevel && params.includeColor) {
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
if (oneAtBit(childrenColoredBits, i)) {
OctreeElement* childNode = element->getChildAtIndex(i);
if (childNode) {
OctreeElement* childElement = element->getChildAtIndex(i);
if (childElement) {
int bytesBeforeChild = packetData->getUncompressedSize();
continueThisLevel = childNode->appendElementData(packetData);
continueThisLevel = childElement->appendElementData(packetData);
int bytesAfterChild = packetData->getUncompressedSize();
if (!continueThisLevel) {
@ -1354,9 +1354,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
bytesAtThisLevel += (bytesAfterChild - bytesBeforeChild); // keep track of byte count for this child
// don't need to check childNode here, because we can't get here with no childNode
// don't need to check childElement here, because we can't get here with no childElement
if (params.stats) {
params.stats->colorSent(childNode);
params.stats->colorSent(childElement);
}
}
}
@ -1414,7 +1414,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
// for each child element in Distance sorted order..., 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 indexByDistance = 0; indexByDistance < currentCount; indexByDistance++) {
OctreeElement* childNode = sortedChildren[indexByDistance];
OctreeElement* childElement = sortedChildren[indexByDistance];
int originalIndex = indexOfChildren[indexByDistance];
if (oneAtBit(childrenExistInPacketBits, originalIndex)) {
@ -1435,7 +1435,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
// This only applies in the view frustum case, in other cases, like file save and copy/past where
// no viewFrustum was requested, we still want to recurse the child tree.
if (!params.viewFrustum || !oneAtBit(childrenColoredBits, originalIndex)) {
childTreeBytesOut = encodeTreeBitstreamRecursion(childNode, packetData, bag, params,
childTreeBytesOut = encodeTreeBitstreamRecursion(childElement, packetData, bag, params,
thisLevel, nodeLocationThisView);
}
@ -1634,7 +1634,7 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* element) {
if (element) {
nodeBag.insert(element);
} else {
nodeBag.insert(_rootNode);
nodeBag.insert(_rootElement);
}
static OctreePacketData packetData;
@ -1681,12 +1681,12 @@ bool Octree::countOctreeElementsOperation(OctreeElement* element, void* extraDat
return true; // keep going
}
void Octree::copySubTreeIntoNewTree(OctreeElement* startNode, Octree* destinationTree, bool rebaseToRoot) {
void Octree::copySubTreeIntoNewTree(OctreeElement* startElement, Octree* destinationTree, bool rebaseToRoot) {
OctreeElementBag nodeBag;
nodeBag.insert(startNode);
nodeBag.insert(startElement);
int chopLevels = 0;
if (rebaseToRoot) {
chopLevels = numberOfThreeBitSectionsInCode(startNode->getOctalCode());
chopLevels = numberOfThreeBitSectionsInCode(startElement->getOctalCode());
}
static OctreePacketData packetData;
@ -1701,28 +1701,12 @@ void Octree::copySubTreeIntoNewTree(OctreeElement* startNode, Octree* destinatio
ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS);
destinationTree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args);
}
// XXXBHG - what is this trying to do?
// This code appears to be trying to set the color of the destination root
// of a copy operation. But that shouldn't be necessary. I think this code might
// have been a hack that Mark added when he was trying to solve the copy of a single
// voxel bug. But this won't solve that problem, and doesn't appear to be needed for
// a normal copy operation. I'm leaving this in for a little bit until we see if anything
// about copy/paste is broken.
//
//OctreeElement* destinationStartNode;
//if (rebaseToRoot) {
// destinationStartNode = destinationTree->_rootNode;
//} else {
// destinationStartNode = nodeForOctalCode(destinationTree->_rootNode, startNode->getOctalCode(), NULL);
//}
//destinationStartNode->setColor(startNode->getColor());
}
void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinationNode) {
void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinationElement) {
OctreeElementBag nodeBag;
// If we were given a specific element, start from there, otherwise start from root
nodeBag.insert(sourceTree->_rootNode);
nodeBag.insert(sourceTree->_rootElement);
static OctreePacketData packetData;
@ -1737,7 +1721,7 @@ void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinat
// ask destination tree to read the bitstream
bool wantImportProgress = true;
ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, destinationNode, 0, SharedNodePointer(), wantImportProgress);
ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, destinationElement, 0, SharedNodePointer(), wantImportProgress);
readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args);
}
}

View file

@ -166,7 +166,7 @@ class ReadBitstreamToTreeParams {
public:
bool includeColor;
bool includeExistsBits;
OctreeElement* destinationNode;
OctreeElement* destinationElement;
QUuid sourceUUID;
SharedNodePointer sourceNode;
bool wantImportProgress;
@ -174,13 +174,13 @@ public:
ReadBitstreamToTreeParams(
bool includeColor = WANT_COLOR,
bool includeExistsBits = WANT_EXISTS_BITS,
OctreeElement* destinationNode = NULL,
OctreeElement* destinationElement = NULL,
QUuid sourceUUID = QUuid(),
SharedNodePointer sourceNode = SharedNodePointer(),
bool wantImportProgress = false) :
includeColor(includeColor),
includeExistsBits(includeExistsBits),
destinationNode(destinationNode),
destinationElement(destinationElement),
sourceUUID(sourceUUID),
sourceNode(sourceNode),
wantImportProgress(wantImportProgress)
@ -207,14 +207,14 @@ public:
virtual void update() { }; // nothing to do by default
OctreeElement* getRoot() { return _rootNode; }
OctreeElement* getRoot() { return _rootElement; }
void eraseAllOctreeElements();
void processRemoveOctreeElementsBitstream(const unsigned char* bitstream, int bufferSizeBytes);
void readBitstreamToTree(const unsigned char* bitstream, unsigned long int bufferSizeBytes, ReadBitstreamToTreeParams& args);
void deleteOctalCodeFromTree(const unsigned char* codeBuffer, bool collapseEmptyTrees = DONT_COLLAPSE);
void reaverageOctreeElements(OctreeElement* startNode = NULL);
void reaverageOctreeElements(OctreeElement* startElement = NULL);
void deleteOctreeElementAt(float x, float y, float z, float s);
@ -282,23 +282,23 @@ public:
unsigned long getOctreeElementsCount();
void copySubTreeIntoNewTree(OctreeElement* startNode, Octree* destinationTree, bool rebaseToRoot);
void copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinationNode);
void copySubTreeIntoNewTree(OctreeElement* startElement, Octree* destinationTree, bool rebaseToRoot);
void copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinationElement);
bool getShouldReaverage() const { return _shouldReaverage; }
void recurseNodeWithOperation(OctreeElement* element, RecurseOctreeOperation operation,
void recurseElementWithOperation(OctreeElement* element, RecurseOctreeOperation operation,
void* extraData, int recursionCount = 0);
/// Traverse child nodes of node applying operation in post-fix order
///
void recurseNodeWithPostOperation(OctreeElement* element, RecurseOctreeOperation operation,
void recurseElementWithPostOperation(OctreeElement* element, RecurseOctreeOperation operation,
void* extraData, int recursionCount = 0);
void recurseNodeWithOperationDistanceSorted(OctreeElement* element, RecurseOctreeOperation operation,
void recurseElementWithOperationDistanceSorted(OctreeElement* element, RecurseOctreeOperation operation,
const glm::vec3& point, void* extraData, int recursionCount = 0);
bool recurseNodeWithOperator(OctreeElement* element, RecurseOctreeOperator* operatorObject, int recursionCount = 0);
bool recurseElementWithOperator(OctreeElement* element, RecurseOctreeOperator* operatorObject, int recursionCount = 0);
bool getIsViewing() const { return _isViewing; }
void setIsViewing(bool isViewing) { _isViewing = isViewing; }
@ -321,12 +321,12 @@ protected:
static bool countOctreeElementsOperation(OctreeElement* element, void* extraData);
OctreeElement* nodeForOctalCode(OctreeElement* ancestorNode, const unsigned char* needleCode, OctreeElement** parentOfFoundNode) const;
OctreeElement* createMissingNode(OctreeElement* lastParentNode, const unsigned char* codeToReach);
int readNodeData(OctreeElement *destinationNode, const unsigned char* nodeData,
OctreeElement* nodeForOctalCode(OctreeElement* ancestorElement, const unsigned char* needleCode, OctreeElement** parentOfFoundElement) const;
OctreeElement* createMissingElement(OctreeElement* lastParentElement, const unsigned char* codeToReach);
int readElementData(OctreeElement *destinationElement, const unsigned char* nodeData,
int bufferSizeBytes, ReadBitstreamToTreeParams& args);
OctreeElement* _rootNode;
OctreeElement* _rootElement;
bool _isDirty;
bool _shouldReaverage;

View file

@ -12,7 +12,7 @@
#include "ParticleTree.h"
ParticleTree::ParticleTree(bool shouldReaverage) : Octree(shouldReaverage) {
_rootNode = createNewElement();
_rootElement = createNewElement();
}
ParticleTreeElement* ParticleTree::createNewElement(unsigned char * octalCode) {

View file

@ -29,7 +29,7 @@ public:
virtual ParticleTreeElement* createNewElement(unsigned char * octalCode = NULL);
/// Type safe version of getRoot()
ParticleTreeElement* getRoot() { return (ParticleTreeElement*)_rootNode; }
ParticleTreeElement* getRoot() { return static_cast<ParticleTreeElement*>(_rootElement); }
// These methods will allow the OctreeServer to send your tree inbound edit packets of your

View file

@ -23,13 +23,13 @@
VoxelTree::VoxelTree(bool shouldReaverage) : Octree(shouldReaverage)
{
_rootNode = createNewElement();
_rootElement = createNewElement();
}
VoxelTreeElement* VoxelTree::createNewElement(unsigned char * octalCode) {
VoxelSystem* voxelSystem = NULL;
if (_rootNode) {
voxelSystem = ((VoxelTreeElement*)_rootNode)->getVoxelSystem();
if (_rootElement) {
voxelSystem = (static_cast<VoxelTreeElement*>(_rootElement))->getVoxelSystem();
}
VoxelTreeElement* newElement = new VoxelTreeElement(octalCode);
newElement->setVoxelSystem(voxelSystem);

View file

@ -26,7 +26,7 @@ public:
VoxelTree(bool shouldReaverage = false);
virtual VoxelTreeElement* createNewElement(unsigned char * octalCode = NULL);
VoxelTreeElement* getRoot() { return (VoxelTreeElement*)_rootNode; }
VoxelTreeElement* getRoot() { return static_cast<VoxelTreeElement*>(_rootElement); }
void deleteVoxelAt(float x, float y, float z, float s);