// // SimpleEntitySimulation.cpp // libraries/entities/src // // Created by Andrew Meadows on 2014.11.24 // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include #include #include "EntityItem.h" #include "MovingEntitiesOperator.h" #include "SimpleEntitySimulation.h" void SimpleEntitySimulation::update(QSet& entitiesToDelete) { quint64 now = usecTimestampNow(); updateChangedEntities(now, entitiesToDelete); updateMovingEntities(now, entitiesToDelete); updateMortalEntities(now, entitiesToDelete); } void SimpleEntitySimulation::addEntity(EntityItem* entity) { assert(entity && entity->getSimulationState() == EntityItem::Static); EntityItem::SimulationState state = entity->computeSimulationState(); switch(state) { case EntityItem::Moving: _movingEntities.push_back(entity); entity->setSimulationState(state); break; case EntityItem::Mortal: _mortalEntities.push_back(entity); entity->setSimulationState(state); break; case EntityItem::Static: default: break; } } void SimpleEntitySimulation::removeEntity(EntityItem* entity) { assert(entity); // make sure to remove it from any of our simulation lists EntityItem::SimulationState state = entity->getSimulationState(); switch (state) { case EntityItem::Moving: _movingEntities.removeAll(entity); break; case EntityItem::Mortal: _mortalEntities.removeAll(entity); break; default: break; } entity->setSimulationState(EntityItem::Static); _changedEntities.remove(entity); } void SimpleEntitySimulation::entityChanged(EntityItem* entity) { assert(entity); // we batch all changes and deal with them in updateChangedEntities() _changedEntities.insert(entity); } void SimpleEntitySimulation::clearEntities() { foreach (EntityItem* entity, _changedEntities) { entity->clearUpdateFlags(); entity->setSimulationState(EntityItem::Static); } _changedEntities.clear(); _movingEntities.clear(); _mortalEntities.clear(); } void SimpleEntitySimulation::updateChangedEntities(quint64 now, QSet& entitiesToDelete) { foreach (EntityItem* entity, _changedEntities) { // check to see if the lifetime has expired, for immortal entities this is always false if (entity->lifetimeHasExpired()) { qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID(); entitiesToDelete.insert(entity); clearEntityState(entity); } else { updateEntityState(entity); } entity->clearUpdateFlags(); } _changedEntities.clear(); } void SimpleEntitySimulation::updateMovingEntities(quint64 now, QSet& entitiesToDelete) { if (_entityTree && _movingEntities.size() > 0) { PerformanceTimer perfTimer("_movingEntities"); MovingEntitiesOperator moveOperator(_entityTree); QList::iterator item_itr = _movingEntities.begin(); while (item_itr != _movingEntities.end()) { EntityItem* entity = *item_itr; // always check to see if the lifetime has expired, for immortal entities this is always false if (entity->lifetimeHasExpired()) { qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID(); entitiesToDelete.insert(entity); // remove entity from the list item_itr = _movingEntities.erase(item_itr); entity->setSimulationState(EntityItem::Static); } else { AACube oldCube = entity->getMaximumAACube(); entity->update(now); AACube newCube = entity->getMaximumAACube(); // check to see if this movement has sent the entity outside of the domain. AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f); if (!domainBounds.touches(newCube)) { qDebug() << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; entitiesToDelete.insert(entity); // remove entity from the list item_itr = _movingEntities.erase(item_itr); entity->setSimulationState(EntityItem::Static); } else { moveOperator.addEntityToMoveList(entity, oldCube, newCube); EntityItem::SimulationState newState = entity->computeSimulationState(); if (newState != EntityItem::Moving) { if (newState == EntityItem::Mortal) { _mortalEntities.push_back(entity); } // remove entity from the list item_itr = _movingEntities.erase(item_itr); entity->setSimulationState(newState); } else { ++item_itr; } } } } if (moveOperator.hasMovingEntities()) { PerformanceTimer perfTimer("recurseTreeWithOperator"); _entityTree->recurseTreeWithOperator(&moveOperator); } } } void SimpleEntitySimulation::updateMortalEntities(quint64 now, QSet& entitiesToDelete) { QList::iterator item_itr = _mortalEntities.begin(); while (item_itr != _mortalEntities.end()) { EntityItem* entity = *item_itr; // always check to see if the lifetime has expired, for immortal entities this is always false if (entity->lifetimeHasExpired()) { qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID(); entitiesToDelete.insert(entity); // remove entity from the list item_itr = _mortalEntities.erase(item_itr); entity->setSimulationState(EntityItem::Static); } else { // check to see if this entity is no longer moving EntityItem::SimulationState newState = entity->computeSimulationState(); if (newState != EntityItem::Mortal) { if (newState == EntityItem::Moving) { entity->update(now); _movingEntities.push_back(entity); } // remove entity from the list item_itr = _mortalEntities.erase(item_itr); entity->setSimulationState(newState); } else { ++item_itr; } } } } void SimpleEntitySimulation::updateEntityState(EntityItem* entity) { EntityItem::SimulationState oldState = entity->getSimulationState(); EntityItem::SimulationState newState = entity->computeSimulationState(); if (newState != oldState) { switch (oldState) { case EntityItem::Moving: _movingEntities.removeAll(entity); break; case EntityItem::Mortal: _mortalEntities.removeAll(entity); break; default: break; } switch (newState) { case EntityItem::Moving: _movingEntities.push_back(entity); break; case EntityItem::Mortal: _mortalEntities.push_back(entity); break; default: break; } entity->setSimulationState(newState); } } void SimpleEntitySimulation::clearEntityState(EntityItem* entity) { EntityItem::SimulationState oldState = entity->getSimulationState(); switch (oldState) { case EntityItem::Moving: _movingEntities.removeAll(entity); break; case EntityItem::Mortal: _mortalEntities.removeAll(entity); break; default: break; } entity->setSimulationState(EntityItem::Static); }