mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 11:53:28 +02:00
Replace scene buckets with nonspatial set
This commit is contained in:
parent
7457b73e74
commit
8e1c514a9c
3 changed files with 46 additions and 114 deletions
|
@ -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; }
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue