mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 19:01:09 +02:00
Multiview support for priority queue
This commit is contained in:
parent
d47ddbd6e4
commit
21213e81f4
8 changed files with 71 additions and 23 deletions
|
@ -223,7 +223,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
|
|
||||||
// prepare to sort
|
// prepare to sort
|
||||||
ViewFrustum cameraView = nodeData->getViewFrustum();
|
ViewFrustum cameraView = nodeData->getViewFrustum();
|
||||||
PrioritySortUtil::PriorityQueue<SortableAvatar> sortedAvatars(cameraView,
|
PrioritySortUtil::PriorityQueue<SortableAvatar> sortedAvatars({cameraView},
|
||||||
AvatarData::_avatarSortCoefficientSize,
|
AvatarData::_avatarSortCoefficientSize,
|
||||||
AvatarData::_avatarSortCoefficientCenter,
|
AvatarData::_avatarSortCoefficientCenter,
|
||||||
AvatarData::_avatarSortCoefficientAge);
|
AvatarData::_avatarSortCoefficientAge);
|
||||||
|
|
|
@ -175,13 +175,13 @@ public:
|
||||||
Camera& getCamera() { return _myCamera; }
|
Camera& getCamera() { return _myCamera; }
|
||||||
const Camera& getCamera() const { return _myCamera; }
|
const Camera& getCamera() const { return _myCamera; }
|
||||||
// Represents the current view frustum of the avatar.
|
// Represents the current view frustum of the avatar.
|
||||||
void copyViewFrustum(ViewFrustum& viewOut) const;
|
void copyViewFrustum(ViewFrustum& viewOut) const override;
|
||||||
|
void copySecondaryViewFrustum(ViewFrustum& viewOut) const override;
|
||||||
|
bool hasSecondaryViewFrustum() const override { return _hasSecondaryViewFrustum; }
|
||||||
// Represents the view frustum of the current rendering pass,
|
// Represents the view frustum of the current rendering pass,
|
||||||
// which might be different from the viewFrustum, i.e. shadowmap
|
// which might be different from the viewFrustum, i.e. shadowmap
|
||||||
// passes, mirror window passes, etc
|
// passes, mirror window passes, etc
|
||||||
void copyDisplayViewFrustum(ViewFrustum& viewOut) const;
|
void copyDisplayViewFrustum(ViewFrustum& viewOut) const;
|
||||||
void copySecondaryViewFrustum(ViewFrustum& viewOut) const;
|
|
||||||
bool hasSecondaryViewFrustum() const { return _hasSecondaryViewFrustum; }
|
|
||||||
|
|
||||||
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
|
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
|
||||||
QSharedPointer<EntityTreeRenderer> getEntities() const { return DependencyManager::get<EntityTreeRenderer>(); }
|
QSharedPointer<EntityTreeRenderer> getEntities() const { return DependencyManager::get<EntityTreeRenderer>(); }
|
||||||
|
|
|
@ -155,9 +155,19 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
AvatarSharedPointer _avatar;
|
AvatarSharedPointer _avatar;
|
||||||
};
|
};
|
||||||
|
|
||||||
ViewFrustum cameraView;
|
|
||||||
qApp->copyDisplayViewFrustum(cameraView);
|
std::vector<ViewFrustum> views;
|
||||||
PrioritySortUtil::PriorityQueue<SortableAvatar> sortedAvatars(cameraView,
|
|
||||||
|
ViewFrustum view;
|
||||||
|
qApp->copyCurrentViewFrustum(view);
|
||||||
|
views.push_back(view);
|
||||||
|
|
||||||
|
if (qApp->hasSecondaryViewFrustum()) {
|
||||||
|
qApp->copySecondaryViewFrustum(view);
|
||||||
|
views.push_back(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrioritySortUtil::PriorityQueue<SortableAvatar> sortedAvatars(views,
|
||||||
AvatarData::_avatarSortCoefficientSize,
|
AvatarData::_avatarSortCoefficientSize,
|
||||||
AvatarData::_avatarSortCoefficientCenter,
|
AvatarData::_avatarSortCoefficientCenter,
|
||||||
AvatarData::_avatarSortCoefficientAge);
|
AvatarData::_avatarSortCoefficientAge);
|
||||||
|
|
|
@ -296,7 +296,8 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, const ViewFrustum& view, render::Transaction& transaction) {
|
void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, const std::vector<ViewFrustum>& views,
|
||||||
|
render::Transaction& transaction) {
|
||||||
PROFILE_RANGE_EX(simulation_physics, "ChangeInScene", 0xffff00ff, (uint64_t)_changedEntities.size());
|
PROFILE_RANGE_EX(simulation_physics, "ChangeInScene", 0xffff00ff, (uint64_t)_changedEntities.size());
|
||||||
PerformanceTimer pt("change");
|
PerformanceTimer pt("change");
|
||||||
std::unordered_set<EntityItemID> changedEntities;
|
std::unordered_set<EntityItemID> changedEntities;
|
||||||
|
@ -357,7 +358,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
|
||||||
|
|
||||||
// prioritize and sort the renderables
|
// prioritize and sort the renderables
|
||||||
uint64_t sortStart = usecTimestampNow();
|
uint64_t sortStart = usecTimestampNow();
|
||||||
PrioritySortUtil::PriorityQueue<SortableRenderer> sortedRenderables(view);
|
PrioritySortUtil::PriorityQueue<SortableRenderer> sortedRenderables(views);
|
||||||
{
|
{
|
||||||
PROFILE_RANGE_EX(simulation_physics, "SortRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size());
|
PROFILE_RANGE_EX(simulation_physics, "SortRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size());
|
||||||
std::unordered_map<EntityItemID, EntityRendererPointer>::iterator itr = _renderablesToUpdate.begin();
|
std::unordered_map<EntityItemID, EntityRendererPointer>::iterator itr = _renderablesToUpdate.begin();
|
||||||
|
@ -415,9 +416,20 @@ void EntityTreeRenderer::update(bool simulate) {
|
||||||
if (scene) {
|
if (scene) {
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
addPendingEntities(scene, transaction);
|
addPendingEntities(scene, transaction);
|
||||||
|
|
||||||
|
std::vector<ViewFrustum> views;
|
||||||
|
|
||||||
ViewFrustum view;
|
ViewFrustum view;
|
||||||
_viewState->copyCurrentViewFrustum(view);
|
_viewState->copyViewFrustum(view);
|
||||||
updateChangedEntities(scene, view, transaction);
|
views.push_back(view);
|
||||||
|
|
||||||
|
if (_viewState->hasSecondaryViewFrustum()) {
|
||||||
|
_viewState->copySecondaryViewFrustum(view);
|
||||||
|
views.push_back(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
updateChangedEntities(scene, views, transaction);
|
||||||
scene->enqueueTransaction(transaction);
|
scene->enqueueTransaction(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,8 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction);
|
void addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction);
|
||||||
void updateChangedEntities(const render::ScenePointer& scene, const ViewFrustum& view, render::Transaction& transaction);
|
void updateChangedEntities(const render::ScenePointer& scene, const std::vector<ViewFrustum>& views,
|
||||||
|
render::Transaction& transaction);
|
||||||
EntityRendererPointer renderableForEntity(const EntityItemPointer& entity) const { return renderableForEntityId(entity->getID()); }
|
EntityRendererPointer renderableForEntity(const EntityItemPointer& entity) const { return renderableForEntityId(entity->getID()); }
|
||||||
render::ItemID renderableIdForEntity(const EntityItemPointer& entity) const { return renderableIdForEntityId(entity->getID()); }
|
render::ItemID renderableIdForEntity(const EntityItemPointer& entity) const { return renderableIdForEntityId(entity->getID()); }
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,10 @@ public:
|
||||||
/// copies the current view frustum for rendering the view state
|
/// copies the current view frustum for rendering the view state
|
||||||
virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const = 0;
|
virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const = 0;
|
||||||
|
|
||||||
|
virtual void copyViewFrustum(ViewFrustum& viewOut) const = 0;
|
||||||
|
virtual void copySecondaryViewFrustum(ViewFrustum& viewOut) const = 0;
|
||||||
|
virtual bool hasSecondaryViewFrustum() const = 0;
|
||||||
|
|
||||||
virtual QThread* getMainThread() = 0;
|
virtual QThread* getMainThread() = 0;
|
||||||
|
|
||||||
virtual PickRay computePickRay(float x, float y) const = 0;
|
virtual PickRay computePickRay(float x, float y) const = 0;
|
||||||
|
|
|
@ -83,15 +83,15 @@ namespace PrioritySortUtil {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class PriorityQueue {
|
class PriorityQueue {
|
||||||
public:
|
public:
|
||||||
|
using Views = std::vector<ViewFrustum>;
|
||||||
|
|
||||||
PriorityQueue() = delete;
|
PriorityQueue() = delete;
|
||||||
|
PriorityQueue(const Views& views) : _views(views) { }
|
||||||
PriorityQueue(const ViewFrustum& view) : _view(view) { }
|
PriorityQueue(const Views& views, float angularWeight, float centerWeight, float ageWeight)
|
||||||
|
: _views(views), _angularWeight(angularWeight), _centerWeight(centerWeight), _ageWeight(ageWeight)
|
||||||
PriorityQueue(const ViewFrustum& view, float angularWeight, float centerWeight, float ageWeight)
|
|
||||||
: _view(view), _angularWeight(angularWeight), _centerWeight(centerWeight), _ageWeight(ageWeight)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void setView(const ViewFrustum& view) { _view = view; }
|
void setViews(const Views& views) { _views = views; }
|
||||||
|
|
||||||
void setWeights(float angularWeight, float centerWeight, float ageWeight) {
|
void setWeights(float angularWeight, float centerWeight, float ageWeight) {
|
||||||
_angularWeight = angularWeight;
|
_angularWeight = angularWeight;
|
||||||
|
@ -109,7 +109,18 @@ namespace PrioritySortUtil {
|
||||||
bool empty() const { return _queue.empty(); }
|
bool empty() const { return _queue.empty(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
float computePriority(const T& thing) const {
|
float computePriority(const T& thing) const {
|
||||||
|
float priority = std::numeric_limits<float>::min();
|
||||||
|
|
||||||
|
for (const auto& view : _views) {
|
||||||
|
priority = std::max(priority, computePriority(view, thing));
|
||||||
|
}
|
||||||
|
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
float computePriority(const ViewFrustum& view, const T& thing) const {
|
||||||
// priority = weighted linear combination of multiple values:
|
// priority = weighted linear combination of multiple values:
|
||||||
// (a) angular size
|
// (a) angular size
|
||||||
// (b) proximity to center of view
|
// (b) proximity to center of view
|
||||||
|
@ -117,11 +128,11 @@ namespace PrioritySortUtil {
|
||||||
// where the relative "weights" are tuned to scale the contributing values into units of "priority".
|
// where the relative "weights" are tuned to scale the contributing values into units of "priority".
|
||||||
|
|
||||||
glm::vec3 position = thing.getPosition();
|
glm::vec3 position = thing.getPosition();
|
||||||
glm::vec3 offset = position - _view.getPosition();
|
glm::vec3 offset = position - view.getPosition();
|
||||||
float distance = glm::length(offset) + 0.001f; // add 1mm to avoid divide by zero
|
float distance = glm::length(offset) + 0.001f; // add 1mm to avoid divide by zero
|
||||||
const float MIN_RADIUS = 0.1f; // WORKAROUND for zero size objects (we still want them to sort by distance)
|
const float MIN_RADIUS = 0.1f; // WORKAROUND for zero size objects (we still want them to sort by distance)
|
||||||
float radius = glm::min(thing.getRadius(), MIN_RADIUS);
|
float radius = glm::min(thing.getRadius(), MIN_RADIUS);
|
||||||
float cosineAngle = (glm::dot(offset, _view.getDirection()) / distance);
|
float cosineAngle = (glm::dot(offset, view.getDirection()) / distance);
|
||||||
float age = (float)(usecTimestampNow() - thing.getTimestamp());
|
float age = (float)(usecTimestampNow() - thing.getTimestamp());
|
||||||
|
|
||||||
// we modulatate "age" drift rate by the cosineAngle term to make periphrial objects sort forward
|
// we modulatate "age" drift rate by the cosineAngle term to make periphrial objects sort forward
|
||||||
|
@ -134,8 +145,8 @@ namespace PrioritySortUtil {
|
||||||
+ _ageWeight * cosineAngleFactor * age;
|
+ _ageWeight * cosineAngleFactor * age;
|
||||||
|
|
||||||
// decrement priority of things outside keyhole
|
// decrement priority of things outside keyhole
|
||||||
if (distance - radius > _view.getCenterRadius()) {
|
if (distance - radius > view.getCenterRadius()) {
|
||||||
if (!_view.sphereIntersectsFrustum(position, radius)) {
|
if (!view.sphereIntersectsFrustum(position, radius)) {
|
||||||
constexpr float OUT_OF_VIEW_PENALTY = -10.0f;
|
constexpr float OUT_OF_VIEW_PENALTY = -10.0f;
|
||||||
priority += OUT_OF_VIEW_PENALTY;
|
priority += OUT_OF_VIEW_PENALTY;
|
||||||
}
|
}
|
||||||
|
@ -143,7 +154,7 @@ namespace PrioritySortUtil {
|
||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewFrustum _view;
|
Views _views;
|
||||||
std::priority_queue<T> _queue;
|
std::priority_queue<T> _queue;
|
||||||
float _angularWeight { DEFAULT_ANGULAR_COEF };
|
float _angularWeight { DEFAULT_ANGULAR_COEF };
|
||||||
float _centerWeight { DEFAULT_CENTER_COEF };
|
float _centerWeight { DEFAULT_CENTER_COEF };
|
||||||
|
|
|
@ -441,6 +441,16 @@ protected:
|
||||||
viewOut = _viewFrustum;
|
viewOut = _viewFrustum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copyViewFrustum(ViewFrustum& viewOut) const override {
|
||||||
|
viewOut = _viewFrustum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copySecondaryViewFrustum(ViewFrustum& viewOut) const override {}
|
||||||
|
|
||||||
|
bool hasSecondaryViewFrustum() const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QThread* getMainThread() override {
|
QThread* getMainThread() override {
|
||||||
return QThread::currentThread();
|
return QThread::currentThread();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue