Replace scene buckets with nonspatial set

This commit is contained in:
Zach Pomerantz 2016-02-26 11:51:53 -08:00
parent 7457b73e74
commit 8e1c514a9c
3 changed files with 46 additions and 114 deletions

View file

@ -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; }

View file

@ -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++;

View file

@ -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<ItemFilter, ItemIDSet, ItemFilter::Less> {
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 <class T> void updateItem(ItemID id, std::function<void(T&)> 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<unsigned int> _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);