From dfdace8cdc049714895bae5bea55b07a2cdaf956 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 10 May 2019 14:52:26 -0700 Subject: [PATCH] fix zones for real this time --- .../src/EntityTreeRenderer.cpp | 72 ++++++++++--------- .../src/EntityTreeRenderer.h | 14 ++-- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index fbf577755d..ae8473e544 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -591,7 +591,7 @@ void EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QSetgetVisible() && renderableIdForEntity(entity) != render::Item::INVALID_ITEM_ID) { - _layeredZones.emplace(std::dynamic_pointer_cast(entity)); + _layeredZones.emplace_back(std::dynamic_pointer_cast(entity)); } if ((!hasScript && isZone) || scriptHasLoaded) { @@ -600,6 +600,7 @@ void EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QSet(getTree()->findEntityByEntityItemID(id))) { - _layeredZones.update(zone, _avatarPosition, this); - applyLayeredZones(); + if (_layeredZones.update(zone, _avatarPosition, this)) { + applyLayeredZones(); + } } } bool EntityTreeRenderer::LayeredZones::clearDomainAndNonOwnedZones(const QUuid& sessionUUID) { bool zonesChanged = false; - auto it = c.begin(); - while (it != c.end()) { + auto it = begin(); + while (it != end()) { auto zone = it->zone.lock(); if (!zone || !(zone->isLocalEntity() || (zone->isAvatarEntity() && zone->getOwningAvatarID() == sessionUUID))) { zonesChanged = true; - it = c.erase(it); + it = erase(it); } else { it++; } } if (zonesChanged) { - std::make_heap(c.begin(), c.end(), comp); + sort(); } return zonesChanged; } std::pair EntityTreeRenderer::LayeredZones::getZoneInteractionProperties() const { - auto it = c.cbegin(); - while (it != c.cend()) { + for (auto it = cbegin(); it != cend(); it++) { auto zone = it->zone.lock(); if (zone && zone->isDomainEntity()) { return { zone->getFlyingAllowed(), zone->getGhostingAllowed() }; } - it++; } return { true, true }; } -void EntityTreeRenderer::LayeredZones::remove(const std::shared_ptr& zone) { - auto it = c.begin(); - while (it != c.end()) { - if (it->zone.lock() == zone) { - break; - } - it++; - } - if (it != c.end()) { - c.erase(it); - std::make_heap(c.begin(), c.end(), comp); - } -} - -void EntityTreeRenderer::LayeredZones::update(std::shared_ptr zone, const glm::vec3& position, EntityTreeRenderer* entityTreeRenderer) { +bool EntityTreeRenderer::LayeredZones::update(std::shared_ptr zone, const glm::vec3& position, EntityTreeRenderer* entityTreeRenderer) { // When a zone's position or visibility changes, we call this method // In order to resort our zones, we first remove the changed zone, and then re-insert it if necessary - remove(zone); + + bool needsResort = false; + + { + auto it = begin(); + while (it != end()) { + if (it->zone.lock() == zone) { + break; + } + it++; + } + if (it != end()) { + erase(it); + needsResort = true; + } + } // Only call contains if the zone is rendering if (zone->isVisible() && entityTreeRenderer->renderableIdForEntity(zone) != render::Item::INVALID_ITEM_ID && zone->contains(position)) { - emplace(zone); + emplace_back(zone); + needsResort = true; } + + if (needsResort) { + sort(); + } + + return needsResort; } bool EntityTreeRenderer::LayeredZones::equals(const LayeredZones& other) const { @@ -1254,9 +1262,9 @@ bool EntityTreeRenderer::LayeredZones::equals(const LayeredZones& other) const { return false; } - auto it = c.cbegin(); - auto otherIt = other.c.cbegin(); - while (it != c.cend()) { + auto it = cbegin(); + auto otherIt = other.cbegin(); + while (it != cend()) { if (*it != *otherIt) { return false; } @@ -1268,15 +1276,13 @@ bool EntityTreeRenderer::LayeredZones::equals(const LayeredZones& other) const { } void EntityTreeRenderer::LayeredZones::appendRenderIDs(render::ItemIDs& list, EntityTreeRenderer* entityTreeRenderer) const { - auto it = c.cbegin(); - while (it != c.cend()) { + for (auto it = cbegin(); it != cend(); it++) { if (it->zone.lock()) { auto id = entityTreeRenderer->renderableIdForEntityId(it->id); if (id != render::Item::INVALID_ITEM_ID) { list.push_back(id); } } - it++; } } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index a0243a159a..f794d947ed 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -213,24 +213,24 @@ private: public: LayeredZone(std::shared_ptr zone) : zone(zone), id(zone->getID()), volume(zone->getVolumeEstimate()) {} - bool operator>(const LayeredZone& r) const { return volume > r.volume; } - bool operator==(const LayeredZone& r) const { return zone.lock() == r.zone.lock(); } + // We need to sort on volume AND id so that different clients sort zones with identical volumes the same way + bool operator<(const LayeredZone& r) const { return volume < r.volume || (volume == r.volume && id < r.id); } + bool operator==(const LayeredZone& r) const { return zone.lock() && zone.lock() == r.zone.lock(); } bool operator!=(const LayeredZone& r) const { return !(*this == r); } - bool operator>=(const LayeredZone& r) const { return (*this > r) || (*this == r); } + bool operator<=(const LayeredZone& r) const { return (*this < r) || (*this == r); } std::weak_ptr zone; QUuid id; float volume; }; - class LayeredZones : public std::priority_queue, std::greater> { + class LayeredZones : public std::vector { public: - void clear() { *this = LayeredZones(); } bool clearDomainAndNonOwnedZones(const QUuid& sessionUUID); + void sort() { std::sort(begin(), end(), std::less()); } bool equals(const LayeredZones& other) const; - void remove(const std::shared_ptr& zone); - void update(std::shared_ptr zone, const glm::vec3& position, EntityTreeRenderer* entityTreeRenderer); + bool update(std::shared_ptr zone, const glm::vec3& position, EntityTreeRenderer* entityTreeRenderer); void appendRenderIDs(render::ItemIDs& list, EntityTreeRenderer* entityTreeRenderer) const; std::pair getZoneInteractionProperties() const;