mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 04:12:46 +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 isPickable() const { return _flags[PICKABLE]; }
|
||||||
|
|
||||||
bool isLayered() const { return _flags[LAYERED]; }
|
bool isLayered() const { return _flags[LAYERED]; }
|
||||||
|
bool isSpatial() const { return !isLayered(); }
|
||||||
|
|
||||||
// Probably not public, flags used by the scene
|
// Probably not public, flags used by the scene
|
||||||
bool isSmall() const { return _flags[SMALLER]; }
|
bool isSmall() const { return _flags[SMALLER]; }
|
||||||
|
@ -315,8 +316,10 @@ public:
|
||||||
// Main scene / item managment interface Reset/Update/Kill
|
// Main scene / item managment interface Reset/Update/Kill
|
||||||
void resetPayload(const PayloadPointer& payload);
|
void resetPayload(const PayloadPointer& payload);
|
||||||
void resetCell(ItemCell cell, bool _small) { _cell = cell; _key.setSmaller(_small); }
|
void resetCell(ItemCell cell, bool _small) { _cell = cell; _key.setSmaller(_small); }
|
||||||
void update(const UpdateFunctorPointer& updateFunctor) { _payload->update(updateFunctor); } // Communicate update to the payload
|
// Communicate the update to the payload
|
||||||
void kill() { _payload.reset(); _key._flags.reset(); _cell = INVALID_CELL; } // Kill means forget the payload and key and cell
|
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
|
// Check heuristic key
|
||||||
const ItemKey& getKey() const { return _key; }
|
const ItemKey& getKey() const { return _key; }
|
||||||
|
|
|
@ -15,59 +15,11 @@
|
||||||
|
|
||||||
using namespace render;
|
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) {
|
void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) {
|
||||||
_resetItems.push_back(id);
|
_resetItems.push_back(id);
|
||||||
_resetPayloads.push_back(payload);
|
_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) {
|
void PendingChanges::removeItem(ItemID id) {
|
||||||
_removedItems.push_back(id);
|
_removedItems.push_back(id);
|
||||||
}
|
}
|
||||||
|
@ -80,9 +32,6 @@ void PendingChanges::updateItem(ItemID id, const UpdateFunctorPointer& functor)
|
||||||
void PendingChanges::merge(PendingChanges& changes) {
|
void PendingChanges::merge(PendingChanges& changes) {
|
||||||
_resetItems.insert(_resetItems.end(), changes._resetItems.begin(), changes._resetItems.end());
|
_resetItems.insert(_resetItems.end(), changes._resetItems.begin(), changes._resetItems.end());
|
||||||
_resetPayloads.insert(_resetPayloads.end(), changes._resetPayloads.begin(), changes._resetPayloads.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());
|
_removedItems.insert(_removedItems.end(), changes._removedItems.begin(), changes._removedItems.end());
|
||||||
_updatedItems.insert(_updatedItems.end(), changes._updatedItems.begin(), changes._updatedItems.end());
|
_updatedItems.insert(_updatedItems.end(), changes._updatedItems.begin(), changes._updatedItems.end());
|
||||||
_updateFunctors.insert(_updateFunctors.end(), changes._updateFunctors.begin(), changes._updateFunctors.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)
|
_masterSpatialTree(origin, size)
|
||||||
{
|
{
|
||||||
_items.push_back(Item()); // add the itemID #0 to nothing
|
_items.push_back(Item()); // add the itemID #0 to nothing
|
||||||
_masterBucketMap.allocateStandardOpaqueTranparentBuckets();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemID Scene::allocateID() {
|
ItemID Scene::allocateID() {
|
||||||
|
@ -133,7 +81,6 @@ void Scene::processPendingChangesQueue() {
|
||||||
// capture anything coming from the pendingChanges
|
// capture anything coming from the pendingChanges
|
||||||
resetItems(consolidatedPendingChanges._resetItems, consolidatedPendingChanges._resetPayloads);
|
resetItems(consolidatedPendingChanges._resetItems, consolidatedPendingChanges._resetPayloads);
|
||||||
updateItems(consolidatedPendingChanges._updatedItems, consolidatedPendingChanges._updateFunctors);
|
updateItems(consolidatedPendingChanges._updatedItems, consolidatedPendingChanges._updateFunctors);
|
||||||
resortItems(consolidatedPendingChanges._resortItems, consolidatedPendingChanges._resortOldKeys, consolidatedPendingChanges._resortNewKeys);
|
|
||||||
removeItems(consolidatedPendingChanges._removedItems);
|
removeItems(consolidatedPendingChanges._removedItems);
|
||||||
|
|
||||||
// ready to go back to rendering activities
|
// ready to go back to rendering activities
|
||||||
|
@ -141,7 +88,6 @@ void Scene::processPendingChangesQueue() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) {
|
void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) {
|
||||||
|
|
||||||
auto resetPayload = payloads.begin();
|
auto resetPayload = payloads.begin();
|
||||||
for (auto resetID : ids) {
|
for (auto resetID : ids) {
|
||||||
// Access the true item
|
// Access the true item
|
||||||
|
@ -153,28 +99,18 @@ void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) {
|
||||||
item.resetPayload(*resetPayload);
|
item.resetPayload(*resetPayload);
|
||||||
auto newKey = item.getKey();
|
auto newKey = item.getKey();
|
||||||
|
|
||||||
|
// Update the item's container
|
||||||
// Reset the item in the Bucket map
|
assert((oldKey.isSpatial() == newKey.isSpatial()) || oldKey._flags.none());
|
||||||
_masterBucketMap.reset(resetID, oldKey, newKey);
|
if (newKey.isSpatial()) {
|
||||||
|
auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), resetID, newKey);
|
||||||
// Reset the item in the spatial tree
|
item.resetCell(newCell, newKey.isSmall());
|
||||||
auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), resetID, newKey);
|
}
|
||||||
item.resetCell(newCell, newKey.isSmall());
|
|
||||||
|
|
||||||
// next loop
|
// next loop
|
||||||
resetPayload++;
|
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) {
|
void Scene::removeItems(const ItemIDs& ids) {
|
||||||
for (auto removedID :ids) {
|
for (auto removedID :ids) {
|
||||||
// Access the true item
|
// Access the true item
|
||||||
|
@ -182,11 +118,12 @@ void Scene::removeItems(const ItemIDs& ids) {
|
||||||
auto oldCell = item.getCell();
|
auto oldCell = item.getCell();
|
||||||
auto oldKey = item.getKey();
|
auto oldKey = item.getKey();
|
||||||
|
|
||||||
// Remove from Bucket map
|
// Remove the item
|
||||||
_masterBucketMap.erase(removedID, item.getKey());
|
if (oldKey.isSpatial()) {
|
||||||
|
_masterSpatialTree.removeItem(oldCell, oldKey, removedID);
|
||||||
// Remove from spatial tree
|
} else {
|
||||||
_masterSpatialTree.removeItem(oldCell, oldKey, removedID);
|
_masterNonspatialSet.erase(removedID);
|
||||||
|
}
|
||||||
|
|
||||||
// Kill it
|
// Kill it
|
||||||
item.kill();
|
item.kill();
|
||||||
|
@ -202,14 +139,27 @@ void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) {
|
||||||
auto oldCell = item.getCell();
|
auto oldCell = item.getCell();
|
||||||
auto oldKey = item.getKey();
|
auto oldKey = item.getKey();
|
||||||
|
|
||||||
// Update it
|
// Update the item
|
||||||
_items[updateID].update((*updateFunctor));
|
item.update((*updateFunctor));
|
||||||
|
|
||||||
auto newKey = item.getKey();
|
auto newKey = item.getKey();
|
||||||
|
|
||||||
// Update the citem in the spatial tree if needed
|
// Update the item's container
|
||||||
auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey);
|
if (oldKey.isSpatial() == newKey.isSpatial()) {
|
||||||
item.resetCell(newCell, newKey.isSmall());
|
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
|
// next loop
|
||||||
updateFunctor++;
|
updateFunctor++;
|
||||||
|
|
|
@ -17,21 +17,6 @@
|
||||||
|
|
||||||
namespace render {
|
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 Engine;
|
||||||
|
|
||||||
class PendingChanges {
|
class PendingChanges {
|
||||||
|
@ -40,7 +25,6 @@ public:
|
||||||
~PendingChanges() {}
|
~PendingChanges() {}
|
||||||
|
|
||||||
void resetItem(ItemID id, const PayloadPointer& payload);
|
void resetItem(ItemID id, const PayloadPointer& payload);
|
||||||
void resortItem(ItemID id, ItemKey oldKey, ItemKey newKey);
|
|
||||||
void removeItem(ItemID id);
|
void removeItem(ItemID id);
|
||||||
|
|
||||||
template <class T> void updateItem(ItemID id, std::function<void(T&)> func) {
|
template <class T> void updateItem(ItemID id, std::function<void(T&)> func) {
|
||||||
|
@ -53,9 +37,6 @@ public:
|
||||||
|
|
||||||
ItemIDs _resetItems;
|
ItemIDs _resetItems;
|
||||||
Payloads _resetPayloads;
|
Payloads _resetPayloads;
|
||||||
ItemIDs _resortItems;
|
|
||||||
ItemKeys _resortOldKeys;
|
|
||||||
ItemKeys _resortNewKeys;
|
|
||||||
ItemIDs _removedItems;
|
ItemIDs _removedItems;
|
||||||
ItemIDs _updatedItems;
|
ItemIDs _updatedItems;
|
||||||
UpdateFunctors _updateFunctors;
|
UpdateFunctors _updateFunctors;
|
||||||
|
@ -75,27 +56,27 @@ public:
|
||||||
Scene(glm::vec3 origin, float size);
|
Scene(glm::vec3 origin, float size);
|
||||||
~Scene() {}
|
~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();
|
ItemID allocateID();
|
||||||
|
|
||||||
/// Enqueue change batch to the scene
|
// Enqueue change batch to the scene
|
||||||
void enqueuePendingChanges(const PendingChanges& pendingChanges);
|
void enqueuePendingChanges(const PendingChanges& pendingChanges);
|
||||||
|
|
||||||
// Process the penging changes equeued
|
// Process the penging changes equeued
|
||||||
void processPendingChangesQueue();
|
void processPendingChangesQueue();
|
||||||
|
|
||||||
/// Access a particular item form its ID
|
// 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
|
// 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]; }
|
const Item& getItem(const ItemID& id) const { return _items[id]; }
|
||||||
|
|
||||||
size_t getNumItems() const { return _items.size(); }
|
size_t getNumItems() const { return _items.size(); }
|
||||||
|
|
||||||
/// Access the main bucketmap of items
|
// Access the spatialized items
|
||||||
const ItemBucketMap& getMasterBucket() const { return _masterBucketMap; }
|
|
||||||
|
|
||||||
/// Access the item spatial tree
|
|
||||||
const ItemSpatialTree& getSpatialTree() const { return _masterSpatialTree; }
|
const ItemSpatialTree& getSpatialTree() const { return _masterSpatialTree; }
|
||||||
|
|
||||||
|
// Access non-spatialized items (overlays, backgrounds)
|
||||||
|
const ItemIDSet& getNonspatialSet() const { return _masterNonspatialSet; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Thread safe elements that can be accessed from anywhere
|
// Thread safe elements that can be accessed from anywhere
|
||||||
std::atomic<unsigned int> _IDAllocator{ 1 }; // first valid itemID will be One
|
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
|
// database of items is protected for editing by a mutex
|
||||||
std::mutex _itemsMutex;
|
std::mutex _itemsMutex;
|
||||||
Item::Vector _items;
|
Item::Vector _items;
|
||||||
ItemBucketMap _masterBucketMap;
|
|
||||||
ItemSpatialTree _masterSpatialTree;
|
ItemSpatialTree _masterSpatialTree;
|
||||||
|
ItemIDSet _masterNonspatialSet;
|
||||||
|
|
||||||
void resetItems(const ItemIDs& ids, Payloads& payloads);
|
void resetItems(const ItemIDs& ids, Payloads& payloads);
|
||||||
void resortItems(const ItemIDs& ids, ItemKeys& oldKeys, ItemKeys& newKeys);
|
|
||||||
void removeItems(const ItemIDs& ids);
|
void removeItems(const ItemIDs& ids);
|
||||||
void updateItems(const ItemIDs& ids, UpdateFunctors& functors);
|
void updateItems(const ItemIDs& ids, UpdateFunctors& functors);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue