mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 21:56:14 +02:00
188 lines
6.1 KiB
C++
188 lines
6.1 KiB
C++
//
|
|
// Scene.cpp
|
|
// render/src/render
|
|
//
|
|
// Created by Sam Gateau on 1/11/15.
|
|
// Copyright 2014 High Fidelity, Inc.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
#include "Scene.h"
|
|
|
|
#include <numeric>
|
|
#include "gpu/Batch.h"
|
|
|
|
using namespace render;
|
|
|
|
void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) {
|
|
_resetItems.push_back(id);
|
|
_resetPayloads.push_back(payload);
|
|
}
|
|
|
|
void PendingChanges::removeItem(ItemID id) {
|
|
_removedItems.push_back(id);
|
|
}
|
|
|
|
void PendingChanges::updateItem(ItemID id, const UpdateFunctorPointer& functor) {
|
|
_updatedItems.push_back(id);
|
|
_updateFunctors.push_back(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());
|
|
_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());
|
|
}
|
|
|
|
Scene::Scene(glm::vec3 origin, float size) :
|
|
_masterSpatialTree(origin, size)
|
|
{
|
|
_items.push_back(Item()); // add the itemID #0 to nothing
|
|
}
|
|
|
|
ItemID Scene::allocateID() {
|
|
// Just increment and return the proevious value initialized at 0
|
|
return _IDAllocator.fetch_add(1);
|
|
}
|
|
|
|
bool Scene::isAllocatedID(const ItemID& id) {
|
|
return Item::isValidID(id) && (id < _numAllocatedItems.load());
|
|
}
|
|
|
|
/// Enqueue change batch to the scene
|
|
void Scene::enqueuePendingChanges(const PendingChanges& pendingChanges) {
|
|
_changeQueueMutex.lock();
|
|
_changeQueue.push(pendingChanges);
|
|
_changeQueueMutex.unlock();
|
|
}
|
|
|
|
void consolidateChangeQueue(PendingChangesQueue& queue, PendingChanges& singleBatch) {
|
|
while (!queue.empty()) {
|
|
auto pendingChanges = queue.front();
|
|
singleBatch.merge(pendingChanges);
|
|
queue.pop();
|
|
};
|
|
}
|
|
|
|
void Scene::processPendingChangesQueue() {
|
|
PROFILE_RANGE(__FUNCTION__);
|
|
_changeQueueMutex.lock();
|
|
PendingChanges consolidatedPendingChanges;
|
|
consolidateChangeQueue(_changeQueue, consolidatedPendingChanges);
|
|
_changeQueueMutex.unlock();
|
|
|
|
_itemsMutex.lock();
|
|
// Here we should be able to check the value of last ItemID allocated
|
|
// and allocate new items accordingly
|
|
ItemID maxID = _IDAllocator.load();
|
|
if (maxID > _items.size()) {
|
|
_items.resize(maxID + 100); // allocate the maxId and more
|
|
}
|
|
// Now we know for sure that we have enough items in the array to
|
|
// capture anything coming from the pendingChanges
|
|
|
|
// resets and potential NEW items
|
|
resetItems(consolidatedPendingChanges._resetItems, consolidatedPendingChanges._resetPayloads);
|
|
|
|
// Update the numItemsAtomic counter AFTER the reset changes went through
|
|
_numAllocatedItems.exchange(maxID);
|
|
|
|
// updates
|
|
updateItems(consolidatedPendingChanges._updatedItems, consolidatedPendingChanges._updateFunctors);
|
|
|
|
// removes
|
|
removeItems(consolidatedPendingChanges._removedItems);
|
|
|
|
// Update the numItemsAtomic counter AFTER the pending changes went through
|
|
_numAllocatedItems.exchange(maxID);
|
|
|
|
// ready to go back to rendering activities
|
|
_itemsMutex.unlock();
|
|
}
|
|
|
|
void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) {
|
|
auto resetPayload = payloads.begin();
|
|
for (auto resetID : ids) {
|
|
// Access the true item
|
|
auto& item = _items[resetID];
|
|
auto oldKey = item.getKey();
|
|
auto oldCell = item.getCell();
|
|
|
|
// Reset the item with a new payload
|
|
item.resetPayload(*resetPayload);
|
|
auto newKey = item.getKey();
|
|
|
|
// 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());
|
|
} else {
|
|
_masterNonspatialSet.insert(resetID);
|
|
}
|
|
|
|
// next loop
|
|
resetPayload++;
|
|
}
|
|
}
|
|
|
|
void Scene::removeItems(const ItemIDs& ids) {
|
|
for (auto removedID :ids) {
|
|
// Access the true item
|
|
auto& item = _items[removedID];
|
|
auto oldCell = item.getCell();
|
|
auto oldKey = item.getKey();
|
|
|
|
// Remove the item
|
|
if (oldKey.isSpatial()) {
|
|
_masterSpatialTree.removeItem(oldCell, oldKey, removedID);
|
|
} else {
|
|
_masterNonspatialSet.erase(removedID);
|
|
}
|
|
|
|
// Kill it
|
|
item.kill();
|
|
}
|
|
}
|
|
|
|
void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) {
|
|
|
|
auto updateFunctor = functors.begin();
|
|
for (auto updateID : ids) {
|
|
// Access the true item
|
|
auto& item = _items[updateID];
|
|
auto oldCell = item.getCell();
|
|
auto oldKey = item.getKey();
|
|
|
|
// Update the item
|
|
item.update((*updateFunctor));
|
|
auto newKey = item.getKey();
|
|
|
|
// 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);
|
|
item.resetCell();
|
|
|
|
_masterNonspatialSet.insert(updateID);
|
|
}
|
|
}
|
|
|
|
|
|
// next loop
|
|
updateFunctor++;
|
|
}
|
|
}
|