Merge pull request #13097 from AndrewMeadows/workload-013

workload: stop locally-owned dynamic entities when removed from Bullet simulation
This commit is contained in:
Sam Gateau 2018-05-04 11:53:57 -07:00 committed by GitHub
commit 328e2dc7f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 33 deletions

View file

@ -53,20 +53,29 @@ void SimpleEntitySimulation::updateEntitiesInternal(uint64_t now) {
} }
void SimpleEntitySimulation::addEntityInternal(EntityItemPointer entity) { void SimpleEntitySimulation::addEntityInternal(EntityItemPointer entity) {
if (entity->isMovingRelativeToParent() && !entity->getPhysicsInfo()) { if (entity->getSimulatorID().isNull()) {
QMutexLocker lock(&_mutex); QMutexLocker lock(&_mutex);
_simpleKinematicEntities.insert(entity); if (entity->getDynamic()) {
entity->setLastSimulated(usecTimestampNow()); // we don't allow dynamic objects to move without an owner so nothing to do here
} } else if (entity->isMovingRelativeToParent()) {
if (!entity->getSimulatorID().isNull()) { SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity);
if (itr != _simpleKinematicEntities.end()) {
_simpleKinematicEntities.insert(entity);
entity->setLastSimulated(usecTimestampNow());
}
}
} else {
QMutexLocker lock(&_mutex); QMutexLocker lock(&_mutex);
_entitiesWithSimulationOwner.insert(entity); _entitiesWithSimulationOwner.insert(entity);
_nextStaleOwnershipExpiry = glm::min(_nextStaleOwnershipExpiry, entity->getSimulationOwnershipExpiry()); _nextStaleOwnershipExpiry = glm::min(_nextStaleOwnershipExpiry, entity->getSimulationOwnershipExpiry());
} else if (entity->getDynamic() && entity->hasLocalVelocity()) {
QMutexLocker lock(&_mutex); if (entity->isMovingRelativeToParent()) {
_entitiesThatNeedSimulationOwner.insert(entity); SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity);
uint64_t expiry = entity->getLastChangedOnServer() + MAX_OWNERLESS_PERIOD; if (itr != _simpleKinematicEntities.end()) {
_nextOwnerlessExpiry = glm::min(_nextOwnerlessExpiry, expiry); _simpleKinematicEntities.insert(entity);
entity->setLastSimulated(usecTimestampNow());
}
}
} }
} }
@ -77,32 +86,50 @@ void SimpleEntitySimulation::removeEntityInternal(EntityItemPointer entity) {
} }
void SimpleEntitySimulation::changeEntityInternal(EntityItemPointer entity) { void SimpleEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
{ uint32_t flags = entity->getDirtyFlags();
QMutexLocker lock(&_mutex); if ((flags & Simulation::DIRTY_SIMULATOR_ID) || (flags & Simulation::DIRTY_VELOCITIES)) {
if (entity->isMovingRelativeToParent() && !entity->getPhysicsInfo()) { if (entity->getSimulatorID().isNull()) {
int numKinematicEntities = _simpleKinematicEntities.size(); QMutexLocker lock(&_mutex);
_simpleKinematicEntities.insert(entity); _entitiesWithSimulationOwner.remove(entity);
if (numKinematicEntities != _simpleKinematicEntities.size()) {
entity->setLastSimulated(usecTimestampNow()); 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 { } 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(); entity->clearDirtyFlags();
} }
@ -131,6 +158,12 @@ void SimpleEntitySimulation::expireStaleOwnerships(uint64_t now) {
uint64_t expiry = entity->getSimulationOwnershipExpiry(); uint64_t expiry = entity->getSimulationOwnershipExpiry();
if (now > expiry) { if (now > expiry) {
itemItr = _entitiesWithSimulationOwner.erase(itemItr); 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 // remove ownership and dirty all the tree elements that contain the it
entity->clearSimulationOwnership(); entity->clearSimulationOwnership();

View file

@ -130,7 +130,21 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
bool canBeKinematic = region <= workload::Region::R3; bool canBeKinematic = region <= workload::Region::R3;
if (motionState) { if (motionState) {
if (!shouldBePhysical) { 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); _incomingChanges.remove(motionState);
_physicalObjects.remove(motionState); _physicalObjects.remove(motionState);
removeOwnershipData(motionState); removeOwnershipData(motionState);