From 3d16c9014f308f8b2947b4a5343828796d0eb98d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 3 May 2018 16:22:36 -0700 Subject: [PATCH 1/2] remove unowned 'dynamic' objects from kinematic integration --- .../entities/src/SimpleEntitySimulation.cpp | 97 +++++++++++++------ 1 file changed, 65 insertions(+), 32 deletions(-) diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp index cf42e93821..3ed84035ac 100644 --- a/libraries/entities/src/SimpleEntitySimulation.cpp +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -53,20 +53,29 @@ void SimpleEntitySimulation::updateEntitiesInternal(uint64_t now) { } void SimpleEntitySimulation::addEntityInternal(EntityItemPointer entity) { - if (entity->isMovingRelativeToParent() && !entity->getPhysicsInfo()) { + if (entity->getSimulatorID().isNull()) { QMutexLocker lock(&_mutex); - _simpleKinematicEntities.insert(entity); - entity->setLastSimulated(usecTimestampNow()); - } - if (!entity->getSimulatorID().isNull()) { + if (entity->getDynamic()) { + // we don't allow dynamic objects to move without an owner so nothing to do here + } else if (entity->isMovingRelativeToParent()) { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.insert(entity); + entity->setLastSimulated(usecTimestampNow()); + } + } + } else { QMutexLocker lock(&_mutex); _entitiesWithSimulationOwner.insert(entity); _nextStaleOwnershipExpiry = glm::min(_nextStaleOwnershipExpiry, entity->getSimulationOwnershipExpiry()); - } else if (entity->getDynamic() && entity->hasLocalVelocity()) { - QMutexLocker lock(&_mutex); - _entitiesThatNeedSimulationOwner.insert(entity); - uint64_t expiry = entity->getLastChangedOnServer() + MAX_OWNERLESS_PERIOD; - _nextOwnerlessExpiry = glm::min(_nextOwnerlessExpiry, expiry); + + if (entity->isMovingRelativeToParent()) { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.insert(entity); + entity->setLastSimulated(usecTimestampNow()); + } + } } } @@ -77,32 +86,50 @@ void SimpleEntitySimulation::removeEntityInternal(EntityItemPointer entity) { } void SimpleEntitySimulation::changeEntityInternal(EntityItemPointer entity) { - { - QMutexLocker lock(&_mutex); - if (entity->isMovingRelativeToParent() && !entity->getPhysicsInfo()) { - int numKinematicEntities = _simpleKinematicEntities.size(); - _simpleKinematicEntities.insert(entity); - if (numKinematicEntities != _simpleKinematicEntities.size()) { - entity->setLastSimulated(usecTimestampNow()); + uint32_t flags = entity->getDirtyFlags(); + if ((flags & Simulation::DIRTY_SIMULATOR_ID) || (flags & Simulation::DIRTY_VELOCITIES)) { + if (entity->getSimulatorID().isNull()) { + QMutexLocker lock(&_mutex); + _entitiesWithSimulationOwner.remove(entity); + + if (entity->getDynamic()) { + // we don't allow dynamic objects to move without an owner + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.erase(itr); + } + } else if (entity->isMovingRelativeToParent()) { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.insert(entity); + entity->setLastSimulated(usecTimestampNow()); + } + } else { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.erase(itr); + } } } else { - _simpleKinematicEntities.remove(entity); + QMutexLocker lock(&_mutex); + _entitiesWithSimulationOwner.insert(entity); + _nextStaleOwnershipExpiry = glm::min(_nextStaleOwnershipExpiry, entity->getSimulationOwnershipExpiry()); + _entitiesThatNeedSimulationOwner.remove(entity); + + if (entity->isMovingRelativeToParent()) { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.insert(entity); + entity->setLastSimulated(usecTimestampNow()); + } + } else { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.erase(itr); + } + } } } - if (entity->getSimulatorID().isNull()) { - QMutexLocker lock(&_mutex); - _entitiesWithSimulationOwner.remove(entity); - if (entity->getDynamic() && entity->hasLocalVelocity()) { - _entitiesThatNeedSimulationOwner.insert(entity); - uint64_t expiry = entity->getLastChangedOnServer() + MAX_OWNERLESS_PERIOD; - _nextOwnerlessExpiry = glm::min(_nextOwnerlessExpiry, expiry); - } - } else { - QMutexLocker lock(&_mutex); - _entitiesWithSimulationOwner.insert(entity); - _nextStaleOwnershipExpiry = glm::min(_nextStaleOwnershipExpiry, entity->getSimulationOwnershipExpiry()); - _entitiesThatNeedSimulationOwner.remove(entity); - } entity->clearDirtyFlags(); } @@ -131,6 +158,12 @@ void SimpleEntitySimulation::expireStaleOwnerships(uint64_t now) { uint64_t expiry = entity->getSimulationOwnershipExpiry(); if (now > expiry) { itemItr = _entitiesWithSimulationOwner.erase(itemItr); + if (entity->getDynamic()) { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.erase(itr); + } + } // remove ownership and dirty all the tree elements that contain the it entity->clearSimulationOwnership(); From b1fcb43246047e113d56ce2fca784a66bba6d191 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 3 May 2018 16:23:13 -0700 Subject: [PATCH 2/2] send ownership removal packet when dynamic object leaves bullet --- .../physics/src/PhysicalEntitySimulation.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 8e2695fbfd..4f8e8342c8 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -130,7 +130,21 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { bool canBeKinematic = region <= workload::Region::R3; if (motionState) { if (!shouldBePhysical) { - // the entity should be removed from the physical simulation + if (motionState->isLocallyOwned()) { + // zero velocities by first deactivating the RigidBody + btRigidBody* body = motionState->getRigidBody(); + if (body) { + body->forceActivationState(ISLAND_SLEEPING); + motionState->updateSendVelocities(); // has side-effect of zeroing entity velocities for inactive body + } + + // send packet to remove ownership + // NOTE: this packet will NOT be resent if lost, but the good news is: + // the entity-server will eventually clear velocity and ownership for timeout + motionState->sendUpdate(_entityPacketSender, _physicsEngine->getNumSubsteps()); + } + + // remove from the physical simulation _incomingChanges.remove(motionState); _physicalObjects.remove(motionState); removeOwnershipData(motionState);