Merge pull request #281 from HifiExperiments/parenting2

Improve performance of MyAvatar::simulate when you have lots of descendants
This commit is contained in:
kasenvr 2020-05-31 14:47:22 -04:00 committed by GitHub
commit 4cca7f6f75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 27 deletions

View file

@ -972,7 +972,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
recorder->recordFrame(FRAME_TYPE, toFrame(*this)); recorder->recordFrame(FRAME_TYPE, toFrame(*this));
} }
locationChanged(true, false); locationChanged(true, true);
// if a entity-child of this avatar has moved outside of its queryAACube, update the cube and tell the entity server. // if a entity-child of this avatar has moved outside of its queryAACube, update the cube and tell the entity server.
auto entityTreeRenderer = qApp->getEntities(); auto entityTreeRenderer = qApp->getEntities();
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
@ -981,16 +981,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
entityTree->withWriteLock([&] { entityTree->withWriteLock([&] {
zoneInteractionProperties = entityTreeRenderer->getZoneInteractionProperties(); zoneInteractionProperties = entityTreeRenderer->getZoneInteractionProperties();
EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender(); EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender();
forEachDescendant([&](SpatiallyNestablePointer object) { entityTree->updateEntityQueryAACube(shared_from_this(), packetSender, false, true);
locationChanged(true, false);
// we need to update attached queryAACubes in our own local tree so point-select always works
// however we don't want to flood the update pipeline with AvatarEntity updates, so we assume
// others have all info required to properly update queryAACube of AvatarEntities on their end
EntityItemPointer entity = std::dynamic_pointer_cast<EntityItem>(object);
bool iShouldTellServer = !(entity && entity->isAvatarEntity());
const bool force = false;
entityTree->updateEntityQueryAACube(object, packetSender, force, iShouldTellServer);
});
}); });
bool isPhysicsEnabled = qApp->isPhysicsEnabled(); bool isPhysicsEnabled = qApp->isPhysicsEnabled();
bool zoneAllowsFlying = zoneInteractionProperties.first; bool zoneAllowsFlying = zoneInteractionProperties.first;

View file

@ -3194,21 +3194,30 @@ glm::vec3 EntityTree::getUnscaledDimensionsForID(const QUuid& id) {
return glm::vec3(1.0f); return glm::vec3(1.0f);
} }
void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender, AACube EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
MovingEntitiesOperator& moveOperator, bool force, bool tellServer) { MovingEntitiesOperator& moveOperator, bool force, bool tellServer) {
glm::vec3 min(FLT_MAX);
glm::vec3 max(-FLT_MAX);
// if the queryBox has changed, tell the entity-server // if the queryBox has changed, tell the entity-server
EntityItemPointer entity = std::dynamic_pointer_cast<EntityItem>(object); EntityItemPointer entity = std::dynamic_pointer_cast<EntityItem>(object);
if (entity) { if (entity) {
bool queryAACubeChanged = false; bool queryAACubeChanged = false;
if (!entity->hasChildren()) { if (!entity->hasChildren()) {
// updateQueryAACube will also update all ancestors' AACubes, so we only need to call this for leaf nodes queryAACubeChanged = entity->updateQueryAACube(false);
queryAACubeChanged = entity->updateQueryAACube(); AACube entityAACube = entity->getQueryAACube();
min = glm::min(min, entityAACube.getMinimumPoint());
max = glm::max(max, entityAACube.getMaximumPoint());
} else { } else {
AACube oldCube = entity->getQueryAACube();
object->forEachChild([&](SpatiallyNestablePointer descendant) { object->forEachChild([&](SpatiallyNestablePointer descendant) {
updateEntityQueryAACubeWorker(descendant, packetSender, moveOperator, force, tellServer); AACube entityAACube = updateEntityQueryAACubeWorker(descendant, packetSender, moveOperator, force, tellServer);
min = glm::min(min, entityAACube.getMinimumPoint());
max = glm::max(max, entityAACube.getMaximumPoint());
}); });
queryAACubeChanged = oldCube != entity->getQueryAACube(); queryAACubeChanged = entity->updateQueryAACubeWithDescendantAACube(AACube(Extents(min, max)), false);
AACube newCube = entity->getQueryAACube();
min = glm::min(min, newCube.getMinimumPoint());
max = glm::max(max, newCube.getMaximumPoint());
} }
if (queryAACubeChanged || force) { if (queryAACubeChanged || force) {
@ -3217,9 +3226,10 @@ void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object,
if (success) { if (success) {
moveOperator.addEntityToMoveList(entity, newCube); moveOperator.addEntityToMoveList(entity, newCube);
} }
// send an edit packet to update the entity-server about the queryAABox. We do this for domain-hosted // send an edit packet to update the entity-server about the queryAABox. We only do this for domain-hosted
// entities as well as for avatar-entities; the packet-sender will route the update accordingly // entities, as we don't want to flood the update pipeline with AvatarEntity updates, so we assume
if (tellServer && packetSender && (entity->isDomainEntity() || entity->isAvatarEntity())) { // others have all info required to properly update queryAACube of AvatarEntities on their end
if (tellServer && packetSender && entity->isDomainEntity()) {
quint64 now = usecTimestampNow(); quint64 now = usecTimestampNow();
EntityItemProperties properties = entity->getProperties(); EntityItemProperties properties = entity->getProperties();
properties.setQueryAACubeDirty(); properties.setQueryAACubeDirty();
@ -3234,7 +3244,16 @@ void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object,
entity->markDirtyFlags(Simulation::DIRTY_POSITION); entity->markDirtyFlags(Simulation::DIRTY_POSITION);
entityChanged(entity); entityChanged(entity);
} }
} else {
// if we're called on a non-entity, we might still have entity descendants
object->forEachChild([&](SpatiallyNestablePointer descendant) {
AACube entityAACube = updateEntityQueryAACubeWorker(descendant, packetSender, moveOperator, force, tellServer);
min = glm::min(min, entityAACube.getMinimumPoint());
max = glm::max(max, entityAACube.getMaximumPoint());
});
} }
return AACube(Extents(min, max));
} }
void EntityTree::updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender, void EntityTree::updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,

View file

@ -400,7 +400,8 @@ private:
std::map<QString, QString> _namedPaths; std::map<QString, QString> _namedPaths;
void updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender, // Return an AACube containing object and all its entity descendants
AACube updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
MovingEntitiesOperator& moveOperator, bool force, bool tellServer); MovingEntitiesOperator& moveOperator, bool force, bool tellServer);
}; };

