diff --git a/libraries/entities/src/EntitySimulation.h b/libraries/entities/src/EntitySimulation.h index 1eb4fdc951..913f431186 100644 --- a/libraries/entities/src/EntitySimulation.h +++ b/libraries/entities/src/EntitySimulation.h @@ -61,6 +61,8 @@ public: void clearEntities(); + virtual void bump(EntityItem* bumpEntity) {} + EntityTree* getEntityTree() { return _entityTree; } signals: diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 5b15aa26b4..a41deb174f 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -269,6 +269,9 @@ void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ign return; } + // in case something is resting on top of this, give it a bump in the simulation. + _simulation->bump(existingEntity); + if (existingEntity->getLocked() && !force) { if (!ignoreWarnings) { qCDebug(entities) << "ERROR! EntityTree::deleteEntity() trying to delete locked entity. entityID=" << entityID; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index ae76e1c785..074500f719 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -366,6 +366,39 @@ void PhysicsEngine::stepNonPhysicalKinematics(const quint64& now) { } } + +void PhysicsEngine::bump(EntityItem* bumpEntity) { + // If this node is doing something like deleting an entity, scan for contacts involving the + // entity. For each found, flag the other entity involved as being simulated by this node. + lock(); + int numManifolds = _collisionDispatcher->getNumManifolds(); + for (int i = 0; i < numManifolds; ++i) { + btPersistentManifold* contactManifold = _collisionDispatcher->getManifoldByIndexInternal(i); + if (contactManifold->getNumContacts() > 0) { + const btCollisionObject* objectA = static_cast(contactManifold->getBody0()); + const btCollisionObject* objectB = static_cast(contactManifold->getBody1()); + if (objectA && objectB) { + void* a = objectA->getUserPointer(); + void* b = objectB->getUserPointer(); + if (a && b) { + EntityItem* entityA = a ? static_cast(a)->getEntity() : NULL; + EntityItem* entityB = b ? static_cast(b)->getEntity() : NULL; + if (entityA && entityB) { + if (entityA == bumpEntity) { + entityB->setShouldClaimSimulationOwnership(true); + } + if (entityB == bumpEntity) { + entityA->setShouldClaimSimulationOwnership(true); + } + } + } + } + } + } + unlock(); +} + + void PhysicsEngine::computeCollisionEvents() { BT_PROFILE("computeCollisionEvents"); @@ -422,7 +455,6 @@ void PhysicsEngine::computeCollisionEvents() { // scan known contacts and trigger events ContactMap::iterator contactItr = _contactMap.begin(); - while (contactItr != _contactMap.end()) { ObjectMotionState* A = static_cast(contactItr->first._a); ObjectMotionState* B = static_cast(contactItr->first._b); diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 6e1f430237..63ec96d04e 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -68,6 +68,7 @@ public: void stepSimulation(); void stepNonPhysicalKinematics(const quint64& now); + virtual void bump(EntityItem* bumpEntity); void computeCollisionEvents(); void dumpStatsIfNecessary();