From 27dd82b517c31bb3b65b6e2d07791688e4017a9e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 21 Feb 2017 13:34:07 -0800 Subject: [PATCH 1/2] fix sorting algorithm for avatar render updates --- interface/src/avatar/AvatarManager.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index c3fc974365..80b9c95cee 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -154,8 +154,7 @@ public: AvatarPriority(AvatarSharedPointer a, float p) : avatar(a), priority(p) {} AvatarSharedPointer avatar; float priority; - // NOTE: we invert the less-than operator to sort high priorities to front - bool operator<(const AvatarPriority& other) const { return priority > other.priority; } + bool operator<(const AvatarPriority& other) const { return priority < other.priority; } }; void AvatarManager::updateOtherAvatars(float deltaTime) { @@ -206,9 +205,8 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { float radius = avatar->getBoundingRadius(); const glm::vec3& forward = cameraView.getDirection(); float apparentSize = radius / distance; - float cosineAngle = glm::length(offset - glm::dot(offset, forward) * forward) / distance; - const float TIME_PENALTY = 0.080f; // seconds - float age = (float)(startTime - avatar->getLastRenderUpdateTime()) / (float)(USECS_PER_SECOND) - TIME_PENALTY; + float cosineAngle = glm::length(glm::dot(offset, forward) * forward) / distance; + float age = (float)(startTime - avatar->getLastRenderUpdateTime()) / (float)(USECS_PER_SECOND); // NOTE: we are adding values of different units to get a single measure of "priority". // Thus we multiply each component by a conversion "weight" that scales its units // relative to the others. These weights are pure magic tuning and are hard coded in the From dd447689e0cefb603814fc019e0dd87e213fcb88 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 21 Feb 2017 15:09:44 -0800 Subject: [PATCH 2/2] expose avatar sort coefficients for fine tuning --- interface/src/avatar/AvatarManager.cpp | 39 ++++++++++++++++++++++---- interface/src/avatar/AvatarManager.h | 9 ++++++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 80b9c95cee..d2c2ea36a3 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -204,14 +204,17 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { float distance = glm::length(offset) + 0.001f; // add 1mm to avoid divide by zero float radius = avatar->getBoundingRadius(); const glm::vec3& forward = cameraView.getDirection(); - float apparentSize = radius / distance; + float apparentSize = 2.0f * radius / distance; float cosineAngle = glm::length(glm::dot(offset, forward) * forward) / distance; float age = (float)(startTime - avatar->getLastRenderUpdateTime()) / (float)(USECS_PER_SECOND); + // NOTE: we are adding values of different units to get a single measure of "priority". - // Thus we multiply each component by a conversion "weight" that scales its units - // relative to the others. These weights are pure magic tuning and are hard coded in the - // relation below: (hint: unitary weights are not explicityly shown) - float priority = apparentSize + 0.25f * cosineAngle + age; + // Thus we multiply each component by a conversion "weight" that scales its units relative to the others. + // These weights are pure magic tuning and should be hard coded in the relation below, + // but are currently exposed for anyone who would like to explore fine tuning: + float priority = _avatarSortCoefficientSize * apparentSize + + _avatarSortCoefficientCenter * cosineAngle + + _avatarSortCoefficientAge * age; // decrement priority of avatars outside keyhole if (distance > cameraView.getCenterRadius()) { @@ -591,3 +594,29 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay& return result; } + +// HACK +float AvatarManager::getAvatarSortCoefficient(const QString& name) { + if (name == "size") { + return _avatarSortCoefficientSize; + } else if (name == "center") { + return _avatarSortCoefficientCenter; + } else if (name == "age") { + return _avatarSortCoefficientAge; + } + return 0.0f; +} + +// HACK +void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptValue& value) { + if (value.isNumber()) { + float numericalValue = (float)value.toNumber(); + if (name == "size") { + _avatarSortCoefficientSize = numericalValue; + } else if (name == "center") { + _avatarSortCoefficientCenter = numericalValue; + } else if (name == "age") { + _avatarSortCoefficientAge = numericalValue; + } + } +} diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 4d503842b9..b4e1a700cb 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -81,6 +81,10 @@ public: const QScriptValue& avatarIdsToInclude = QScriptValue(), const QScriptValue& avatarIdsToDiscard = QScriptValue()); + // TODO: remove this HACK once we settle on optimal default sort coefficients + Q_INVOKABLE float getAvatarSortCoefficient(const QString& name); + Q_INVOKABLE void setAvatarSortCoefficient(const QString& name, const QScriptValue& value); + float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); } public slots: @@ -120,6 +124,11 @@ private: int _partiallySimulatedAvatars { 0 }; float _avatarSimulationTime { 0.0f }; + // TODO: remove this HACK once we settle on optimal sort coefficients + // These coefficients exposed for fine tuning the sort priority for transfering new _jointData to the render pipeline. + float _avatarSortCoefficientSize { 0.5f }; + float _avatarSortCoefficientCenter { 0.25 }; + float _avatarSortCoefficientAge { 1.0f }; }; Q_DECLARE_METATYPE(AvatarManager::LocalLight)