From f5d24a87ca47118beda69356e1f2872c99c9460b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 29 Dec 2015 11:05:02 -0800 Subject: [PATCH] remove entities from physics before we delete them --- libraries/entities/src/EntityItem.h | 4 ++ libraries/entities/src/EntitySimulation.cpp | 17 +++--- libraries/entities/src/EntitySimulation.h | 4 +- .../physics/src/PhysicalEntitySimulation.cpp | 61 +++++++++++-------- .../physics/src/PhysicalEntitySimulation.h | 10 +-- 5 files changed, 58 insertions(+), 38 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 79cecfc1e5..4d7106b858 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -337,6 +337,8 @@ public: bool isMoving() const; + bool isSimulated() const { return _simulated; } + void* getPhysicsInfo() const { return _physicsInfo; } void setPhysicsInfo(void* data) { _physicsInfo = data; } @@ -391,6 +393,8 @@ public: protected: + void setSimulated(bool simulated) { _simulated = simulated; } + const QByteArray getActionDataInternal() const; void setActionDataInternal(QByteArray actionData); diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index 324a7a25dd..62912b8954 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -53,16 +53,15 @@ void EntitySimulation::removeEntityInternal(EntityItemPointer entity) { _entitiesToSort.remove(entity); _simpleKinematicEntities.remove(entity); _allEntities.remove(entity); - entity->_simulated = false; + entity->setSimulated(false); } void EntitySimulation::prepareEntityForDelete(EntityItemPointer entity) { assert(entity); - if (entity->_simulated) { - entity->clearActions(this); - _entitiesToDelete.insert(entity); - removeEntityInternal(entity); - } + assert(entity->isSimulated()); + entity->clearActions(this); + removeEntityInternal(entity); + _entitiesToDelete.insert(entity); } void EntitySimulation::addEntityInternal(EntityItemPointer entity) { @@ -166,7 +165,7 @@ void EntitySimulation::addEntity(EntityItemPointer entity) { addEntityInternal(entity); _allEntities.insert(entity); - entity->_simulated = true; + entity->setSimulated(true); // DirtyFlags are used to signal changes to entities that have already been added, // so we can clear them for this entity which has just been added. @@ -176,7 +175,7 @@ void EntitySimulation::addEntity(EntityItemPointer entity) { void EntitySimulation::changeEntity(EntityItemPointer entity) { QMutexLocker lock(&_mutex); assert(entity); - if (!entity->_simulated) { + if (!entity->isSimulated()) { // This entity was either never added to the simulation or has been removed // (probably for pending delete), so we don't want to keep a pointer to it // on any internal lists. @@ -232,7 +231,7 @@ void EntitySimulation::clearEntities() { clearEntitiesInternal(); for (auto entityItr : _allEntities) { - entityItr->_simulated = false; + entityItr->setSimulated(false); } _allEntities.clear(); } diff --git a/libraries/entities/src/EntitySimulation.h b/libraries/entities/src/EntitySimulation.h index 7ed9a94d4b..f1548b50e9 100644 --- a/libraries/entities/src/EntitySimulation.h +++ b/libraries/entities/src/EntitySimulation.h @@ -101,6 +101,9 @@ protected: QList _actionsToAdd; QSet _actionsToRemove; +protected: + SetOfEntities _entitiesToDelete; // entities simulation decided needed to be deleted (EntityTree will actually delete) + private: void moveSimpleKinematics(); @@ -115,7 +118,6 @@ private: SetOfEntities _entitiesToUpdate; // entities that need to call EntityItem::update() - SetOfEntities _entitiesToDelete; // entities simulation decided needed to be deleted (EntityTree will actually delete) }; diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index f050894cfb..010969d3c9 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -47,7 +47,7 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) { if (entity->shouldBePhysical()) { EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); if (!motionState) { - _pendingAdds.insert(entity); + _entitiesToAddToPhysics.insert(entity); } } else if (entity->isMoving()) { _simpleKinematicEntities.insert(entity); @@ -56,14 +56,17 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) { void PhysicalEntitySimulation::removeEntityInternal(EntityItemPointer entity) { EntitySimulation::removeEntityInternal(entity); + _entitiesToAddToPhysics.remove(entity); + EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); if (motionState) { motionState->clearObjectBackPointer(); entity->setPhysicsInfo(nullptr); - _pendingRemoves.insert(motionState); _outgoingChanges.remove(motionState); + _entitiesToRemoveFromPhysics.insert(entity); + } else { + _entitiesToDelete.insert(entity); } - _pendingAdds.remove(entity); } void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { @@ -75,8 +78,8 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { // the entity should be removed from the physical simulation _pendingChanges.remove(motionState); _physicalObjects.remove(motionState); - _pendingRemoves.insert(motionState); _outgoingChanges.remove(motionState); + _entitiesToRemoveFromPhysics.insert(entity); if (entity->isMoving()) { _simpleKinematicEntities.insert(entity); } @@ -86,7 +89,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { } else if (entity->shouldBePhysical()) { // The intent is for this object to be in the PhysicsEngine, but it has no MotionState yet. // Perhaps it's shape has changed and it can now be added? - _pendingAdds.insert(entity); + _entitiesToAddToPhysics.insert(entity); _simpleKinematicEntities.remove(entity); // just in case it's non-physical-kinematic } else if (entity->isMoving()) { _simpleKinematicEntities.insert(entity); @@ -115,43 +118,53 @@ void PhysicalEntitySimulation::clearEntitiesInternal() { // finally clear all lists (which now have only dangling pointers) _physicalObjects.clear(); - _pendingRemoves.clear(); - _pendingAdds.clear(); + _entitiesToRemoveFromPhysics.clear(); + _entitiesToAddToPhysics.clear(); _pendingChanges.clear(); _outgoingChanges.clear(); } -// end EntitySimulation overrides +// virtual +void PhysicalEntitySimulation::prepareEntityForDelete(EntityItemPointer entity) { + assert(entity); + assert(entity->isSimulated()); + entity->clearActions(this); + removeEntityInternal(entity); + + // the PhysicalEntitySimulation must pull the corresponding object out of the PhysicsEngine + // before the Entity is ready to delete so we first put them on this list + _entitiesToRemoveFromPhysics.insert(entity); +} +// end EntitySimulation overrides void PhysicalEntitySimulation::getObjectsToDelete(VectorOfMotionStates& result) { result.clear(); QMutexLocker lock(&_mutex); - for (auto stateItr : _pendingRemoves) { - EntityMotionState* motionState = &(*stateItr); - _pendingChanges.remove(motionState); - _physicalObjects.remove(motionState); - - EntityItemPointer entity = motionState->getEntity(); - if (entity) { - _pendingAdds.remove(entity); - entity->setPhysicsInfo(nullptr); + for (auto entity: _entitiesToRemoveFromPhysics) { + EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); + if (motionState) { + _pendingChanges.remove(motionState); + _physicalObjects.remove(motionState); motionState->clearObjectBackPointer(); + result.push_back(motionState); } - result.push_back(motionState); + _entitiesToAddToPhysics.remove(entity); + entity->setPhysicsInfo(nullptr); + _entitiesToDelete.insert(entity); } - _pendingRemoves.clear(); + _entitiesToRemoveFromPhysics.clear(); } void PhysicalEntitySimulation::getObjectsToAdd(VectorOfMotionStates& result) { result.clear(); QMutexLocker lock(&_mutex); - SetOfEntities::iterator entityItr = _pendingAdds.begin(); - while (entityItr != _pendingAdds.end()) { + SetOfEntities::iterator entityItr = _entitiesToAddToPhysics.begin(); + while (entityItr != _entitiesToAddToPhysics.end()) { EntityItemPointer entity = *entityItr; assert(!entity->getPhysicsInfo()); if (!entity->shouldBePhysical()) { - // this entity should no longer be on the internal _pendingAdds - entityItr = _pendingAdds.erase(entityItr); + // this entity should no longer be on the internal _entitiesToAddToPhysics + entityItr = _entitiesToAddToPhysics.erase(entityItr); if (entity->isMoving()) { _simpleKinematicEntities.insert(entity); } @@ -164,7 +177,7 @@ void PhysicalEntitySimulation::getObjectsToAdd(VectorOfMotionStates& result) { entity->setPhysicsInfo(static_cast(motionState)); _physicalObjects.insert(motionState); result.push_back(motionState); - entityItr = _pendingAdds.erase(entityItr); + entityItr = _entitiesToAddToPhysics.erase(entityItr); } else { //qDebug() << "Warning! Failed to generate new shape for entity." << entity->getName(); ++entityItr; diff --git a/libraries/physics/src/PhysicalEntitySimulation.h b/libraries/physics/src/PhysicalEntitySimulation.h index c4f96e023a..ad921bd9a1 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.h +++ b/libraries/physics/src/PhysicalEntitySimulation.h @@ -44,6 +44,8 @@ protected: // only called by EntitySimulation virtual void clearEntitiesInternal() override; public: + virtual void prepareEntityForDelete(EntityItemPointer entity) override; + void getObjectsToDelete(VectorOfMotionStates& result); void getObjectsToAdd(VectorOfMotionStates& result); void setObjectsToChange(const VectorOfMotionStates& objectsToChange); @@ -55,12 +57,12 @@ public: EntityEditPacketSender* getPacketSender() { return _entityPacketSender; } private: - // incoming changes - SetOfEntityMotionStates _pendingRemoves; // EntityMotionStates to be removed from PhysicsEngine (and deleted) - SetOfEntities _pendingAdds; // entities to be be added to PhysicsEngine (and a their EntityMotionState created) + // incoming changes to physics simulation + SetOfEntities _entitiesToRemoveFromPhysics; + SetOfEntities _entitiesToAddToPhysics; // entities to be be added to PhysicsEngine (and a their EntityMotionState created) SetOfEntityMotionStates _pendingChanges; // EntityMotionStates already in PhysicsEngine that need their physics changed - // outgoing changes + // outgoing changes from physics simulation SetOfEntityMotionStates _outgoingChanges; // EntityMotionStates for which we need to send updates to entity-server SetOfMotionStates _physicalObjects; // MotionStates of entities in PhysicsEngine