224 lines · 8.1 KB · C++
RawDownload
////  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 <AACube.h>#include <PerfStat.h> #include "EntityItem.h"#include "MovingEntitiesOperator.h"#include "SimpleEntitySimulation.h" void SimpleEntitySimulation::update(QSet<EntityItem*>& 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<EntityItem*>& 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<EntityItem*>& entitiesToDelete) {    if (_entityTree && _movingEntities.size() > 0) {        PerformanceTimer perfTimer("_movingEntities");        MovingEntitiesOperator moveOperator(_entityTree);        QList<EntityItem*>::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<EntityItem*>& entitiesToDelete) {    QList<EntityItem*>::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);}