From 8e1c514a9c5c289d9c5059f58ce912b709ff0104 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 26 Feb 2016 11:51:53 -0800 Subject: [PATCH] Replace scene buckets with nonspatial set --- libraries/render/src/render/Item.h | 7 +- libraries/render/src/render/Scene.cpp | 112 +++++++------------------- libraries/render/src/render/Scene.h | 41 +++------- 3 files changed, 46 insertions(+), 114 deletions(-) diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 8aaaf07300..53e1f3f0df 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -112,6 +112,7 @@ public: bool isPickable() const { return _flags[PICKABLE]; } bool isLayered() const { return _flags[LAYERED]; } + bool isSpatial() const { return !isLayered(); } // Probably not public, flags used by the scene bool isSmall() const { return _flags[SMALLER]; } @@ -315,8 +316,10 @@ public: // Main scene / item managment interface Reset/Update/Kill void resetPayload(const PayloadPointer& payload); void resetCell(ItemCell cell, bool _small) { _cell = cell; _key.setSmaller(_small); } - void update(const UpdateFunctorPointer& updateFunctor) { _payload->update(updateFunctor); } // Communicate update to the payload - void kill() { _payload.reset(); _key._flags.reset(); _cell = INVALID_CELL; } // Kill means forget the payload and key and cell + // Communicate the update to the payload + void update(const UpdateFunctorPointer& updateFunctor) { _payload->update(updateFunctor); _key = _payload->getKey(); } + // Forget the payload, key, and cell + void kill() { _payload.reset(); _key._flags.reset(); _cell = INVALID_CELL; } // Check heuristic key const ItemKey& getKey() const { return _key; } diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 58b1e61046..624f639d79 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -15,59 +15,11 @@ using namespace render; -void ItemBucketMap::insert(const ItemID& id, const ItemKey& key) { - // Insert the itemID in every bucket where it filters true - for (auto& bucket : (*this)) { - if (bucket.first.test(key)) { - bucket.second.insert(id); - } - } -} -void ItemBucketMap::erase(const ItemID& id, const ItemKey& key) { - // Remove the itemID in every bucket where it filters true - for (auto& bucket : (*this)) { - if (bucket.first.test(key)) { - bucket.second.erase(id); - } - } -} - -void ItemBucketMap::reset(const ItemID& id, const ItemKey& oldKey, const ItemKey& newKey) { - // Reset the itemID in every bucket, - // Remove from the buckets where oldKey filters true AND newKey filters false - // Insert into the buckets where newKey filters true - for (auto& bucket : (*this)) { - if (bucket.first.test(oldKey)) { - if (!bucket.first.test(newKey)) { - bucket.second.erase(id); - } - } else if (bucket.first.test(newKey)) { - bucket.second.insert(id); - } - } -} - -void ItemBucketMap::allocateStandardOpaqueTranparentBuckets() { - (*this)[ItemFilter::Builder::opaqueShape().withoutLayered()]; - (*this)[ItemFilter::Builder::transparentShape().withoutLayered()]; - (*this)[ItemFilter::Builder::light()]; - (*this)[ItemFilter::Builder::background()]; - (*this)[ItemFilter::Builder::opaqueShape().withLayered()]; - (*this)[ItemFilter::Builder::transparentShape().withLayered()]; -} - - void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) { _resetItems.push_back(id); _resetPayloads.push_back(payload); } -void PendingChanges::resortItem(ItemID id, ItemKey oldKey, ItemKey newKey) { - _resortItems.push_back(id); - _resortOldKeys.push_back(oldKey); - _resortNewKeys.push_back(newKey); -} - void PendingChanges::removeItem(ItemID id) { _removedItems.push_back(id); } @@ -80,9 +32,6 @@ void PendingChanges::updateItem(ItemID id, const UpdateFunctorPointer& functor) void PendingChanges::merge(PendingChanges& changes) { _resetItems.insert(_resetItems.end(), changes._resetItems.begin(), changes._resetItems.end()); _resetPayloads.insert(_resetPayloads.end(), changes._resetPayloads.begin(), changes._resetPayloads.end()); - _resortItems.insert(_resortItems.end(), changes._resortItems.begin(), changes._resortItems.end()); - _resortOldKeys.insert(_resortOldKeys.end(), changes._resortOldKeys.begin(), changes._resortOldKeys.end()); - _resortNewKeys.insert(_resortNewKeys.end(), changes._resortNewKeys.begin(), changes._resortNewKeys.end()); _removedItems.insert(_removedItems.end(), changes._removedItems.begin(), changes._removedItems.end()); _updatedItems.insert(_updatedItems.end(), changes._updatedItems.begin(), changes._updatedItems.end()); _updateFunctors.insert(_updateFunctors.end(), changes._updateFunctors.begin(), changes._updateFunctors.end()); @@ -92,7 +41,6 @@ Scene::Scene(glm::vec3 origin, float size) : _masterSpatialTree(origin, size) { _items.push_back(Item()); // add the itemID #0 to nothing - _masterBucketMap.allocateStandardOpaqueTranparentBuckets(); } ItemID Scene::allocateID() { @@ -133,7 +81,6 @@ void Scene::processPendingChangesQueue() { // capture anything coming from the pendingChanges resetItems(consolidatedPendingChanges._resetItems, consolidatedPendingChanges._resetPayloads); updateItems(consolidatedPendingChanges._updatedItems, consolidatedPendingChanges._updateFunctors); - resortItems(consolidatedPendingChanges._resortItems, consolidatedPendingChanges._resortOldKeys, consolidatedPendingChanges._resortNewKeys); removeItems(consolidatedPendingChanges._removedItems); // ready to go back to rendering activities @@ -141,7 +88,6 @@ void Scene::processPendingChangesQueue() { } void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) { - auto resetPayload = payloads.begin(); for (auto resetID : ids) { // Access the true item @@ -153,28 +99,18 @@ void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) { item.resetPayload(*resetPayload); auto newKey = item.getKey(); - - // Reset the item in the Bucket map - _masterBucketMap.reset(resetID, oldKey, newKey); - - // Reset the item in the spatial tree - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), resetID, newKey); - item.resetCell(newCell, newKey.isSmall()); + // Update the item's container + assert((oldKey.isSpatial() == newKey.isSpatial()) || oldKey._flags.none()); + if (newKey.isSpatial()) { + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), resetID, newKey); + item.resetCell(newCell, newKey.isSmall()); + } // next loop resetPayload++; } } -void Scene::resortItems(const ItemIDs& ids, ItemKeys& oldKeys, ItemKeys& newKeys) { - auto resortID = ids.begin(); - auto oldKey = oldKeys.begin(); - auto newKey = newKeys.begin(); - for (; resortID != ids.end(); resortID++, oldKey++, newKey++) { - _masterBucketMap.reset(*resortID, *oldKey, *newKey); - } -} - void Scene::removeItems(const ItemIDs& ids) { for (auto removedID :ids) { // Access the true item @@ -182,11 +118,12 @@ void Scene::removeItems(const ItemIDs& ids) { auto oldCell = item.getCell(); auto oldKey = item.getKey(); - // Remove from Bucket map - _masterBucketMap.erase(removedID, item.getKey()); - - // Remove from spatial tree - _masterSpatialTree.removeItem(oldCell, oldKey, removedID); + // Remove the item + if (oldKey.isSpatial()) { + _masterSpatialTree.removeItem(oldCell, oldKey, removedID); + } else { + _masterNonspatialSet.erase(removedID); + } // Kill it item.kill(); @@ -202,14 +139,27 @@ void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) { auto oldCell = item.getCell(); auto oldKey = item.getKey(); - // Update it - _items[updateID].update((*updateFunctor)); - + // Update the item + item.update((*updateFunctor)); auto newKey = item.getKey(); - // Update the citem in the spatial tree if needed - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey); - item.resetCell(newCell, newKey.isSmall()); + // Update the item's container + if (oldKey.isSpatial() == newKey.isSpatial()) { + if (newKey.isSpatial()) { + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey); + item.resetCell(newCell, newKey.isSmall()); + } + } else { + if (newKey.isSpatial()) { + _masterNonspatialSet.erase(updateID); + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey); + item.resetCell(newCell, newKey.isSmall()); + } else { + _masterSpatialTree.removeItem(oldCell, oldKey, updateID); + _masterNonspatialSet.insert(updateID); + } + } + // next loop updateFunctor++; diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 63aa2ba831..8516c234dd 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -17,21 +17,6 @@ namespace render { -// A map of ItemIDSets allowing to create bucket lists of items which are filtered according to their key -class ItemBucketMap : public std::map { -public: - - ItemBucketMap() {} - - void insert(const ItemID& id, const ItemKey& key); - void erase(const ItemID& id, const ItemKey& key); - void reset(const ItemID& id, const ItemKey& oldKey, const ItemKey& newKey); - - // standard builders allocating the main buckets - void allocateStandardOpaqueTranparentBuckets(); - -}; - class Engine; class PendingChanges { @@ -40,7 +25,6 @@ public: ~PendingChanges() {} void resetItem(ItemID id, const PayloadPointer& payload); - void resortItem(ItemID id, ItemKey oldKey, ItemKey newKey); void removeItem(ItemID id); template void updateItem(ItemID id, std::function func) { @@ -53,9 +37,6 @@ public: ItemIDs _resetItems; Payloads _resetPayloads; - ItemIDs _resortItems; - ItemKeys _resortOldKeys; - ItemKeys _resortNewKeys; ItemIDs _removedItems; ItemIDs _updatedItems; UpdateFunctors _updateFunctors; @@ -75,27 +56,27 @@ public: Scene(glm::vec3 origin, float size); ~Scene() {} - /// This call is thread safe, can be called from anywhere to allocate a new ID + // This call is thread safe, can be called from anywhere to allocate a new ID ItemID allocateID(); - /// Enqueue change batch to the scene + // Enqueue change batch to the scene void enqueuePendingChanges(const PendingChanges& pendingChanges); // Process the penging changes equeued void processPendingChangesQueue(); - /// Access a particular item form its ID - /// WARNING, There is No check on the validity of the ID, so this could return a bad Item + // Access a particular item form its ID + // WARNING, There is No check on the validity of the ID, so this could return a bad Item const Item& getItem(const ItemID& id) const { return _items[id]; } size_t getNumItems() const { return _items.size(); } - /// Access the main bucketmap of items - const ItemBucketMap& getMasterBucket() const { return _masterBucketMap; } - - /// Access the item spatial tree + // Access the spatialized items const ItemSpatialTree& getSpatialTree() const { return _masterSpatialTree; } - + + // Access non-spatialized items (overlays, backgrounds) + const ItemIDSet& getNonspatialSet() const { return _masterNonspatialSet; } + protected: // Thread safe elements that can be accessed from anywhere std::atomic _IDAllocator{ 1 }; // first valid itemID will be One @@ -106,12 +87,10 @@ protected: // database of items is protected for editing by a mutex std::mutex _itemsMutex; Item::Vector _items; - ItemBucketMap _masterBucketMap; ItemSpatialTree _masterSpatialTree; - + ItemIDSet _masterNonspatialSet; void resetItems(const ItemIDs& ids, Payloads& payloads); - void resortItems(const ItemIDs& ids, ItemKeys& oldKeys, ItemKeys& newKeys); void removeItems(const ItemIDs& ids); void updateItems(const ItemIDs& ids, UpdateFunctors& functors);