remove entities from physics before we delete them

This commit is contained in:
Andrew Meadows 2015-12-29 11:05:02 -08:00
parent b34df211df
commit f5d24a87ca
5 changed files with 58 additions and 38 deletions

View file

@ -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);

View file

@ -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();
}

View file

@ -101,6 +101,9 @@ protected:
QList<EntityActionPointer> _actionsToAdd;
QSet<QUuid> _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)
};

View file

@ -47,7 +47,7 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) {
if (entity->shouldBePhysical()) {
EntityMotionState* motionState = static_cast<EntityMotionState*>(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<EntityMotionState*>(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<EntityMotionState*>(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<void*>(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;

View file

@ -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