コード例 #1
0
ファイル: EntityTreeElement.cpp プロジェクト: JamesLinus/hifi
void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params) {

    OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
    assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
    // Check to see if this element yet has encode data... if it doesn't create it
    if (!extraEncodeData->contains(this)) {
        EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData = new EntityTreeElementExtraEncodeData();
        entityTreeElementExtraEncodeData->elementCompleted = (_entityItems.size() == 0);
        for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
            EntityTreeElementPointer child = getChildAtIndex(i);
            if (!child) {
                entityTreeElementExtraEncodeData->childCompleted[i] = true; // if no child exists, it is completed
            } else {
                if (child->hasEntities()) {
                    entityTreeElementExtraEncodeData->childCompleted[i] = false; // HAS ENTITIES NEEDS ENCODING
                } else {
                    entityTreeElementExtraEncodeData->childCompleted[i] = true; // child doesn't have enities, it is completed
                }
            }
        }
        forEachEntity([&](EntityItemPointer entity) {
            entityTreeElementExtraEncodeData->entities.insert(entity->getEntityItemID(), entity->getEntityProperties(params));
        });

        // TODO: some of these inserts might be redundant!!!
        extraEncodeData->insert(this, entityTreeElementExtraEncodeData);
    }
}
コード例 #2
0
ファイル: OctreeElement.cpp プロジェクト: rabedik/hifi
OctreeElement* OctreeElement::getOrCreateChildElementContaining(const AABox& box) {
    OctreeElement* 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 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);
}
コード例 #3
0
ファイル: OctreeElement.cpp プロジェクト: rabedik/hifi
// TODO: consider removing this, or switching to using getOrCreateChildElementContaining(const AACube& box)...
OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float z, float s) {
    OctreeElement* 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 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);
}
コード例 #4
0
ファイル: EntityTreeElement.cpp プロジェクト: JamesLinus/hifi
bool EntityTreeElement::shouldRecurseChildTree(int childIndex, EncodeBitstreamParams& params) const {
    EntityTreeElementPointer childElement = getChildAtIndex(childIndex);
    if (childElement->alreadyFullyEncoded(params)) {
        return false;
    }

    return true; // if we don't know otherwise than recurse!
}
コード例 #5
0
ファイル: OctreeElement.cpp プロジェクト: rabedik/hifi
bool OctreeElement::isParentOf(OctreeElement* possibleChild) const {
    if (possibleChild) {
        for (int childIndex = 0; childIndex < NUMBER_OF_CHILDREN; childIndex++) {
            OctreeElement* childAt = getChildAtIndex(childIndex);
            if (childAt == possibleChild) {
                return true;
            }
        }
    }
    return false;
}
コード例 #6
0
ファイル: VoxelTreeElement.cpp プロジェクト: MojoK/hifi
// will detect if children are leaves AND the same color
// and in that case will delete the children and make this node
// a leaf, returns TRUE if all the leaves are collapsed into a
// single node
bool VoxelTreeElement::collapseChildren() {
    // scan children, verify that they are ALL present and accounted for
    bool allChildrenMatch = true; // assume the best (ottimista)
    int red,green,blue;
    for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
        VoxelTreeElement* childAt = getChildAtIndex(i);
        // if no child, child isn't a leaf, or child doesn't have a color
        if (!childAt || !childAt->isLeaf() || !childAt->isColored()) {
            allChildrenMatch=false;
            //qDebug("SADNESS child missing or not colored! i=%d\n",i);
            break;
        } else {
            if (i==0) {
                red   = childAt->getColor()[0];
                green = childAt->getColor()[1];
                blue  = childAt->getColor()[2];
            } else if (red != childAt->getColor()[0] ||
                    green != childAt->getColor()[1] || blue != childAt->getColor()[2]) {
                allChildrenMatch=false;
                break;
            }
        }
    }


    if (allChildrenMatch) {
        //qDebug("allChildrenMatch: pruning tree\n");
        for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
            OctreeElement* childAt = getChildAtIndex(i);
            delete childAt; // delete all the child nodes
            setChildAtIndex(i, NULL); // set it to NULL
        }
        nodeColor collapsedColor;
        collapsedColor[0]=red;
        collapsedColor[1]=green;
        collapsedColor[2]=blue;
        collapsedColor[3]=1;    // color is set
        setColor(collapsedColor);
    }
    return allChildrenMatch;
}
コード例 #7
0
ファイル: OctreeTests.cpp プロジェクト: AlexanderOtavka/hifi
void OctreeTests::elementAddChildTests() {
    EntityTreePointer tree = std::make_shared<EntityTree>();
    auto elem = tree->createNewElement();
    QCOMPARE((bool)elem->getChildAtIndex(0), false);
    elem->addChildAtIndex(0);
    QCOMPARE((bool)elem->getChildAtIndex(0), true);

    const int MAX_CHILD_INDEX = 8;
    for (int i = 0; i < MAX_CHILD_INDEX; i++) {
        for (int j = 0; j < MAX_CHILD_INDEX; j++) {
            auto e = tree->createNewElement();

            // add a single child.
            auto firstChild = e->addChildAtIndex(i);
            QCOMPARE(e->getChildAtIndex(i), firstChild);

            if (i != j) {
                // add a second child.
                auto secondChild = e->addChildAtIndex(j);
                QCOMPARE(e->getChildAtIndex(i), firstChild);
                QCOMPARE(e->getChildAtIndex(j), secondChild);

                // remove scecond child.
                e->removeChildAtIndex(j);

                QCOMPARE((bool)e->getChildAtIndex(j), false);
            }

            QCOMPARE(e->getChildAtIndex(i), firstChild);
        }
    }
}
コード例 #8
0
ファイル: OctreeElement.cpp プロジェクト: rabedik/hifi
void OctreeElement::deleteAllChildren() {
    // first delete all the OctreeElement objects...
    for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
        OctreeElement* childAt = getChildAtIndex(i);
        if (childAt) {
            delete childAt;
        }
    }

    if (_childrenExternal) {
        // if the children_t union represents _children.external we need to delete it here
        delete[] _children.external;
    }
}
コード例 #9
0
ファイル: OctreeElement.cpp プロジェクト: rabedik/hifi
// does not delete the node!
OctreeElement* OctreeElement::removeChildAtIndex(int childIndex) {
    OctreeElement* returnedChild = getChildAtIndex(childIndex);
    if (returnedChild) {
        setChildAtIndex(childIndex, NULL);
        _isDirty = true;
        markWithChangedTime();

        // after removing the child, check to see if we're a leaf
        if (isLeaf()) {
            _voxelNodeLeafCount++;
        }
    }
    return returnedChild;
}
コード例 #10
0
ファイル: OctreeElement.cpp プロジェクト: rabedik/hifi
void OctreeElement::deleteChildAtIndex(int childIndex) {
    OctreeElement* childAt = getChildAtIndex(childIndex);
    if (childAt) {
        delete childAt;
        setChildAtIndex(childIndex, NULL);
        _isDirty = true;
        markWithChangedTime();

        // after deleting the child, check to see if we're a leaf
        if (isLeaf()) {
            _voxelNodeLeafCount++;
        }
    }
}
コード例 #11
0
void AccessibilityUIElement::childAtIndexCallback(const CppArgumentList& arguments, CppVariant* result)
{
    if (!arguments.size() || !arguments[0].isNumber()) {
        result->setNull();
        return;
    }

    AccessibilityUIElement* child = getChildAtIndex(arguments[0].toInt32());
    if (!child) {
        result->setNull();
        return;
    }

    result->set(*(child->getAsCppVariant()));
}
コード例 #12
0
ファイル: OctreeElement.cpp プロジェクト: rabedik/hifi
OctreeElement* OctreeElement::addChildAtIndex(int childIndex) {
    OctreeElement* childAt = getChildAtIndex(childIndex);
    if (!childAt) {
        // before adding a child, see if we're currently a leaf
        if (isLeaf()) {
            _voxelNodeLeafCount--;
        }

        unsigned char* newChildCode = childOctalCode(getOctalCode(), childIndex);
        childAt = createNewElement(newChildCode);
        setChildAtIndex(childIndex, childAt);

        _isDirty = true;
        markWithChangedTime();
    }
    return childAt;
}
コード例 #13
0
ファイル: VoxelTreeElement.cpp プロジェクト: MojoK/hifi
// will average the child colors...
void VoxelTreeElement::calculateAverageFromChildren() {
    int colorArray[4] = {0,0,0,0};
    float density = 0.0f;
    for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
        VoxelTreeElement* childAt = getChildAtIndex(i);
        if (childAt && childAt->isColored()) {
            for (int j = 0; j < 3; j++) {
                colorArray[j] += childAt->getTrueColor()[j]; // color averaging should always be based on true colors
            }
            colorArray[3]++;
        }
        if (childAt) {
            density += childAt->getDensity();
        }
    }
    density /= (float) NUMBER_OF_CHILDREN;
    //
    //  The VISIBLE_ABOVE_DENSITY sets the density of matter above which an averaged color voxel will
    //  be set.  It is an important physical constant in our universe.  A number below 0.5 will cause
    //  things to get 'fatter' at a distance, because upward averaging will make larger voxels out of
    //  less data, which is (probably) going to be preferable because it gives a sense that there is
    //  something out there to go investigate.   A number above 0.5 would cause the world to become
    //  more 'empty' at a distance.  Exactly 0.5 would match the physical world, at least for materials
    //  that are not shiny and have equivalent ambient reflectance.
    //
    const float VISIBLE_ABOVE_DENSITY = 0.10f;
    nodeColor newColor = { 0, 0, 0, 0};
    if (density > VISIBLE_ABOVE_DENSITY) {
        // The density of material in the space of the voxel sets whether it is actually colored
        for (int c = 0; c < 3; c++) {
            // set the average color value
            newColor[c] = colorArray[c] / colorArray[3];
        }
        // set the alpha to 1 to indicate that this isn't transparent
        newColor[3] = 1;
    }
    //  Set the color from the average of the child colors, and update the density
    setColor(newColor);
    setDensity(density);
}
コード例 #14
0
ファイル: OctreeElement.cpp プロジェクト: rabedik/hifi
void OctreeElement::printDebugDetails(const char* label) const {
    unsigned char childBits = 0;
    for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
        OctreeElement* childAt = getChildAtIndex(i);
        if (childAt) {
            setAtBit(childBits,i);
        }
    }

    QDebug elementDebug = qDebug().nospace();

    QString resultString;
    resultString.sprintf("%s - Voxel at corner=(%f,%f,%f) size=%f\n isLeaf=%s isDirty=%s shouldRender=%s\n children=", label,
                         (double)_cube.getCorner().x, (double)_cube.getCorner().y, (double)_cube.getCorner().z,
                         (double)_cube.getScale(),
                         debug::valueOf(isLeaf()), debug::valueOf(isDirty()), debug::valueOf(getShouldRender()));
    elementDebug << resultString;

    outputBits(childBits, &elementDebug);
    qDebug("octalCode=");
    printOctalCode(getOctalCode());
}
コード例 #15
0
ファイル: OctreeElement.cpp プロジェクト: rabedik/hifi
// 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;
    }
    OctreeElement* 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;
}
コード例 #16
0
ファイル: EntityTreeElement.cpp プロジェクト: RyanDowne/hifi
OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData* packetData, 
                                                                    EncodeBitstreamParams& params) const {

    OctreeElement::AppendState appendElementState = OctreeElement::COMPLETED; // assume the best...
    
    // first, check the params.extraEncodeData to see if there's any partial re-encode data for this element
    OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
    EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData = NULL;
    bool hadElementExtraData = false;
    if (extraEncodeData && extraEncodeData->contains(this)) {
        entityTreeElementExtraEncodeData = static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
        hadElementExtraData = true;
    } else {
        // if there wasn't one already, then create one
        entityTreeElementExtraEncodeData = new EntityTreeElementExtraEncodeData();
        entityTreeElementExtraEncodeData->elementCompleted = (_entityItems->size() == 0);

        for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
            EntityTreeElement* child = getChildAtIndex(i);
            if (!child) {
                entityTreeElementExtraEncodeData->childCompleted[i] = true; // if no child exists, it is completed
            } else {
                if (child->hasEntities()) {
                    entityTreeElementExtraEncodeData->childCompleted[i] = false;
                } else {
                    entityTreeElementExtraEncodeData->childCompleted[i] = true; // if the child doesn't have enities, it is completed
                }
            }
        }
        for (uint16_t i = 0; i < _entityItems->size(); i++) {
            EntityItem* entity = (*_entityItems)[i];
            entityTreeElementExtraEncodeData->entities.insert(entity->getEntityItemID(), entity->getEntityProperties(params));
        }
    }

    //assert(extraEncodeData);
    //assert(extraEncodeData->contains(this));
    //entityTreeElementExtraEncodeData = static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));

    LevelDetails elementLevel = packetData->startLevel();

    // write our entities out... first determine which of the entities are in view based on our params
    uint16_t numberOfEntities = 0;
    uint16_t actualNumberOfEntities = 0;
    QVector<uint16_t> indexesOfEntitiesToInclude;

    // It's possible that our element has been previous completed. In this case we'll simply not include any of our
    // entities for encoding. This is needed because we encode the element data at the "parent" level, and so we 
    // need to handle the case where our sibling elements need encoding but we don't.
    if (!entityTreeElementExtraEncodeData->elementCompleted) {
        for (uint16_t i = 0; i < _entityItems->size(); i++) {
            EntityItem* entity = (*_entityItems)[i];
            bool includeThisEntity = true;
            
            if (!params.forceSendScene && entity->getLastChangedOnServer() < params.lastViewFrustumSent) {
                includeThisEntity = false;
            }
        
            if (hadElementExtraData) {
                includeThisEntity = includeThisEntity && 
                                        entityTreeElementExtraEncodeData->entities.contains(entity->getEntityItemID());
            }
        
            if (includeThisEntity && params.viewFrustum) {
            
                // we want to use the maximum possible box for this, so that we don't have to worry about the nuance of
                // simulation changing what's visible. consider the case where the entity contains an angular velocity
                // the entity may not be in view and then in view a frame later, let the client side handle it's view
                // frustum culling on rendering.
                AACube entityCube = entity->getMaximumAACube();
                entityCube.scale(TREE_SCALE);
                if (params.viewFrustum->cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE) {
                    includeThisEntity = false; // out of view, don't include it
                }
            }
        
            if (includeThisEntity) {
                indexesOfEntitiesToInclude << i;
                numberOfEntities++;
            }
        }
    }

    int numberOfEntitiesOffset = packetData->getUncompressedByteOffset();
    bool successAppendEntityCount = packetData->appendValue(numberOfEntities);

    if (successAppendEntityCount) {
        foreach (uint16_t i, indexesOfEntitiesToInclude) {
            EntityItem* entity = (*_entityItems)[i];
            LevelDetails entityLevel = packetData->startLevel();
            OctreeElement::AppendState appendEntityState = entity->appendEntityData(packetData, 
                                                                        params, entityTreeElementExtraEncodeData);

            // If none of this entity data was able to be appended, then discard it
            // and don't include it in our entity count
            if (appendEntityState == OctreeElement::NONE) {
                packetData->discardLevel(entityLevel);
            } else {
                // If either ALL or some of it got appended, then end the level (commit it)
                // and include the entity in our final count of entities
                packetData->endLevel(entityLevel);
                actualNumberOfEntities++;
            }
            
            // If the entity item got completely appended, then we can remove it from the extra encode data
            if (appendEntityState == OctreeElement::COMPLETED) {
                entityTreeElementExtraEncodeData->entities.remove(entity->getEntityItemID());
            }

            // If any part of the entity items didn't fit, then the element is considered partial
            // NOTE: if the entity item didn't fit or only partially fit, then the entity item should have
            // added itself to the extra encode data.
            if (appendEntityState != OctreeElement::COMPLETED) {
                appendElementState = OctreeElement::PARTIAL;
            }
        }
    } else {
コード例 #17
0
ファイル: EntityTreeElement.cpp プロジェクト: JamesLinus/hifi
OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData* packetData,
                                                                    EncodeBitstreamParams& params) const {

    OctreeElement::AppendState appendElementState = OctreeElement::COMPLETED; // assume the best...

    // first, check the params.extraEncodeData to see if there's any partial re-encode data for this element
    OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
    EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData = NULL;
    bool hadElementExtraData = false;
    if (extraEncodeData && extraEncodeData->contains(this)) {
        entityTreeElementExtraEncodeData =
            static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
        hadElementExtraData = true;
    } else {
        // if there wasn't one already, then create one
        entityTreeElementExtraEncodeData = new EntityTreeElementExtraEncodeData();
        entityTreeElementExtraEncodeData->elementCompleted = !hasContent();

        for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
            EntityTreeElementPointer child = getChildAtIndex(i);
            if (!child) {
                entityTreeElementExtraEncodeData->childCompleted[i] = true; // if no child exists, it is completed
            } else {
                if (child->hasEntities()) {
                    entityTreeElementExtraEncodeData->childCompleted[i] = false;
                } else {
                    // if the child doesn't have enities, it is completed
                    entityTreeElementExtraEncodeData->childCompleted[i] = true;
                }
            }
        }
        forEachEntity([&](EntityItemPointer entity) {
            entityTreeElementExtraEncodeData->entities.insert(entity->getEntityItemID(), entity->getEntityProperties(params));
        });
    }

    //assert(extraEncodeData);
    //assert(extraEncodeData->contains(this));
    //entityTreeElementExtraEncodeData = static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));

    LevelDetails elementLevel = packetData->startLevel();

    // write our entities out... first determine which of the entities are in view based on our params
    uint16_t numberOfEntities = 0;
    uint16_t actualNumberOfEntities = 0;
    int numberOfEntitiesOffset = 0;
    withReadLock([&] {
        QVector<uint16_t> indexesOfEntitiesToInclude;

        // It's possible that our element has been previous completed. In this case we'll simply not include any of our
        // entities for encoding. This is needed because we encode the element data at the "parent" level, and so we
        // need to handle the case where our sibling elements need encoding but we don't.
        if (!entityTreeElementExtraEncodeData->elementCompleted) {
            for (uint16_t i = 0; i < _entityItems.size(); i++) {
                EntityItemPointer entity = _entityItems[i];
                bool includeThisEntity = true;

                if (!params.forceSendScene && entity->getLastChangedOnServer() < params.lastViewFrustumSent) {
                    includeThisEntity = false;
                }

                if (hadElementExtraData) {
                    includeThisEntity = includeThisEntity &&
                        entityTreeElementExtraEncodeData->entities.contains(entity->getEntityItemID());
                }

                if (includeThisEntity && params.viewFrustum) {

                    // we want to use the maximum possible box for this, so that we don't have to worry about the nuance of
                    // simulation changing what's visible. consider the case where the entity contains an angular velocity
                    // the entity may not be in view and then in view a frame later, let the client side handle it's view
                    // frustum culling on rendering.
                    bool success;
                    AACube entityCube = entity->getQueryAACube(success);
                    if (!success || !params.viewFrustum->cubeIntersectsKeyhole(entityCube)) {
                        includeThisEntity = false; // out of view, don't include it
                    } else {
                        // Check the size of the entity, it's possible that a "too small to see" entity is included in a
                        // larger octree cell because of its position (for example if it crosses the boundary of a cell it
                        // pops to the next higher cell. So we want to check to see that the entity is large enough to be seen
                        // before we consider including it.
                        success = true;
                        // we can't cull a parent-entity by its dimensions because the child may be larger.  we need to
                        // avoid sending details about a child but not the parent.  the parent's queryAACube should have
                        // been adjusted to encompass the queryAACube of the child.
                        AABox entityBounds = entity->hasChildren() ? AABox(entityCube) : entity->getAABox(success);
                        if (!success) {
                            // if this entity is a child of an avatar, the entity-server wont be able to determine its
                            // AABox.  If this happens, fall back to the queryAACube.
                            entityBounds = AABox(entityCube);
                        }
                        auto renderAccuracy = params.viewFrustum->calculateRenderAccuracy(entityBounds,
                                                                                          params.octreeElementSizeScale,
                                                                                          params.boundaryLevelAdjust);
                        if (renderAccuracy <= 0.0f) {
                            includeThisEntity = false; // too small, don't include it

                            #ifdef WANT_LOD_DEBUGGING
                            qDebug() << "skipping entity - TOO SMALL - \n"
                                     << "......id:" << entity->getID() << "\n"
                                     << "....name:" << entity->getName() << "\n"
                                     << "..bounds:" << entityBounds << "\n"
                                     << "....cell:" << getAACube();
                            #endif
                        }
                    }
                }

                if (includeThisEntity) {
                    #ifdef WANT_LOD_DEBUGGING
                    qDebug() << "including entity - \n"
                        << "......id:" << entity->getID() << "\n"
                        << "....name:" << entity->getName() << "\n"
                        << "....cell:" << getAACube();
                    #endif
                    indexesOfEntitiesToInclude << i;
                    numberOfEntities++;
                } else {
                    // if the extra data included this entity, and we've decided to not include the entity, then
                    // we can treat it as if it was completed.
                    entityTreeElementExtraEncodeData->entities.remove(entity->getEntityItemID());
                }
            }
        }

        numberOfEntitiesOffset = packetData->getUncompressedByteOffset();
        bool successAppendEntityCount = packetData->appendValue(numberOfEntities);

        if (successAppendEntityCount) {
            foreach(uint16_t i, indexesOfEntitiesToInclude) {
                EntityItemPointer entity = _entityItems[i];
                LevelDetails entityLevel = packetData->startLevel();
                OctreeElement::AppendState appendEntityState = entity->appendEntityData(packetData,
                    params, entityTreeElementExtraEncodeData);

                // If none of this entity data was able to be appended, then discard it
                // and don't include it in our entity count
                if (appendEntityState == OctreeElement::NONE) {
                    packetData->discardLevel(entityLevel);
                } else {
                    // If either ALL or some of it got appended, then end the level (commit it)
                    // and include the entity in our final count of entities
                    packetData->endLevel(entityLevel);
                    actualNumberOfEntities++;
                }

                // If the entity item got completely appended, then we can remove it from the extra encode data
                if (appendEntityState == OctreeElement::COMPLETED) {
                    entityTreeElementExtraEncodeData->entities.remove(entity->getEntityItemID());
                }

                // If any part of the entity items didn't fit, then the element is considered partial
                // NOTE: if the entity item didn't fit or only partially fit, then the entity item should have
                // added itself to the extra encode data.
                if (appendEntityState != OctreeElement::COMPLETED) {
                    appendElementState = OctreeElement::PARTIAL;
                }
            }
        } else {
コード例 #18
0
ファイル: EntityTreeElement.cpp プロジェクト: JamesLinus/hifi
void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params) const {
    const bool wantDebug = false;

    if (wantDebug) {
        qCDebug(entities) << "EntityTreeElement::elementEncodeComplete() element:" << _cube;
    }

    OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
    assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
    assert(extraEncodeData->contains(this));

    EntityTreeElementExtraEncodeData* thisExtraEncodeData
                = static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));

    // Note: this will be called when OUR element has finished running through encodeTreeBitstreamRecursion()
    // which means, it's possible that our parent element hasn't finished encoding OUR data... so
    // in this case, our children may be complete, and we should clean up their encode data...
    // but not necessarily cleanup our own encode data...
    //
    // If we're really complete here's what must be true...
    //    1) our own data must be complete
    //    2) the data for all our immediate children must be complete.
    // However, the following might also be the case...
    //    1) it's ok for our child trees to not yet be fully encoded/complete...
    //       SO LONG AS... the our child's node is in the bag ready for encoding

    bool someChildTreeNotComplete = false;
    for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
        EntityTreeElementPointer childElement = getChildAtIndex(i);
        if (childElement) {

            // why would this ever fail???
            // If we've encoding this element before... but we're coming back a second time in an attempt to
            // encoud our parent... this might happen.
            if (extraEncodeData->contains(childElement.get())) {
                EntityTreeElementExtraEncodeData* childExtraEncodeData
                    = static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(childElement.get()));

                if (wantDebug) {
                    qCDebug(entities) << "checking child: " << childElement->_cube;
                    qCDebug(entities) << "    childElement->isLeaf():" << childElement->isLeaf();
                    qCDebug(entities) << "    childExtraEncodeData->elementCompleted:" << childExtraEncodeData->elementCompleted;
                    qCDebug(entities) << "    childExtraEncodeData->subtreeCompleted:" << childExtraEncodeData->subtreeCompleted;
                }

                if (childElement->isLeaf() && childExtraEncodeData->elementCompleted) {
                    if (wantDebug) {
                        qCDebug(entities) << "    CHILD IS LEAF -- AND CHILD ELEMENT DATA COMPLETED!!!";
                    }
                    childExtraEncodeData->subtreeCompleted = true;
                }

                if (!childExtraEncodeData->elementCompleted || !childExtraEncodeData->subtreeCompleted) {
                    someChildTreeNotComplete = true;
                }
            }
        }
    }

    if (wantDebug) {
        qCDebug(entities) << "for this element: " << _cube;
        qCDebug(entities) << "    WAS elementCompleted:" << thisExtraEncodeData->elementCompleted;
        qCDebug(entities) << "    WAS subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted;
    }

    thisExtraEncodeData->subtreeCompleted = !someChildTreeNotComplete;

    if (wantDebug) {
        qCDebug(entities) << "    NOW elementCompleted:" << thisExtraEncodeData->elementCompleted;
        qCDebug(entities) << "    NOW subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted;

        if (thisExtraEncodeData->subtreeCompleted) {
            qCDebug(entities) << "    YEAH!!!!! >>>>>>>>>>>>>> NOW subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted;
        }
    }
}
コード例 #19
0
ファイル: OctreeElement.cpp プロジェクト: MarcelEdward/hifi
// TODO: consider removing this, or switching to using getOrCreateChildElementContaining(const AACube& box)...
OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float z, float s) {
    OctreeElement* 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 this;
    }
    // otherwise, we need to find which of our children we should recurse
    glm::vec3 ourCenter = _cube.calcCenter();

    int childIndex = CHILD_UNKNOWN;
    // left half
    if (x > ourCenter.x) {
        if (y > ourCenter.y) {
            // top left
            if (z > ourCenter.z) {
                // top left far
                childIndex = CHILD_TOP_LEFT_FAR;
            } else {
                // top left near
                childIndex = CHILD_TOP_LEFT_NEAR;
            }
        } else {
            // bottom left
            if (z > ourCenter.z) {
                // bottom left far
                childIndex = CHILD_BOTTOM_LEFT_FAR;
            } else {
                // bottom left near
                childIndex = CHILD_BOTTOM_LEFT_NEAR;
            }
        }
    } else {
        // right half
        if (y > ourCenter.y) {
            // top right
            if (z > ourCenter.z) {
                // top right far
                childIndex = CHILD_TOP_RIGHT_FAR;
            } else {
                // top right near
                childIndex = CHILD_TOP_RIGHT_NEAR;
            }
        } else {
            // bottom right
            if (z > ourCenter.z) {
                // bottom right far
                childIndex = CHILD_BOTTOM_RIGHT_FAR;
            } else {
                // bottom right near
                childIndex = CHILD_BOTTOM_RIGHT_NEAR;
            }
        }
    }

    // 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);
}
コード例 #20
0
ファイル: NativeEnumModules.cpp プロジェクト: prazek/llvm
std::unique_ptr<PDBSymbol> NativeEnumModules::getNext() {
  if (Index >= Modules.getModuleCount())
    return nullptr;
  return getChildAtIndex(Index++);
}