void SimpleEntitySimulation::clearOwnership(const QUuid& ownerID) {
    QMutexLocker lock(&_mutex);
    SetOfEntities::iterator itemItr = _entitiesWithSimulationOwner.begin();
    while (itemItr != _entitiesWithSimulationOwner.end()) {
        EntityItemPointer entity = *itemItr;
        if (entity->getSimulatorID() == ownerID) {
            // the simulator has abandonded this object --> remove from owned list
            qCDebug(entities) << "auto-removing simulation owner " << entity->getSimulatorID();
            itemItr = _entitiesWithSimulationOwner.erase(itemItr);

            if (entity->getDynamic() && entity->hasLocalVelocity()) {
                // it is still moving dynamically --> add to orphaned list
                _entitiesThatNeedSimulationOwner.insert(entity);
                quint64 expiry = entity->getLastChangedOnServer() + MAX_OWNERLESS_PERIOD;
                if (expiry < _nextOwnerlessExpiry) {
                    _nextOwnerlessExpiry = expiry;
                }
            }

            // remove ownership and dirty all the tree elements that contain the it
            entity->clearSimulationOwnership();
            entity->markAsChangedOnServer();
            DirtyOctreeElementOperator op(entity->getElement());
            getEntityTree()->recurseTreeWithOperator(&op);
        } else {
            ++itemItr;
        }
    }
}
void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) {
    if (now > _nextOwnerlessExpiry) {
        // search for ownerless objects that have expired
        QMutexLocker lock(&_mutex);
        _nextOwnerlessExpiry = -1;
        SetOfEntities::iterator itemItr = _entitiesThatNeedSimulationOwner.begin();
        while (itemItr != _entitiesThatNeedSimulationOwner.end()) {
            EntityItemPointer entity = *itemItr;
            quint64 expiry = entity->getLastChangedOnServer() + MAX_OWNERLESS_PERIOD;
            if (expiry < now) {
                // no simulators have volunteered ownership --> remove from list
                itemItr = _entitiesThatNeedSimulationOwner.erase(itemItr);

                if (entity->getSimulatorID().isNull() && entity->getDynamic() && entity->hasLocalVelocity()) {
                    // zero the derivatives
                    entity->setVelocity(Vectors::ZERO);
                    entity->setAngularVelocity(Vectors::ZERO);
                    entity->setAcceleration(Vectors::ZERO);

                    // dirty all the tree elements that contain it
                    entity->markAsChangedOnServer();
                    DirtyOctreeElementOperator op(entity->getElement());
                    getEntityTree()->recurseTreeWithOperator(&op);
                }
            } else {
                ++itemItr;
                if (expiry < _nextOwnerlessExpiry) {
                    _nextOwnerlessExpiry = expiry;
                }
            }
        }
    }
}
void MovingEntitiesOperator::addEntityToMoveList(EntityItemPointer entity, const AACube& newCube) {
    EntityTreeElementPointer oldContainingElement = entity->getElement();
    AABox newCubeClamped = newCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE);

    if (_wantDebug) {
        qCDebug(entities) << "MovingEntitiesOperator::addEntityToMoveList() -----------------------------";
        qCDebug(entities) << "    newCube:" << newCube;
        qCDebug(entities) << "    newCubeClamped:" << newCubeClamped;
        if (oldContainingElement) {
            qCDebug(entities) << "    oldContainingElement:" << oldContainingElement->getAACube();
            qCDebug(entities) << "    oldContainingElement->bestFitBounds(newCubeClamped):" 
                            << oldContainingElement->bestFitBounds(newCubeClamped);
        } else {
            qCDebug(entities) << "    WARNING NO OLD CONTAINING ELEMENT for entity" << entity->getEntityItemID();
        }
    }

    if (!oldContainingElement) {
        return; // bail without adding.
    }

    // If the original containing element is the best fit for the requested newCube locations then
    // we don't actually need to add the entity for moving and we can short circuit all this work
    if (!oldContainingElement->bestFitBounds(newCubeClamped)) {
        // check our tree, to determine if this entity is known
        EntityToMoveDetails details;
        details.oldContainingElement = oldContainingElement;
        details.oldContainingElementCube = oldContainingElement->getAACube();
        details.entity = entity;
        details.oldFound = false;
        details.newFound = false;
        details.newCube = newCube;
        details.newCubeClamped = newCubeClamped;
        _entitiesToMove << details;
        _lookingCount++;

        if (_wantDebug) {
            qCDebug(entities) << "MovingEntitiesOperator::addEntityToMoveList() -----------------------------";
            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) << "    _lookingCount:" << _lookingCount;
            qCDebug(entities) << "--------------------------------------------------------------------------";
        }
    } else {
        if (_wantDebug) {
            qCDebug(entities) << "    oldContainingElement->bestFitBounds(newCubeClamped) IS BEST FIT... NOTHING TO DO";
        }
    }

    if (_wantDebug) {
        qCDebug(entities) << "--------------------------------------------------------------------------";
    }
}
Beispiel #4
0
EntityItemPointer ObjectDynamic::getEntityByID(EntityItemID entityID) const {
    EntityItemPointer ownerEntity;
    withReadLock([&]{
        ownerEntity = _ownerEntity.lock();
    });
    EntityTreeElementPointer element = ownerEntity ? ownerEntity->getElement() : nullptr;
    EntityTreePointer tree = element ? element->getTree() : nullptr;
    if (!tree) {
        return nullptr;
    }
    return tree->findEntityByID(entityID);
}