From 2541bfb1a8fdf4a81a1ccf83e6b426e6bbbe6d0b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 10 Jan 2017 20:19:09 -0800 Subject: [PATCH] only create collision events for owned entities --- .../src/EntityTreeRenderer.cpp | 2 -- libraries/physics/src/EntityMotionState.cpp | 5 ++++ libraries/physics/src/EntityMotionState.h | 2 ++ libraries/physics/src/ObjectMotionState.h | 2 ++ libraries/physics/src/PhysicsEngine.cpp | 23 ++++++++++++++----- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index da06a07552..c56d55286e 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1045,8 +1045,6 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons const QUuid& myNodeID = DependencyManager::get()->getSessionUUID(); // trigger scripted collision sounds and events for locally owned objects - // BUG! scripts don't get the final COLLISION_EVENT_TYPE_END event in a timely manner because - // by the time it gets here the object has been deactivated and local ownership is relenquished. EntityItemPointer entityA = entityTree->findEntityByEntityItemID(idA); if ((bool)entityA && myNodeID == entityA->getSimulatorID()) { playEntityCollisionSound(entityA, collision); diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 1833d0aba4..b0bdc34b52 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -762,6 +762,11 @@ void EntityMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& ma _entity->computeCollisionGroupAndFinalMask(group, mask); } +bool EntityMotionState::shouldBeLocallyOwned() const { + return (_outgoingPriority > VOLUNTEER_SIMULATION_PRIORITY && _outgoingPriority > _entity->getSimulationPriority()) || + _entity->getSimulatorID() == Physics::getSessionUUID(); +} + void EntityMotionState::upgradeOutgoingPriority(uint8_t priority) { _outgoingPriority = glm::max(_outgoingPriority, priority); } diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 194d82805f..feac47d8ec 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -78,6 +78,8 @@ public: virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override; + bool shouldBeLocallyOwned() const override; + friend class PhysicalEntitySimulation; protected: diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index a7894998a8..1d258560c3 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -146,6 +146,8 @@ public: void dirtyInternalKinematicChanges() { _hasInternalKinematicChanges = true; } void clearInternalKinematicChanges() { _hasInternalKinematicChanges = false; } + virtual bool shouldBeLocallyOwned() const { return false; } + friend class PhysicsEngine; protected: diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index f8e02a14b8..5b638b9a98 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -405,25 +405,36 @@ const CollisionEvents& PhysicsEngine::getCollisionEvents() { if (type != CONTACT_EVENT_TYPE_CONTINUE || _numSubsteps % CONTINUE_EVENT_FILTER_FREQUENCY == 0) { ObjectMotionState* motionStateA = static_cast(contactItr->first._a); ObjectMotionState* motionStateB = static_cast(contactItr->first._b); - glm::vec3 velocityChange = (motionStateA ? motionStateA->getObjectLinearVelocityChange() : glm::vec3(0.0f)) + - (motionStateB ? motionStateB->getObjectLinearVelocityChange() : glm::vec3(0.0f)); - if (motionStateA) { + // NOTE: the MyAvatar RigidBody is the only object in the simulation that does NOT have a MotionState + // which means should we ever want to report ALL collision events against the avatar we can + // modify the logic below. + // + // We only create events when at least one of the objects is (or should be) owned in the local simulation. + if (motionStateA && (motionStateA->shouldBeLocallyOwned())) { QUuid idA = motionStateA->getObjectID(); QUuid idB; if (motionStateB) { idB = motionStateB->getObjectID(); } glm::vec3 position = bulletToGLM(contact.getPositionWorldOnB()) + _originOffset; + glm::vec3 velocityChange = motionStateA->getObjectLinearVelocityChange() + + (motionStateB ? motionStateB->getObjectLinearVelocityChange() : glm::vec3(0.0f)); glm::vec3 penetration = bulletToGLM(contact.distance * contact.normalWorldOnB); _collisionEvents.push_back(Collision(type, idA, idB, position, penetration, velocityChange)); - } else if (motionStateB) { + } else if (motionStateB && (motionStateB->shouldBeLocallyOwned())) { QUuid idB = motionStateB->getObjectID(); + QUuid idA; + if (motionStateA) { + idA = motionStateA->getObjectID(); + } glm::vec3 position = bulletToGLM(contact.getPositionWorldOnA()) + _originOffset; + glm::vec3 velocityChange = motionStateB->getObjectLinearVelocityChange() + + (motionStateA ? motionStateA->getObjectLinearVelocityChange() : glm::vec3(0.0f)); // NOTE: we're flipping the order of A and B (so that the first objectID is never NULL) - // hence we must negate the penetration (because penetration always points from B to A). + // hence we negate the penetration (because penetration always points from B to A). glm::vec3 penetration = - bulletToGLM(contact.distance * contact.normalWorldOnB); - _collisionEvents.push_back(Collision(type, idB, QUuid(), position, penetration, velocityChange)); + _collisionEvents.push_back(Collision(type, idB, idA, position, penetration, velocityChange)); } }