View file

@ -1144,7 +1144,7 @@ AACube SpatiallyNestable::calculateInitialQueryAACube(bool& success) {
} }
} }
bool SpatiallyNestable::updateQueryAACube() { bool SpatiallyNestable::updateQueryAACube(bool updateParent) {
if (!queryAACubeNeedsUpdate()) { if (!queryAACubeNeedsUpdate()) {
return false; return false;
} }
@ -1171,10 +1171,40 @@ bool SpatiallyNestable::updateQueryAACube() {
_queryAACubeSet = true; _queryAACubeSet = true;
if (updateParent) {
auto parent = getParentPointer(success); auto parent = getParentPointer(success);
if (success && parent) { if (success && parent) {
parent->updateQueryAACube(); parent->updateQueryAACube();
} }
}
return true;
}
bool SpatiallyNestable::updateQueryAACubeWithDescendantAACube(const AACube& descendantAACube, bool updateParent) {
if (!queryAACubeNeedsUpdateWithDescendantAACube(descendantAACube)) {
return false;
}
bool success;
AACube initialQueryAACube = calculateInitialQueryAACube(success);
if (!success) {
return false;
}
_queryAACube = initialQueryAACube;
_queryAACubeIsPuffed = shouldPuffQueryAACube();
_queryAACube += descendantAACube.getMinimumPoint();
_queryAACube += descendantAACube.getMaximumPoint();
_queryAACubeSet = true;
if (updateParent) {
auto parent = getParentPointer(success);
if (success && parent) {
parent->updateQueryAACube();
}
}
return true; return true;
} }
@ -1216,6 +1246,24 @@ bool SpatiallyNestable::queryAACubeNeedsUpdate() const {
return childNeedsUpdate; return childNeedsUpdate;
} }
bool SpatiallyNestable::queryAACubeNeedsUpdateWithDescendantAACube(const AACube& descendantAACube) const {
if (!_queryAACubeSet) {
return true;
}
bool success;
AACube maxAACube = getMaximumAACube(success);
if (success && !_queryAACube.contains(maxAACube)) {
return true;
}
if (shouldPuffQueryAACube() != _queryAACubeIsPuffed) {
return true;
}
return !_queryAACube.contains(descendantAACube);
}
AACube SpatiallyNestable::getQueryAACube(bool& success) const { AACube SpatiallyNestable::getQueryAACube(bool& success) const {
if (_queryAACubeSet) { if (_queryAACubeSet) {
success = true; success = true;

View file

@ -117,8 +117,10 @@ public:
virtual void setQueryAACube(const AACube& queryAACube); virtual void setQueryAACube(const AACube& queryAACube);
virtual bool queryAACubeNeedsUpdate() const; virtual bool queryAACubeNeedsUpdate() const;
virtual bool queryAACubeNeedsUpdateWithDescendantAACube(const AACube& descendantAACube) const;
virtual bool shouldPuffQueryAACube() const { return false; } virtual bool shouldPuffQueryAACube() const { return false; }
bool updateQueryAACube(); bool updateQueryAACube(bool updateParent = true);
bool updateQueryAACubeWithDescendantAACube(const AACube& descendentAACube, bool updateParent = true);
void forceQueryAACubeUpdate() { _queryAACubeSet = false; } void forceQueryAACubeUpdate() { _queryAACubeSet = false; }
virtual AACube getQueryAACube(bool& success) const; virtual AACube getQueryAACube(bool& success) const;
virtual AACube getQueryAACube() const; virtual AACube getQueryAACube() const;