mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 11:28:03 +02:00
split work out of EntityTree::update(), call it preUpdate()
This commit is contained in:
parent
3eed8218ca
commit
915cbb69df
14 changed files with 76 additions and 35 deletions
|
@ -37,6 +37,7 @@ void EntityTreeHeadlessViewer::update() {
|
||||||
if (_tree) {
|
if (_tree) {
|
||||||
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
||||||
tree->withTryWriteLock([&] {
|
tree->withTryWriteLock([&] {
|
||||||
|
tree->preUpdate();
|
||||||
tree->update();
|
tree->update();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6399,6 +6399,8 @@ void Application::update(float deltaTime) {
|
||||||
PROFILE_RANGE(simulation_physics, "Simulation");
|
PROFILE_RANGE(simulation_physics, "Simulation");
|
||||||
PerformanceTimer perfTimer("simulation");
|
PerformanceTimer perfTimer("simulation");
|
||||||
|
|
||||||
|
getEntities()->preUpdate();
|
||||||
|
|
||||||
if (_physicsEnabled) {
|
if (_physicsEnabled) {
|
||||||
auto t0 = std::chrono::high_resolution_clock::now();
|
auto t0 = std::chrono::high_resolution_clock::now();
|
||||||
auto t1 = t0;
|
auto t1 = t0;
|
||||||
|
|
|
@ -474,6 +474,12 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityTreeRenderer::preUpdate() {
|
||||||
|
if (_tree && !_shuttingDown) {
|
||||||
|
_tree->preUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::update(bool simulate) {
|
void EntityTreeRenderer::update(bool simulate) {
|
||||||
PROFILE_RANGE(simulation_physics, "ETR::update");
|
PROFILE_RANGE(simulation_physics, "ETR::update");
|
||||||
PerformanceTimer perfTimer("ETRupdate");
|
PerformanceTimer perfTimer("ETRupdate");
|
||||||
|
|
|
@ -78,6 +78,7 @@ public:
|
||||||
void setSetPrecisionPickingOperator(std::function<void(unsigned int, bool)> setPrecisionPickingOperator) { _setPrecisionPickingOperator = setPrecisionPickingOperator; }
|
void setSetPrecisionPickingOperator(std::function<void(unsigned int, bool)> setPrecisionPickingOperator) { _setPrecisionPickingOperator = setPrecisionPickingOperator; }
|
||||||
|
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
void preUpdate();
|
||||||
void update(bool simulate);
|
void update(bool simulate);
|
||||||
|
|
||||||
EntityTreePointer getTree() { return std::static_pointer_cast<EntityTree>(_tree); }
|
EntityTreePointer getTree() { return std::static_pointer_cast<EntityTree>(_tree); }
|
||||||
|
|
|
@ -176,17 +176,26 @@ void EntitySimulation::addEntity(EntityItemPointer entity) {
|
||||||
void EntitySimulation::changeEntity(EntityItemPointer entity) {
|
void EntitySimulation::changeEntity(EntityItemPointer entity) {
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&_mutex);
|
||||||
assert(entity);
|
assert(entity);
|
||||||
if (!entity->isSimulated()) {
|
_changedEntities.insert(entity);
|
||||||
// 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.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void EntitySimulation::processChangedEntities() {
|
||||||
|
QMutexLocker lock(&_mutex);
|
||||||
|
PROFILE_RANGE_EX(simulation_physics, "processChangedEntities", 0xffff00ff, (uint64_t)_changedEntities.size());
|
||||||
|
for (auto& entity : _changedEntities) {
|
||||||
|
if (entity->isSimulated()) {
|
||||||
|
processChangedEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_changedEntities.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntitySimulation::processChangedEntity(const EntityItemPointer& entity) {
|
||||||
|
uint32_t dirtyFlags = entity->getDirtyFlags();
|
||||||
|
/* TODO? maybe add to _entitiesToSort when DIRTY_POSITION is set?
|
||||||
// Although it is not the responsibility of the EntitySimulation to sort the tree for EXTERNAL changes
|
// Although it is not the responsibility of the EntitySimulation to sort the tree for EXTERNAL changes
|
||||||
// it IS responsibile for triggering deletes for entities that leave the bounds of the domain, hence
|
// it IS responsibile for triggering deletes for entities that leave the bounds of the domain, hence
|
||||||
// we must check for that case here, however we rely on the change event to have set DIRTY_POSITION flag.
|
// we must check for that case here, however we rely on the change event to have set DIRTY_POSITION flag.
|
||||||
uint32_t dirtyFlags = entity->getDirtyFlags();
|
|
||||||
if (dirtyFlags & Simulation::DIRTY_POSITION) {
|
if (dirtyFlags & Simulation::DIRTY_POSITION) {
|
||||||
AACube domainBounds(glm::vec3((float)-HALF_TREE_SCALE), (float)TREE_SCALE);
|
AACube domainBounds(glm::vec3((float)-HALF_TREE_SCALE), (float)TREE_SCALE);
|
||||||
bool success;
|
bool success;
|
||||||
|
@ -198,25 +207,29 @@ void EntitySimulation::changeEntity(EntityItemPointer entity) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (dirtyFlags & Simulation::DIRTY_LIFETIME) {
|
if (dirtyFlags & (Simulation::DIRTY_LIFETIME | Simulation::DIRTY_UPDATEABLE)) {
|
||||||
if (entity->isMortal()) {
|
if (dirtyFlags & Simulation::DIRTY_LIFETIME) {
|
||||||
_mortalEntities.insert(entity);
|
if (entity->isMortal()) {
|
||||||
uint64_t expiry = entity->getExpiry();
|
_mortalEntities.insert(entity);
|
||||||
if (expiry < _nextExpiry) {
|
uint64_t expiry = entity->getExpiry();
|
||||||
_nextExpiry = expiry;
|
if (expiry < _nextExpiry) {
|
||||||
|
_nextExpiry = expiry;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_mortalEntities.remove(entity);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
_mortalEntities.remove(entity);
|
|
||||||
}
|
}
|
||||||
entity->clearDirtyFlags(Simulation::DIRTY_LIFETIME);
|
if (dirtyFlags & Simulation::DIRTY_UPDATEABLE) {
|
||||||
|
if (entity->needsToCallUpdate()) {
|
||||||
|
_entitiesToUpdate.insert(entity);
|
||||||
|
} else {
|
||||||
|
_entitiesToUpdate.remove(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entity->clearDirtyFlags(Simulation::DIRTY_LIFETIME | Simulation::DIRTY_UPDATEABLE);
|
||||||
}
|
}
|
||||||
if (entity->needsToCallUpdate()) {
|
|
||||||
_entitiesToUpdate.insert(entity);
|
|
||||||
} else {
|
|
||||||
_entitiesToUpdate.remove(entity);
|
|
||||||
}
|
|
||||||
changeEntityInternal(entity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntitySimulation::clearEntities() {
|
void EntitySimulation::clearEntities() {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#define hifi_EntitySimulation_h
|
#define hifi_EntitySimulation_h
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
@ -82,13 +83,15 @@ public:
|
||||||
/// \param entity pointer to EntityItem that needs to be put on the entitiesToDelete list and removed from others.
|
/// \param entity pointer to EntityItem that needs to be put on the entitiesToDelete list and removed from others.
|
||||||
virtual void prepareEntityForDelete(EntityItemPointer entity);
|
virtual void prepareEntityForDelete(EntityItemPointer entity);
|
||||||
|
|
||||||
|
void processChangedEntities();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// These pure virtual methods are protected because they are not to be called will-nilly. The base class
|
// These pure virtual methods are protected because they are not to be called will-nilly. The base class
|
||||||
// calls them in the right places.
|
// calls them in the right places.
|
||||||
virtual void updateEntitiesInternal(uint64_t now) = 0;
|
virtual void updateEntitiesInternal(uint64_t now) = 0;
|
||||||
virtual void addEntityInternal(EntityItemPointer entity) = 0;
|
virtual void addEntityInternal(EntityItemPointer entity) = 0;
|
||||||
virtual void removeEntityInternal(EntityItemPointer entity);
|
virtual void removeEntityInternal(EntityItemPointer entity);
|
||||||
virtual void changeEntityInternal(EntityItemPointer entity) = 0;
|
virtual void processChangedEntity(const EntityItemPointer& entity);
|
||||||
virtual void clearEntitiesInternal() = 0;
|
virtual void clearEntitiesInternal() = 0;
|
||||||
|
|
||||||
void expireMortalEntities(uint64_t now);
|
void expireMortalEntities(uint64_t now);
|
||||||
|
@ -114,11 +117,11 @@ private:
|
||||||
|
|
||||||
// We maintain multiple lists, each for its distinct purpose.
|
// We maintain multiple lists, each for its distinct purpose.
|
||||||
// An entity may be in more than one list.
|
// An entity may be in more than one list.
|
||||||
|
std::unordered_set<EntityItemPointer> _changedEntities; // all changes this frame
|
||||||
SetOfEntities _allEntities; // tracks all entities added the simulation
|
SetOfEntities _allEntities; // tracks all entities added the simulation
|
||||||
SetOfEntities _mortalEntities; // entities that have an expiry
|
SetOfEntities _mortalEntities; // entities that have an expiry
|
||||||
uint64_t _nextExpiry;
|
uint64_t _nextExpiry;
|
||||||
|
|
||||||
|
|
||||||
SetOfEntities _entitiesToUpdate; // entities that need to call EntityItem::update()
|
SetOfEntities _entitiesToUpdate; // entities that need to call EntityItem::update()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2188,11 +2188,19 @@ void EntityTree::addToNeedsParentFixupList(EntityItemPointer entity) {
|
||||||
_needsParentFixup.append(entity);
|
_needsParentFixup.append(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityTree::preUpdate() {
|
||||||
|
withWriteLock([&] {
|
||||||
|
fixupNeedsParentFixups();
|
||||||
|
if (_simulation) {
|
||||||
|
_simulation->processChangedEntities();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void EntityTree::update(bool simulate) {
|
void EntityTree::update(bool simulate) {
|
||||||
PROFILE_RANGE(simulation_physics, "UpdateTree");
|
PROFILE_RANGE(simulation_physics, "UpdateTree");
|
||||||
PerformanceTimer perfTimer("updateTree");
|
PerformanceTimer perfTimer("updateTree");
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
fixupNeedsParentFixups();
|
|
||||||
if (simulate && _simulation) {
|
if (simulate && _simulation) {
|
||||||
_simulation->updateEntities();
|
_simulation->updateEntities();
|
||||||
{
|
{
|
||||||
|
|
|
@ -109,9 +109,10 @@ public:
|
||||||
|
|
||||||
virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const override;
|
virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const override;
|
||||||
|
|
||||||
virtual void update() override { update(true); }
|
// Why preUpdate() and update()?
|
||||||
|
// Because sometimes we need to do stuff between the two.
|
||||||
void update(bool simulate);
|
void preUpdate() override;
|
||||||
|
void update(bool simulate = true) override;
|
||||||
|
|
||||||
// The newer API...
|
// The newer API...
|
||||||
void postAddEntity(EntityItemPointer entityItem);
|
void postAddEntity(EntityItemPointer entityItem);
|
||||||
|
|
|
@ -85,7 +85,9 @@ void SimpleEntitySimulation::removeEntityInternal(EntityItemPointer entity) {
|
||||||
_entitiesThatNeedSimulationOwner.remove(entity);
|
_entitiesThatNeedSimulationOwner.remove(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
|
void SimpleEntitySimulation::processChangedEntity(const EntityItemPointer& entity) {
|
||||||
|
EntitySimulation::processChangedEntity(entity);
|
||||||
|
|
||||||
uint32_t flags = entity->getDirtyFlags();
|
uint32_t flags = entity->getDirtyFlags();
|
||||||
if ((flags & Simulation::DIRTY_SIMULATOR_ID) || (flags & Simulation::DIRTY_VELOCITIES)) {
|
if ((flags & Simulation::DIRTY_SIMULATOR_ID) || (flags & Simulation::DIRTY_VELOCITIES)) {
|
||||||
if (entity->getSimulatorID().isNull()) {
|
if (entity->getSimulatorID().isNull()) {
|
||||||
|
|
|
@ -31,7 +31,7 @@ protected:
|
||||||
void updateEntitiesInternal(uint64_t now) override;
|
void updateEntitiesInternal(uint64_t now) override;
|
||||||
void addEntityInternal(EntityItemPointer entity) override;
|
void addEntityInternal(EntityItemPointer entity) override;
|
||||||
void removeEntityInternal(EntityItemPointer entity) override;
|
void removeEntityInternal(EntityItemPointer entity) override;
|
||||||
void changeEntityInternal(EntityItemPointer entity) override;
|
void processChangedEntity(const EntityItemPointer& entity) override;
|
||||||
void clearEntitiesInternal() override;
|
void clearEntitiesInternal() override;
|
||||||
|
|
||||||
void sortEntitiesThatMoved() override;
|
void sortEntitiesThatMoved() override;
|
||||||
|
|
|
@ -145,7 +145,10 @@ public:
|
||||||
virtual bool rootElementHasData() const { return false; }
|
virtual bool rootElementHasData() const { return false; }
|
||||||
virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const { }
|
virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const { }
|
||||||
|
|
||||||
virtual void update() { } // nothing to do by default
|
// Why preUpdate() and update()?
|
||||||
|
// Because EntityTree needs them.
|
||||||
|
virtual void preUpdate() { }
|
||||||
|
virtual void update(bool simulate = true) { }
|
||||||
|
|
||||||
OctreeElementPointer getRoot() { return _rootElement; }
|
OctreeElementPointer getRoot() { return _rootElement; }
|
||||||
|
|
||||||
|
|
|
@ -242,6 +242,7 @@ bool OctreePersistThread::backupCurrentFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreePersistThread::process() {
|
void OctreePersistThread::process() {
|
||||||
|
_tree->preUpdate();
|
||||||
_tree->update();
|
_tree->update();
|
||||||
|
|
||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
|
@ -131,10 +131,10 @@ void PhysicalEntitySimulation::takeDeadAvatarEntities(SetOfEntities& deadEntitie
|
||||||
_deadAvatarEntities.clear();
|
_deadAvatarEntities.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
|
void PhysicalEntitySimulation::processChangedEntity(const EntityItemPointer& entity) {
|
||||||
|
EntitySimulation::processChangedEntity(entity);
|
||||||
|
|
||||||
// queue incoming changes: from external sources (script, EntityServer, etc) to physics engine
|
// queue incoming changes: from external sources (script, EntityServer, etc) to physics engine
|
||||||
QMutexLocker lock(&_mutex);
|
|
||||||
assert(entity);
|
|
||||||
EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
|
EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
|
||||||
uint8_t region = _space->getRegion(entity->getSpaceIndex());
|
uint8_t region = _space->getRegion(entity->getSpaceIndex());
|
||||||
bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical();
|
bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical();
|
||||||
|
|
|
@ -72,7 +72,7 @@ protected: // only called by EntitySimulation
|
||||||
virtual void updateEntitiesInternal(uint64_t now) override;
|
virtual void updateEntitiesInternal(uint64_t now) override;
|
||||||
virtual void addEntityInternal(EntityItemPointer entity) override;
|
virtual void addEntityInternal(EntityItemPointer entity) override;
|
||||||
virtual void removeEntityInternal(EntityItemPointer entity) override;
|
virtual void removeEntityInternal(EntityItemPointer entity) override;
|
||||||
virtual void changeEntityInternal(EntityItemPointer entity) override;
|
void processChangedEntity(const EntityItemPointer& entity) override;
|
||||||
virtual void clearEntitiesInternal() override;
|
virtual void clearEntitiesInternal() override;
|
||||||
|
|
||||||
void removeOwnershipData(EntityMotionState* motionState);
|
void removeOwnershipData(EntityMotionState* motionState);
|
||||||
|
|
Loading…
Reference in a new issue