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) << "--------------------------------------------------------------------------"; } }
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); }