Пример #1
0
OctreeElementPointer OctreeElement::getOrCreateChildElementContaining(const AABox& box) {
    OctreeElementPointer child = NULL;

    int childIndex = getMyChildContaining(box);

    // If getMyChildContaining() returns CHILD_UNKNOWN then it means that our level
    // is the correct level for this cube
    if (childIndex == CHILD_UNKNOWN) {
        return shared_from_this();
    }

    // Now, check if we have a child at that location
    child = getChildAtIndex(childIndex);
    if (!child) {
        child = addChildAtIndex(childIndex);
    }

    // if we've made a really small child, then go ahead and use that one.
    if (child->getScale() <= SMALLEST_REASONABLE_OCTREE_ELEMENT_SCALE) {
        return child;
    }

    // Now that we have the child to recurse down, let it answer the original question...
    return child->getOrCreateChildElementContaining(box);
}
Пример #2
0
// TODO: consider removing this, or switching to using getOrCreateChildElementContaining(const AACube& box)...
OctreeElementPointer OctreeElement::getOrCreateChildElementAt(float x, float y, float z, float s) {
    OctreeElementPointer child = NULL;
    // If the requested size is less than or equal to our scale, but greater than half our scale, then
    // we are the Element they are looking for.
    float ourScale = getScale();
    float halfOurScale = ourScale / 2.0f;

    if(s > ourScale) {
        qCDebug(octree, "UNEXPECTED -- OctreeElement::getOrCreateChildElementAt() s=[%f] > ourScale=[%f] ",
                (double)s, (double)ourScale);
    }

    if (s > halfOurScale) {
        return shared_from_this();
    }

    int childIndex = getMyChildContainingPoint(glm::vec3(x, y, z));

    // Now, check if we have a child at that location
    child = getChildAtIndex(childIndex);
    if (!child) {
        child = addChildAtIndex(childIndex);
    }

    // Now that we have the child to recurse down, let it answer the original question...
    return child->getOrCreateChildElementAt(x, y, z, s);
}
bool UpdateEntityOperator::postRecursion(OctreeElementPointer element) {
    // Post-recursion is the unwinding process. For this operation, while we
    // unwind we want to mark the path as being dirty if we changed it below.
    // We might have two paths, one for the old entity and one for the new entity.
    bool keepSearching = !_foundOld || !_foundNew;

    bool subtreeContainsOld = subTreeContainsOldEntity(element);
    bool subtreeContainsNew = subTreeContainsNewEntity(element);

    // As we unwind, if we're in either of these two paths, we mark our element
    // as dirty.
    if ((_foundOld && subtreeContainsOld) ||
            (_foundNew && subtreeContainsNew)) {
        element->markWithChangedTime();
    }

    // It's not OK to prune if we have the potential of deleting the original containig element.
    // because if we prune the containing element then new might end up reallocating the same memory later 
    // and that will confuse our logic.
    // 
    // it's ok to prune if:
    // 1) we're not removing the old
    // 2) we are removing the old, but this subtree doesn't contain the old
    // 3) we are removing the old, this subtree contains the old, but this element isn't a direct parent of _containingElement
    if (!_removeOld || !subtreeContainsOld || !element->isParentOf(_containingElement)) {
        EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
        entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves
    }
    
    return keepSearching; // if we haven't yet found it, keep looking
}
Пример #4
0
// does this entity tree element contain the old entity
bool MovingEntitiesOperator::shouldRecurseSubTree(const OctreeElementPointer& element) {
    bool containsEntity = false;

    // If we don't have an old entity, then we don't contain the entity, otherwise
    // check the bounds
    if (_entitiesToMove.size() > 0) {
        const AACube& elementCube = element->getAACube();
        int detailIndex = 0;
        foreach(const EntityToMoveDetails& details, _entitiesToMove) {

            if (_wantDebug) {
                qCDebug(entities) << "MovingEntitiesOperator::shouldRecurseSubTree() details["<< detailIndex <<"]-----------------------------";
                qCDebug(entities) << "    element:" << element->getAACube();
                qCDebug(entities) << "    details.entity:" << details.entity->getEntityItemID();
                qCDebug(entities) << "    details.oldContainingElementCube:" << details.oldContainingElementCube;
                qCDebug(entities) << "    details.newCube:" << details.newCube;
                qCDebug(entities) << "    details.newCubeClamped:" << details.newCubeClamped;
                qCDebug(entities) << "    elementCube.contains(details.newCube)" << elementCube.contains(details.newCube);
                qCDebug(entities) << "    elementCube.contains(details.newCubeClamped)" << elementCube.contains(details.newCubeClamped);
                qCDebug(entities) << "--------------------------------------------------------------------------";
            }

            if (elementCube.contains(details.oldContainingElementCube) || elementCube.contains(details.newCubeClamped)) {
                containsEntity = true;
                break; // if it contains at least one, we're good to go
            }
            detailIndex++;
        }
    }
    return containsEntity;
}
Пример #5
0
bool AddEntityOperator::postRecursion(const OctreeElementPointer& element) {
    // Post-recursion is the unwinding process. For this operation, while we
    // unwind we want to mark the path as being dirty if we changed it below.
    // We might have two paths, one for the old entity and one for the new entity.
    bool keepSearching = !_foundNew;

    // As we unwind, if we're in either of these two paths, we mark our element
    // as dirty.
    if ((_foundNew && element->getAACube().contains(_newEntityBox))) {
        element->markWithChangedTime();
    }
    return keepSearching; // if we haven't yet found it, keep looking
}
Пример #6
0
void OctreeElement::deleteChildAtIndex(int childIndex) {
    OctreeElementPointer childAt = getChildAtIndex(childIndex);
    if (childAt) {
        childAt.reset();
        setChildAtIndex(childIndex, NULL);
        _isDirty = true;
        markWithChangedTime();

        // after deleting the child, check to see if we're a leaf
        if (isLeaf()) {
            _voxelNodeLeafCount++;
        }
    }
}
Пример #7
0
bool OctreeRenderer::renderOperation(OctreeElementPointer element, void* extraData) {
    RenderArgs* args = static_cast<RenderArgs*>(extraData);
    if (element->isInView(*args->_viewFrustum)) {
        if (element->hasContent()) {
            if (element->calculateShouldRender(args->_viewFrustum, args->_sizeScale, args->_boundaryLevelAdjust)) {
                args->_renderer->renderElement(element, args);
            } else {
                return false; // if we shouldn't render, then we also should stop recursing.
            }
        }
        return true; // continue recursing
    }
    // if not in view stop recursing
    return false;
}
bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElementPointer element) {
    bool elementContainsNewBox = element->getAACube().contains(_newEntityBox);

    if (_wantDebug) {
        bool elementContainsNewCube = element->getAACube().contains(_newEntityCube);
        qCDebug(entities) << "UpdateEntityOperator::subTreeContainsNewEntity()....";
        qCDebug(entities) << "    element->getAACube()=" << element->getAACube();
        qCDebug(entities) << "    _newEntityCube=" << _newEntityCube;
        qCDebug(entities) << "    _newEntityBox=" << _newEntityBox;
        qCDebug(entities) << "    elementContainsNewCube=" << elementContainsNewCube;
        qCDebug(entities) << "    elementContainsNewBox=" << elementContainsNewBox;
    }

    return elementContainsNewBox;
}
Пример #9
0
bool AddEntityOperator::preRecursion(const OctreeElementPointer& element) {
    EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);

    // In Pre-recursion, we're generally deciding whether or not we want to recurse this
    // path of the tree. For this operation, we want to recurse the branch of the tree if
    // any of the following are true:
    //   * We have not yet found the location for the new entity, and this branch contains the bounds of the new entity
    
    bool keepSearching = false; // assume we don't need to search any more
    
    // If we haven't yet found the new entity,  and this subTreeContains our new
    // entity, then we need to keep searching.
    if (!_foundNew && element->getAACube().contains(_newEntityBox)) {

        // If this element is the best fit for the new entity properties, then add/or update it
        if (entityTreeElement->bestFitBounds(_newEntityBox)) {
            _tree->addEntityMapEntry(_newEntity);
            entityTreeElement->addEntityItem(_newEntity);
            _foundNew = true;
            keepSearching = false;
        } else {
            keepSearching = true;
        }
    }
    
    return keepSearching; // if we haven't yet found it, keep looking
}
Пример #10
0
void OctreeElement::deleteAllChildren() {
    // first delete all the OctreeElement objects...
    for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
        OctreeElementPointer childAt = getChildAtIndex(i);
        if (childAt) {
            childAt.reset();
        }
    }

    if (_childrenExternal) {
        // if the children_t union represents _children.external we need to delete it here
        for (int i = 0; i < NUMBER_OF_CHILDREN; i ++) {
            _externalChildren[i].reset();
        }
    }
}
// does this entity tree element contain the old entity
bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElementPointer element) {

    // We've found cases where the old entity might be placed in an element that is not actually the best fit
    // so when we're searching the tree for the old element, we use the known cube for the known containing element
    bool elementContainsOldBox = element->getAACube().contains(_containingElementCube);

    if (_wantDebug) {
        bool elementContainsOldCube = element->getAACube().contains(_oldEntityCube);
        qCDebug(entities) << "UpdateEntityOperator::subTreeContainsOldEntity()....";
        qCDebug(entities) << "    element->getAACube()=" << element->getAACube();
        qCDebug(entities) << "    _oldEntityCube=" << _oldEntityCube;
        qCDebug(entities) << "    _oldEntityBox=" << _oldEntityBox;
        qCDebug(entities) << "    elementContainsOldCube=" << elementContainsOldCube;
        qCDebug(entities) << "    elementContainsOldBox=" << elementContainsOldBox;
    }
    return elementContainsOldBox;
}
Пример #12
0
void OctreeSceneStats::didntFit(const OctreeElementPointer element) {
    _didntFit++;
    if (element->isLeaf()) {
        _leavesDidntFit++;
    } else {
        _internalDidntFit++;
    }
}
Пример #13
0
void OctreeSceneStats::colorSent(const OctreeElementPointer element) {
    _colorSent++;
    if (element->isLeaf()) {
        _leavesColorSent++;
    } else {
        _internalColorSent++;
    }
}
Пример #14
0
void OctreeSceneStats::skippedOccluded(const OctreeElementPointer element) {
    _skippedOccluded++;
    if (element->isLeaf()) {
        _leavesSkippedOccluded++;
    } else {
        _internalSkippedOccluded++;
    }
}
Пример #15
0
void OctreeSceneStats::traversed(const OctreeElementPointer element) {
    _traversed++;
    if (element->isLeaf()) {
        _leaves++;
    } else {
        _internal++;
    }
}
Пример #16
0
OctreeElementPointer AddEntityOperator::possiblyCreateChildAt(const OctreeElementPointer& element, int childIndex) {
    // If we're getting called, it's because there was no child element at this index while recursing.
    // We only care if this happens while still searching for the new entity location.
    // Check to see if 
    if (!_foundNew) {
        float childElementScale = element->getAACube().getScale() / 2.0f; // all of our children will be half our scale
        // if the scale of our desired cube is smaller than our children, then consider making a child
        if (_newEntityBox.getLargestDimension() <= childElementScale) {
            int indexOfChildContainingNewEntity = element->getMyChildContaining(_newEntityBox);
        
            if (childIndex == indexOfChildContainingNewEntity) {
                return element->addChildAtIndex(childIndex);
            }
        }
    }
    return NULL; 
}
OctreeElementPointer UpdateEntityOperator::possiblyCreateChildAt(OctreeElementPointer element, int childIndex) { 
    // If we're getting called, it's because there was no child element at this index while recursing.
    // We only care if this happens while still searching for the new entity location.
    // Check to see if 
    if (!_foundNew) {
        float childElementScale = element->getScale() / 2.0f; // all of our children will be half our scale
        
        // Note: because the entity's bounds might have been clamped to the domain. We want to check if the
        // bounds of the clamped box would fit in our child elements. It may be the case that the actual
        // bounds of the element would hang outside of the child elements cells.
        bool entityWouldFitInChild = _newEntityBox.getLargestDimension() <= childElementScale;

        // if the scale of our desired cube is smaller than our children, then consider making a child
        if (entityWouldFitInChild) {
            int indexOfChildContainingNewEntity = element->getMyChildContaining(_newEntityBox);

            if (childIndex == indexOfChildContainingNewEntity) {
                return element->addChildAtIndex(childIndex);;
            }
        }
    }
    return NULL; 
}
Пример #18
0
// handles staging or deletion of all deep children
bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCount) {
    bool deleteApproved = false;
    if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
        static QString repeatedMessage
            = LogHandler::getInstance().addRepeatedMessageRegex(
                    "OctreeElement::safeDeepDeleteChildAtIndex\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!");

        qCDebug(octree) << "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
        return deleteApproved;
    }
    OctreeElementPointer childToDelete = getChildAtIndex(childIndex);
    if (childToDelete) {
        if (childToDelete->deleteApproved()) {
            // If the child is not a leaf, then call ourselves recursively on all the children
            if (!childToDelete->isLeaf()) {
                // delete all it's children
                for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
                    if (childToDelete->getChildAtIndex(i)) {
                        deleteApproved = childToDelete->safeDeepDeleteChildAtIndex(i,recursionCount+1);
                        if (!deleteApproved) {
                            break; // no point in continuing...
                        }
                    }
                }
            } else {
                deleteApproved = true; // because we got here after checking that delete was approved
            }
            if (deleteApproved) {
                deleteChildAtIndex(childIndex);
                _isDirty = true;
                markWithChangedTime();
            }
        }
    }
    return deleteApproved;
}
Пример #19
0
// does this entity tree element contain the old entity
bool DeleteEntityOperator::subTreeContainsSomeEntitiesToDelete(const OctreeElementPointer& element) {
    bool containsEntity = false;

    // If we don't have an old entity, then we don't contain the entity, otherwise
    // check the bounds
    if (_entitiesToDelete.size() > 0) {
        const AACube& elementCube = element->getAACube();
        foreach(const EntityToDeleteDetails& details, _entitiesToDelete) {
            if (elementCube.contains(details.cube)) {
                containsEntity = true;
                break; // if it contains at least one, we're good to go
            }
        }
    }
    return containsEntity;
}
bool DirtyOctreeElementOperator::postRecursion(const OctreeElementPointer& element) {
    element->markWithChangedTime();
    return true;
}
bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) {
    EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
    
    // In Pre-recursion, we're generally deciding whether or not we want to recurse this
    // path of the tree. For this operation, we want to recurse the branch of the tree if
    // and of the following are true:
    //   * We have not yet found the old entity, and this branch contains our old entity
    //   * We have not yet found the new entity, and this branch contains our new entity
    //
    // Note: it's often the case that the branch in question contains both the old entity
    // and the new entity.
    
    bool keepSearching = false; // assume we don't need to search any more

    bool subtreeContainsOld = subTreeContainsOldEntity(element);
    bool subtreeContainsNew = subTreeContainsNewEntity(element);

    if (_wantDebug) {
        qCDebug(entities) << "---- UpdateEntityOperator::preRecursion().... ----";
        qCDebug(entities) << "    element=" << element->getAACube();
        qCDebug(entities) << "    subtreeContainsOld=" << subtreeContainsOld;
        qCDebug(entities) << "    subtreeContainsNew=" << subtreeContainsNew;
        qCDebug(entities) << "    _foundOld=" << _foundOld;
        qCDebug(entities) << "    _foundNew=" << _foundNew;
    }

    // If we haven't yet found the old entity, and this subTreeContains our old
    // entity, then we need to keep searching.
    if (!_foundOld && subtreeContainsOld) {

        if (_wantDebug) {
            qCDebug(entities) << "    OLD TREE CASE....";
            qCDebug(entities) << "    entityTreeElement=" << entityTreeElement.get();
            qCDebug(entities) << "    _containingElement=" << _containingElement.get();
        }

        // If this is the element we're looking for, then ask it to remove the old entity
        // and we can stop searching.
        if (entityTreeElement == _containingElement) {

            if (_wantDebug) {
                qCDebug(entities) << "    *** it's the OLD ELEMENT! ***";
            }

            // If the containgElement IS NOT the best fit for the new entity properties
            // then we need to remove it, and the updateEntity below will store it in the
            // correct element.
            if (_removeOld) {

                if (_wantDebug) {
                    qCDebug(entities) << "    *** REMOVING from ELEMENT ***";
                }

                // the entity knows what element it's in, so we remove it from that one
                // NOTE: we know we haven't yet added it to its new element because _removeOld is true
                EntityTreeElementPointer oldElement = _existingEntity->getElement();
                oldElement->removeEntityItem(_existingEntity);
                _tree->setContainingElement(_entityItemID, NULL);

                if (oldElement != _containingElement) {
                    qCDebug(entities) << "WARNING entity moved during UpdateEntityOperator recursion";
                    _containingElement->removeEntityItem(_existingEntity);
                }

                if (_wantDebug) {
                    qCDebug(entities) << "    *** REMOVING from MAP ***";
                }
            }
            _foundOld = true;
        } else {
            // if this isn't the element we're looking for, then keep searching
            keepSearching = true;
        }
    }

    // If we haven't yet found the new entity,  and this subTreeContains our new
    // entity, then we need to keep searching.
    if (!_foundNew && subtreeContainsNew) {

        if (_wantDebug) {
            qCDebug(entities) << "    NEW TREE CASE....";
            qCDebug(entities) << "    entityTreeElement=" << entityTreeElement.get();
            qCDebug(entities) << "    _containingElement=" << _containingElement.get();
            qCDebug(entities) << "    entityTreeElement->bestFitBounds(_newEntityBox)=" << entityTreeElement->bestFitBounds(_newEntityBox);
        }

        // If this element is the best fit for the new entity properties, then add/or update it
        if (entityTreeElement->bestFitBounds(_newEntityBox)) {

            if (_wantDebug) {
                qCDebug(entities) << "    *** THIS ELEMENT IS BEST FIT ***";
            }

            EntityTreeElementPointer oldElement = _existingEntity->getElement();
            // if we are the existing containing element, then we can just do the update of the entity properties
            if (entityTreeElement == oldElement) {

                if (_wantDebug) {
                    qCDebug(entities) << "    *** This is the same OLD ELEMENT ***";
                }
            
                // set the entity properties and mark our element as changed.
                _existingEntity->setProperties(_properties);
                if (_wantDebug) {
                    qCDebug(entities) << "    *** set properties ***";
                }
            } else {
                // otherwise, this is an add case.
                if (oldElement) {
                    oldElement->removeEntityItem(_existingEntity);
                    if (oldElement != _containingElement) {
                        qCDebug(entities) << "WARNING entity moved during UpdateEntityOperator recursion";
                    }
                }
                entityTreeElement->addEntityItem(_existingEntity);
                _tree->setContainingElement(_entityItemID, entityTreeElement);

                _existingEntity->setProperties(_properties); // still need to update the properties!
                if (_wantDebug) {
                    qCDebug(entities) << "    *** ADDING ENTITY to ELEMENT and MAP and SETTING PROPERTIES ***";
                }
            }
            _foundNew = true; // we found the new element
            _removeOld = false; // and it has already been removed from the old
        } else {
            keepSearching = true;
        }
    }

    if (_wantDebug) {
        qCDebug(entities) << "    FINAL --- keepSearching=" << keepSearching;
        qCDebug(entities) << "--------------------------------------------------";
    }

    
    return keepSearching; // if we haven't yet found it, keep looking
}
bool DirtyOctreeElementOperator::preRecursion(const OctreeElementPointer& element) {
    if (element == _element) {
        return false;
    }
    return element->getAACube().contains(_point);
}
Пример #23
0
void OctreeElementBag::insert(OctreeElementPointer element) {
    _bagElements[element.get()] = element;
}