From 6f81dd53f2cdbc730fc84eae648f72bea3807d56 Mon Sep 17 00:00:00 2001 From: Gerard Maguire Date: Tue, 8 Aug 2017 05:08:20 +0100 Subject: [PATCH 001/183] Fixed avatar rotation upon teleportation using Pal Added "VisitUserFromPAL" to LookupTrigger enum and bool "shouldMatchOrientation" to goToUser() --- interface/resources/qml/hifi/NameCard.qml | 4 +++- interface/resources/qml/hifi/Pal.qml | 2 +- libraries/networking/src/AddressManager.cpp | 18 ++++++++++++------ libraries/networking/src/AddressManager.h | 5 +++-- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 65517f5a73..937c67d8ba 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -433,7 +433,7 @@ Item { anchors.verticalCenter: nameCardRemoveConnectionImage.verticalCenter x: 240 onClicked: { - AddressManager.goToUser(thisNameCard.userName); + AddressManager.goToUser(thisNameCard.userName, false); UserActivityLogger.palAction("go_to_user", thisNameCard.userName); } } @@ -595,7 +595,9 @@ Item { // the avatar goes into fly mode rather than falling. However, that is not exposed to Javascript right now. // FIXME: it would be nice if this used the same teleport steps and smoothing as in the teleport.js script. // Note, however, that this script allows teleporting to a person in the air, while teleport.js is going to a grounded target. + // Position avatar 2 metres from the target in the direction that target avatar was facing. MyAvatar.position = Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.orientation, {x: 0, y: 0, z: -2})); + // Rotate avatar on Y axis to face target avatar. MyAvatar.orientation = Quat.multiply(avatar.orientation, {y: 1}); } } diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index c98cfba1ba..134fea5170 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -830,7 +830,7 @@ Rectangle { hoverEnabled: enabled enabled: connectionsNameCard.selected && pal.activeTab == "connectionsTab" onClicked: { - AddressManager.goToUser(model.userName); + AddressManager.goToUser(model.userName, false); UserActivityLogger.palAction("go_to_user", model.userName); } onEntered: connectionsLocationData.color = hifi.colors.blueHighlight; diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 99e1962387..588df71e41 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -665,6 +665,11 @@ bool AddressManager::handleViewpoint(const QString& viewpointString, bool should } } + if (trigger == LookupTrigger::VisitUserFromPAL) { + qCDebug(networking) << "trigger is VisitUserFromPAL -- applying Quat.cancelOutRollAndPitch"; + newOrientation = cancelOutRollAndPitch(newOrientation); + } + emit locationChangeRequired(newPosition, orientationChanged, newOrientation, shouldFace); } else { @@ -729,13 +734,14 @@ bool AddressManager::setDomainInfo(const QString& hostname, quint16 port, Lookup return hostChanged; } -void AddressManager::goToUser(const QString& username) { +void AddressManager::goToUser(const QString& username, bool shouldMatchOrientation) { QString formattedUsername = QUrl::toPercentEncoding(username); - // for history storage handling we remember how this lookup was trigged - for a username it's always user input + // for history storage handling we remember how this lookup was triggered - for a username it's always user input QVariantMap requestParams; - requestParams.insert(LOOKUP_TRIGGER_KEY, static_cast(LookupTrigger::UserInput)); - + requestParams.insert(LOOKUP_TRIGGER_KEY, static_cast( + shouldMatchOrientation ? LookupTrigger::UserInput : LookupTrigger::VisitUserFromPAL + )); // this is a username - pull the captured name and lookup that user's location DependencyManager::get()->sendRequest(GET_USER_LOCATION.arg(formattedUsername), AccountManagerAuth::Optional, @@ -841,8 +847,8 @@ void AddressManager::addCurrentAddressToHistory(LookupTrigger trigger) { // and do not but it into the back stack _forwardStack.push(currentAddress()); } else { - if (trigger == LookupTrigger::UserInput) { - // anyime the user has manually looked up an address we know we should clear the forward stack + if (trigger == LookupTrigger::UserInput || trigger == LookupTrigger::VisitUserFromPAL) { + // anyime the user has actively triggered an address we know we should clear the forward stack _forwardStack.clear(); emit goForwardPossible(false); diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 83eedfc82f..98b2048601 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -55,7 +55,8 @@ public: DomainPathResponse, Internal, AttemptedRefresh, - Suggestions + Suggestions, + VisitUserFromPAL }; bool isConnected(); @@ -95,7 +96,7 @@ public slots: void goToLocalSandbox(QString path = "", LookupTrigger trigger = LookupTrigger::StartupFromSettings) { handleUrl(SANDBOX_HIFI_ADDRESS + path, trigger); } void goToEntry(LookupTrigger trigger = LookupTrigger::StartupFromSettings) { handleUrl(DEFAULT_HIFI_ADDRESS, trigger); } - void goToUser(const QString& username); + void goToUser(const QString& username, bool shouldMatchOrientation = true); void refreshPreviousLookup(); From 356f055b53284ba22b0a7c0763452e9b89fee9ac Mon Sep 17 00:00:00 2001 From: Gerard Maguire Date: Tue, 8 Aug 2017 15:26:21 +0100 Subject: [PATCH 002/183] fixed missing bool --- interface/resources/qml/hifi/NameCard.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 937c67d8ba..78dff425c7 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -244,7 +244,7 @@ Item { enabled: selected && pal.activeTab == "nearbyTab" && thisNameCard.userName !== "" && isPresent; hoverEnabled: enabled onClicked: { - goToUserInDomain(thisNameCard.uuid); + goToUserInDomain(thisNameCard.uuid, false); UserActivityLogger.palAction("go_to_user_in_domain", thisNameCard.uuid); } onEntered: { From 47b37ac04ef315bdf2d2cadec595fadaf4db9d0a Mon Sep 17 00:00:00 2001 From: Gerard Maguire Date: Tue, 8 Aug 2017 15:35:14 +0100 Subject: [PATCH 003/183] Bool --- interface/resources/qml/hifi/NameCard.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 78dff425c7..7e93d2c397 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -339,7 +339,7 @@ Item { enabled: selected && pal.activeTab == "nearbyTab" && thisNameCard.userName !== "" && isPresent; hoverEnabled: enabled onClicked: { - goToUserInDomain(thisNameCard.uuid); + goToUserInDomain(thisNameCard.uuid, false); UserActivityLogger.palAction("go_to_user_in_domain", thisNameCard.uuid); } onEntered: { From b8fdb667457e8339b7ad240d88e80bd2b5425073 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 20 Sep 2017 14:20:43 -0700 Subject: [PATCH 004/183] added support for fbx formats --- interface/src/Application.cpp | 53 ++++++++++++++++++++++++++++------- interface/src/Application.h | 1 + 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bd870ff8bb..8491a8dc07 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -341,7 +341,8 @@ const QHash Application::_acceptedExtensi { JS_EXTENSION, &Application::askToLoadScript }, { FST_EXTENSION, &Application::askToSetAvatarUrl }, { JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent }, - { ZIP_EXTENSION, &Application::importFromZIP } + { ZIP_EXTENSION, &Application::importFromZIP }, + { FBX_EXTENSION, &Application::importFromFBX } }; class DeadlockWatchdogThread : public QThread { @@ -2893,6 +2894,18 @@ bool Application::importFromZIP(const QString& filePath) { return true; } +bool Application::importFromFBX(const QString& filePath) { + qDebug() << "An fbx file has been dropped in: " << filePath; + QUrl empty; + // handle Blocks download from Marketplace + if (filePath.contains("vr.google.com/downloads")) { + addAssetToWorldFromURL(filePath); + } else { + addAssetToWorld(filePath, "", false, false); + } + return true; +} + void Application::onPresent(quint32 frameCount) { postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority); if (_renderEventHandler && !isAboutToQuit()) { @@ -6412,7 +6425,11 @@ void Application::addAssetToWorldFromURL(QString url) { if (url.contains("vr.google.com/downloads")) { filename = url.section('/', -1); if (url.contains("noDownload")) { - filename.remove(".zip?noDownload=false"); + if (url.contains(".fbx")) { + filename.remove("?noDownload=false"); + } else { + filename.remove(".zip?noDownload=false"); + } } else { filename.remove(".zip"); } @@ -6439,7 +6456,7 @@ void Application::addAssetToWorldFromURLRequestFinished() { auto result = request->getResult(); QString filename; - bool isBlocks = false; + bool isBlocksOBJ = false; if (url.contains("filename")) { filename = url.section("filename=", 1, 1); // Filename is in "?filename=" parameter at end of URL. @@ -6447,11 +6464,15 @@ void Application::addAssetToWorldFromURLRequestFinished() { if (url.contains("vr.google.com/downloads")) { filename = url.section('/', -1); if (url.contains("noDownload")) { - filename.remove(".zip?noDownload=false"); + if (url.contains(".fbx")) { + filename.remove("?noDownload=false"); + } else { + filename.remove(".zip?noDownload=false"); + } } else { filename.remove(".zip"); } - isBlocks = true; + isBlocksOBJ = true; } if (result == ResourceRequest::Success) { @@ -6468,7 +6489,11 @@ void Application::addAssetToWorldFromURLRequestFinished() { tempFile.write(request->getData()); addAssetToWorldInfoClear(filename); // Remove message from list; next one added will have a different key. tempFile.close(); - qApp->getFileDownloadInterface()->runUnzip(downloadPath, url, true, false, isBlocks); + if (url.contains(".fbx")) { + addAssetToWorld(downloadPath, "", false, false); + } else { + qApp->getFileDownloadInterface()->runUnzip(downloadPath, url, true, false, isBlocksOBJ); + } } else { QString errorInfo = "Couldn't open temporary file for download"; qWarning(interfaceapp) << errorInfo; @@ -6498,7 +6523,7 @@ void Application::addAssetToWorldUnzipFailure(QString filePath) { addAssetToWorldError(filename, "Couldn't unzip file " + filename + "."); } -void Application::addAssetToWorld(QString filePath, QString zipFile, bool isZip, bool isBlocks) { +void Application::addAssetToWorld(QString filePath, QString zipFile, bool isZip, bool isBlocksOBJ) { // Automatically upload and add asset to world as an alternative manual process initiated by showAssetServerWidget(). QString mapping; QString path = filePath; @@ -6507,7 +6532,7 @@ void Application::addAssetToWorld(QString filePath, QString zipFile, bool isZip, QString assetFolder = zipFile.section("/", -1); assetFolder.remove(".zip"); mapping = "/" + assetFolder + "/" + filename; - } else if (isBlocks) { + } else if (isBlocksOBJ) { qCDebug(interfaceapp) << "Path to asset folder: " << zipFile; QString assetFolder = zipFile.section('/', -1); assetFolder.remove(".zip?noDownload=false"); @@ -6638,6 +6663,14 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { // Close progress message box. addAssetToWorldInfoDone(filenameFromPath(filePath)); } + + // Delete temporary directories created from downloads + if (filePath.contains(".fbx")) { + qCDebug(interfaceapp) << "gonna try to remove the temp dir: " << filePath; + QString tempPath = filePath.remove(filePath.section("/", -1)); + qCDebug(interfaceapp) << tempPath; + qCDebug(interfaceapp) << QDir(tempPath).removeRecursively(); + } } void Application::addAssetToWorldCheckModelSize() { @@ -6891,12 +6924,12 @@ void Application::onAssetToWorldMessageBoxClosed() { } -void Application::handleUnzip(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip, bool isBlocks) { +void Application::handleUnzip(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip, bool isBlocksOBJ) { if (autoAdd) { if (!unzipFile.isEmpty()) { for (int i = 0; i < unzipFile.length(); i++) { qCDebug(interfaceapp) << "Preparing file for asset server: " << unzipFile.at(i); - addAssetToWorld(unzipFile.at(i), zipFile, isZip, isBlocks); + addAssetToWorld(unzipFile.at(i), zipFile, isZip, isBlocksOBJ); } } else { addAssetToWorldUnzipFailure(zipFile); diff --git a/interface/src/Application.h b/interface/src/Application.h index 86e4f94917..c6643c38e6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -486,6 +486,7 @@ private: bool importJSONFromURL(const QString& urlString); bool importSVOFromURL(const QString& urlString); bool importFromZIP(const QString& filePath); + bool importFromFBX(const QString& filePath); bool nearbyEntitiesAreReadyForPhysics(); int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode); From 92550b749c3ef958cbc731db30645c8e71cb2f7b Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 20 Sep 2017 14:23:09 -0700 Subject: [PATCH 005/183] removed extraneous printouts --- interface/src/Application.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d7e7771a6d..95b13a1da7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6687,9 +6687,8 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { // Delete temporary directories created from downloads if (filePath.contains(".fbx")) { - qCDebug(interfaceapp) << "gonna try to remove the temp dir: " << filePath; QString tempPath = filePath.remove(filePath.section("/", -1)); - qCDebug(interfaceapp) << tempPath; + qCDebug(interfaceapp) << "Removing temporary path: " << tempPath; qCDebug(interfaceapp) << QDir(tempPath).removeRecursively(); } } From 1ac0a8224fe47dcddf945368023e6cd930d154f1 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 20 Sep 2017 14:23:53 -0700 Subject: [PATCH 006/183] removed extraneous printouts again --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 95b13a1da7..21e4a0ec53 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6689,7 +6689,7 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { if (filePath.contains(".fbx")) { QString tempPath = filePath.remove(filePath.section("/", -1)); qCDebug(interfaceapp) << "Removing temporary path: " << tempPath; - qCDebug(interfaceapp) << QDir(tempPath).removeRecursively(); + QDir(tempPath).removeRecursively(); } } From afb03b3d2d8ae66fa112f16d75aa7422828a9115 Mon Sep 17 00:00:00 2001 From: Gerard Maguire Date: Tue, 10 Oct 2017 16:19:31 +0100 Subject: [PATCH 007/183] Avatar pitch and roll cleared --- interface/resources/qml/hifi/NameCard.qml | 10 ++++++---- libraries/networking/src/AddressManager.cpp | 12 +++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 7e93d2c397..b122f71760 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -244,7 +244,7 @@ Item { enabled: selected && pal.activeTab == "nearbyTab" && thisNameCard.userName !== "" && isPresent; hoverEnabled: enabled onClicked: { - goToUserInDomain(thisNameCard.uuid, false); + goToUserInDomain(thisNameCard.uuid); UserActivityLogger.palAction("go_to_user_in_domain", thisNameCard.uuid); } onEntered: { @@ -339,7 +339,7 @@ Item { enabled: selected && pal.activeTab == "nearbyTab" && thisNameCard.userName !== "" && isPresent; hoverEnabled: enabled onClicked: { - goToUserInDomain(thisNameCard.uuid, false); + goToUserInDomain(thisNameCard.uuid); UserActivityLogger.palAction("go_to_user_in_domain", thisNameCard.uuid); } onEntered: { @@ -433,6 +433,7 @@ Item { anchors.verticalCenter: nameCardRemoveConnectionImage.verticalCenter x: 240 onClicked: { + console.log("Vist user button clicked."); // Remove after debugging. AddressManager.goToUser(thisNameCard.userName, false); UserActivityLogger.palAction("go_to_user", thisNameCard.userName); } @@ -597,7 +598,8 @@ Item { // Note, however, that this script allows teleporting to a person in the air, while teleport.js is going to a grounded target. // Position avatar 2 metres from the target in the direction that target avatar was facing. MyAvatar.position = Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.orientation, {x: 0, y: 0, z: -2})); - // Rotate avatar on Y axis to face target avatar. - MyAvatar.orientation = Quat.multiply(avatar.orientation, {y: 1}); + + // Rotate avatar on Y axis to face target avatar and cancel out any inherited roll and pitch. + MyAvatar.orientation = Quat.cancelOutRollAndPitch(Quat.multiply(avatar.orientation, {y: 1})); } } diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 4030e2101b..772f9df2e1 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -668,13 +668,11 @@ bool AddressManager::handleViewpoint(const QString& viewpointString, bool should qCDebug(networking) << "Orientation parsed from lookup string is invalid. Will not use for location change."; } } - - if (trigger == LookupTrigger::VisitUserFromPAL) { - qCDebug(networking) << "trigger is VisitUserFromPAL -- applying Quat.cancelOutRollAndPitch"; - newOrientation = cancelOutRollAndPitch(newOrientation); - } - - emit locationChangeRequired(newPosition, orientationChanged, newOrientation, shouldFace); + + emit locationChangeRequired(newPosition, orientationChanged, + LookupTrigger::VisitUserFromPAL ? cancelOutRollAndPitch(newOrientation): newOrientation, + shouldFace + ); } else { qCDebug(networking) << "Could not jump to position from lookup string because it has an invalid value."; From 18d723b6b43b62f57ddeaf362bcc95ebf1afa261 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 10 Oct 2017 16:17:39 -0700 Subject: [PATCH 008/183] div by zero fixes, detected by address sanitizer --- interface/src/LODManager.cpp | 1 + libraries/animation/src/Rig.cpp | 7 ++++++- .../avatars-renderer/src/avatars-renderer/Avatar.cpp | 3 ++- libraries/shared/src/MovingMinMaxAvg.h | 8 ++++++-- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index d3c8746e16..199f3ea2c6 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -54,6 +54,7 @@ void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float delta float renderTime = batchTime + OVERLAY_AND_SWAP_TIME_BUDGET; float maxTime = glm::max(renderTime, engineRunTime); const float BLEND_TIMESCALE = 0.3f; // sec + const float safeDeltaTime = (deltaTime == 0.0f) ? 0.001f : deltaTime; float blend = BLEND_TIMESCALE / deltaTimeSec; if (blend > 1.0f) { blend = 1.0f; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 0897c26a12..83d258fb08 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -38,7 +38,12 @@ static std::mutex rigRegistryMutex; static bool isEqual(const glm::vec3& u, const glm::vec3& v) { const float EPSILON = 0.0001f; - return glm::length(u - v) / glm::length(u) <= EPSILON; + float uLen = glm::length(u); + if (uLen == 0.0f) { + return glm::length(v) <= EPSILON; + } else { + return glm::length(u - v) / glm::length(u) <= EPSILON; + } } static bool isEqual(const glm::quat& p, const glm::quat& q) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 87d4a2d343..a52582ff45 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -446,7 +446,8 @@ void Avatar::applyPositionDelta(const glm::vec3& delta) { void Avatar::measureMotionDerivatives(float deltaTime) { PerformanceTimer perfTimer("derivatives"); // linear - float invDeltaTime = 1.0f / deltaTime; + const float safeDeltaTime = (deltaTime == 0.0f) ? 0.001f : deltaTime; + float invDeltaTime = 1.0f / safeDeltaTime; // Floating point error prevents us from computing velocity in a naive way // (e.g. vel = (pos - oldPos) / dt) so instead we use _positionOffsetAccumulator. glm::vec3 velocity = _positionDeltaAccumulator * invDeltaTime; diff --git a/libraries/shared/src/MovingMinMaxAvg.h b/libraries/shared/src/MovingMinMaxAvg.h index 580baf7317..782b0dc523 100644 --- a/libraries/shared/src/MovingMinMaxAvg.h +++ b/libraries/shared/src/MovingMinMaxAvg.h @@ -59,8 +59,12 @@ public: _max = other._max; } double totalSamples = _samples + other._samples; - _average = _average * ((double)_samples / totalSamples) - + other._average * ((double)other._samples / totalSamples); + if (totalSamples > 0) { + _average = _average * ((double)_samples / totalSamples) + + other._average * ((double)other._samples / totalSamples); + } else { + _average = 0.0f; + } _samples += other._samples; } From cbb0d27f684b4e0f3c091c6a9268c1e2309426f7 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 10 Oct 2017 16:20:52 -0700 Subject: [PATCH 009/183] div by zero fix --- interface/src/LODManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 199f3ea2c6..4bdb13545e 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -55,7 +55,7 @@ void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float delta float maxTime = glm::max(renderTime, engineRunTime); const float BLEND_TIMESCALE = 0.3f; // sec const float safeDeltaTime = (deltaTime == 0.0f) ? 0.001f : deltaTime; - float blend = BLEND_TIMESCALE / deltaTimeSec; + float blend = BLEND_TIMESCALE / safeDeltaTime; if (blend > 1.0f) { blend = 1.0f; } From fe57a209792e06952da19999e3aeb277a13d3822 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 10 Oct 2017 16:22:49 -0700 Subject: [PATCH 010/183] div by zero fix --- libraries/animation/src/Rig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 83d258fb08..bd19dcc0e8 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -42,7 +42,7 @@ static bool isEqual(const glm::vec3& u, const glm::vec3& v) { if (uLen == 0.0f) { return glm::length(v) <= EPSILON; } else { - return glm::length(u - v) / glm::length(u) <= EPSILON; + return (glm::length(u - v) / uLen) <= EPSILON; } } From cb01c5cada93ed0d4e02f250c7a9047efcc1d227 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 10 Oct 2017 16:30:11 -0700 Subject: [PATCH 011/183] compile fix --- interface/src/LODManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 4bdb13545e..8f01296e1c 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -54,7 +54,7 @@ void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float delta float renderTime = batchTime + OVERLAY_AND_SWAP_TIME_BUDGET; float maxTime = glm::max(renderTime, engineRunTime); const float BLEND_TIMESCALE = 0.3f; // sec - const float safeDeltaTime = (deltaTime == 0.0f) ? 0.001f : deltaTime; + const float safeDeltaTime = (deltaTimeSec == 0.0f) ? 0.001f : deltaTimeSec; float blend = BLEND_TIMESCALE / safeDeltaTime; if (blend > 1.0f) { blend = 1.0f; From 049e3d47b67802e99e0de9215374f08131873683 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 13 Oct 2017 10:23:42 +0200 Subject: [PATCH 012/183] Preparing for support of multiple concurrent outlines by adding mask id buffer --- libraries/gpu-gl/src/gpu/gl/GLShared.h | 1 + libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp | 7 ++ libraries/gpu/src/gpu/Format.cpp | 2 + libraries/gpu/src/gpu/Format.h | 2 + libraries/render-utils/src/OutlineEffect.cpp | 113 +++++++++++++----- libraries/render-utils/src/OutlineEffect.h | 29 +++-- 6 files changed, 110 insertions(+), 44 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLShared.h b/libraries/gpu-gl/src/gpu/gl/GLShared.h index 1b898e5c22..a1cf27afa6 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShared.h +++ b/libraries/gpu-gl/src/gpu/gl/GLShared.h @@ -110,6 +110,7 @@ static const GLenum ELEMENT_TYPE_TO_GL[gpu::NUM_TYPES] = { GL_SHORT, GL_UNSIGNED_SHORT, GL_BYTE, + GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }; diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp index 192a82dafc..27319e1696 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp @@ -212,6 +212,9 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { case gpu::NUINT8: result = GL_RGBA8; break; + case gpu::NUINT2: + result = GL_RGBA2; + break; case gpu::NINT8: result = GL_RGBA8_SNORM; break; @@ -660,6 +663,10 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E texel.format = GL_RGBA; texel.internalFormat = GL_RGBA8_SNORM; break; + case gpu::NUINT2: + texel.format = GL_RGBA; + texel.internalFormat = GL_RGBA2; + break; case gpu::NUINT32: case gpu::NINT32: case gpu::COMPRESSED: diff --git a/libraries/gpu/src/gpu/Format.cpp b/libraries/gpu/src/gpu/Format.cpp index 7efe4d3ed6..3b153097cf 100644 --- a/libraries/gpu/src/gpu/Format.cpp +++ b/libraries/gpu/src/gpu/Format.cpp @@ -19,6 +19,8 @@ const Element Element::COLOR_SRGBA_32{ VEC4, NUINT8, SRGBA }; const Element Element::COLOR_BGRA_32{ VEC4, NUINT8, BGRA }; const Element Element::COLOR_SBGRA_32{ VEC4, NUINT8, SBGRA }; +const Element Element::COLOR_RGBA_2{ VEC4, NUINT2, RGBA }; + const Element Element::COLOR_COMPRESSED_RED{ TILE4x4, COMPRESSED, COMPRESSED_BC4_RED }; const Element Element::COLOR_COMPRESSED_SRGB { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGB }; const Element Element::COLOR_COMPRESSED_SRGBA_MASK { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGBA }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 0654b23581..9d5d2fc49d 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -38,6 +38,7 @@ enum Type : uint8_t { NUINT16, NINT8, NUINT8, + NUINT2, COMPRESSED, @@ -309,6 +310,7 @@ public: static const Element COLOR_SRGBA_32; static const Element COLOR_BGRA_32; static const Element COLOR_SBGRA_32; + static const Element COLOR_RGBA_2; static const Element COLOR_R11G11B10; static const Element COLOR_RGB9E5; static const Element COLOR_COMPRESSED_RED; diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index d5b3b1c3bb..375ba462b9 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -27,12 +27,10 @@ using namespace render; -extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state); - -OutlineFramebuffer::OutlineFramebuffer() { +OutlineRessources::OutlineRessources() { } -void OutlineFramebuffer::update(const gpu::TexturePointer& colorBuffer) { +void OutlineRessources::update(const gpu::TexturePointer& colorBuffer) { // If the depth buffer or size changed, we need to delete our FBOs and recreate them at the // new correct dimensions. if (_depthTexture) { @@ -44,37 +42,48 @@ void OutlineFramebuffer::update(const gpu::TexturePointer& colorBuffer) { } } -void OutlineFramebuffer::clear() { - _depthFramebuffer.reset(); +void OutlineRessources::clear() { + _frameBuffer.reset(); _depthTexture.reset(); + _idTexture.reset(); } -void OutlineFramebuffer::allocate() { +void OutlineRessources::allocate() { auto width = _frameSize.x; auto height = _frameSize.y; - auto format = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); - _depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(format, width, height)); - _depthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); - _depthFramebuffer->setDepthStencilBuffer(_depthTexture, format); + _idTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_2, width, height)); + _depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(depthFormat, width, height)); + + _frameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); + _frameBuffer->setDepthStencilBuffer(_depthTexture, depthFormat); + _frameBuffer->setRenderBuffer(0, _idTexture); } -gpu::FramebufferPointer OutlineFramebuffer::getDepthFramebuffer() { - if (!_depthFramebuffer) { +gpu::FramebufferPointer OutlineRessources::getFramebuffer() { + if (!_frameBuffer) { allocate(); } - return _depthFramebuffer; + return _frameBuffer; } -gpu::TexturePointer OutlineFramebuffer::getDepthTexture() { +gpu::TexturePointer OutlineRessources::getDepthTexture() { if (!_depthTexture) { allocate(); } return _depthTexture; } -void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) { +gpu::TexturePointer OutlineRessources::getIDTexture() { + if (!_idTexture) { + allocate(); + } + return _idTexture; +} + +void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); auto& inShapes = inputs.get0(); @@ -84,19 +93,19 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co RenderArgs* args = renderContext->args; ShapeKey::Builder defaultKeyBuilder; - if (!_outlineFramebuffer) { - _outlineFramebuffer = std::make_shared(); + if (!_outlineRessources) { + _outlineRessources = std::make_shared(); } - _outlineFramebuffer->update(deferredFrameBuffer->getDeferredColorTexture()); + _outlineRessources->update(deferredFrameBuffer->getDeferredColorTexture()); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; - batch.setFramebuffer(_outlineFramebuffer->getDepthFramebuffer()); + batch.setFramebuffer(_outlineRessources->getFramebuffer()); // Clear it batch.clearFramebuffer( - gpu::Framebuffer::BUFFER_DEPTH, - vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, false); + gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, + vec4(0.0f, 0.0f, 0.0f, 0.0f), 1.0f, 0, false); // Setup camera, projection and viewport for all items batch.setViewportTransform(args->_viewport); @@ -110,14 +119,14 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); - auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); + auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); + auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); std::vector skinnedShapeKeys{}; // Iterate through all inShapes and render the unskinned - args->_shapePipeline = shadowPipeline; - batch.setPipeline(shadowPipeline->pipeline); + args->_shapePipeline = maskPipeline; + batch.setPipeline(maskPipeline->pipeline); for (auto items : inShapes) { if (items.first.isSkinned()) { skinnedShapeKeys.push_back(items.first); @@ -128,8 +137,8 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co } // Reiterate to render the skinned - args->_shapePipeline = shadowSkinnedPipeline; - batch.setPipeline(shadowSkinnedPipeline->pipeline); + args->_shapePipeline = maskSkinnedPipeline; + batch.setPipeline(maskSkinnedPipeline->pipeline); for (const auto& key : skinnedShapeKeys) { renderItems(renderContext, inShapes.at(key)); } @@ -138,7 +147,7 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co args->_batch = nullptr; }); - output = _outlineFramebuffer; + output = _outlineRessources; } else { output = nullptr; } @@ -348,7 +357,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende state->setDepthTest(true, true, gpu::LESS_EQUAL); state->setColorWriteMask(false, false, false, false); - initZPassPipelines(*shapePlumberZPass, state); + initMaskPipelines(*shapePlumberZPass, state); } const auto outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", selectedMetas); @@ -359,8 +368,8 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende const auto sortedShapes = task.addJob("OutlineDepthSort", sortedPipelines); // Draw depth of outlined objects in separate buffer - const auto drawOutlineDepthInputs = DrawOutlineDepth::Inputs(sortedShapes, sceneFrameBuffer).asVarying(); - const auto outlinedFrameBuffer = task.addJob("OutlineDepth", drawOutlineDepthInputs, shapePlumberZPass); + const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedShapes, sceneFrameBuffer).asVarying(); + const auto outlinedFrameBuffer = task.addJob("OutlineMask", drawMaskInputs, shapePlumberZPass); // Draw outline const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, primaryFramebuffer).asVarying(); @@ -369,3 +378,43 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende // Debug outline task.addJob("OutlineDebug", outlinedFrameBuffer); } + +#include "model_shadow_vert.h" +#include "model_shadow_fade_vert.h" +#include "skin_model_shadow_vert.h" +#include "skin_model_shadow_fade_vert.h" + +#include "model_shadow_frag.h" +#include "model_shadow_fade_frag.h" +#include "skin_model_shadow_frag.h" +#include "skin_model_shadow_fade_frag.h" + +void DrawOutlineTask::initMaskPipelines(render::ShapePlumber& shapePlumber, gpu::StatePointer state) { + auto modelVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); + auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); + gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withoutSkinned().withoutFade(), + modelProgram, state); + + auto skinVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); + auto skinPixel = gpu::Shader::createPixel(std::string(skin_model_shadow_frag)); + gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, skinPixel); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withSkinned().withoutFade(), + skinProgram, state); + + auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_shadow_fade_vert)); + auto modelFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag)); + gpu::ShaderPointer modelFadeProgram = gpu::Shader::createProgram(modelFadeVertex, modelFadePixel); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withoutSkinned().withFade(), + modelFadeProgram, state); + + auto skinFadeVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_fade_vert)); + auto skinFadePixel = gpu::Shader::createPixel(std::string(skin_model_shadow_fade_frag)); + gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(skinFadeVertex, skinFadePixel); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withSkinned().withFade(), + skinFadeProgram, state); +} diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index f88092429f..b04f102a83 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -16,11 +16,12 @@ #include "DeferredFramebuffer.h" #include "DeferredFrameTransform.h" -class OutlineFramebuffer { +class OutlineRessources { public: - OutlineFramebuffer(); + OutlineRessources(); - gpu::FramebufferPointer getDepthFramebuffer(); + gpu::FramebufferPointer getFramebuffer(); + gpu::TexturePointer getIDTexture(); gpu::TexturePointer getDepthTexture(); // Update the source framebuffer size which will drive the allocation of all the other resources. @@ -32,30 +33,31 @@ protected: void clear(); void allocate(); - gpu::FramebufferPointer _depthFramebuffer; + gpu::FramebufferPointer _frameBuffer; gpu::TexturePointer _depthTexture; + gpu::TexturePointer _idTexture; glm::ivec2 _frameSize; }; -using OutlineFramebufferPointer = std::shared_ptr; +using OutlineRessourcesPointer = std::shared_ptr; -class DrawOutlineDepth { +class DrawOutlineMask { public: using Inputs = render::VaryingSet2; // Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer - using Outputs = OutlineFramebufferPointer; - using JobModel = render::Job::ModelIO; + using Outputs = OutlineRessourcesPointer; + using JobModel = render::Job::ModelIO; - DrawOutlineDepth(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + DrawOutlineMask(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output); protected: render::ShapePlumberPointer _shapePlumber; - OutlineFramebufferPointer _outlineFramebuffer; + OutlineRessourcesPointer _outlineRessources; }; class DrawOutlineConfig : public render::Job::Config { @@ -93,7 +95,7 @@ signals: class DrawOutline { public: - using Inputs = render::VaryingSet4; + using Inputs = render::VaryingSet4; using Config = DrawOutlineConfig; using JobModel = render::Job::ModelI; @@ -146,7 +148,7 @@ signals: class DebugOutline { public: - using Inputs = OutlineFramebufferPointer; + using Inputs = OutlineRessourcesPointer; using Config = DebugOutlineConfig; using JobModel = render::Job::ModelI; @@ -176,6 +178,9 @@ public: void configure(const Config& config); void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); +private: + + static void initMaskPipelines(render::ShapePlumber& plumber, gpu::StatePointer state); }; #endif // hifi_render_utils_OutlineEffect_h From 2658d658148ce359ebd9fd6903bafce0747dcc5d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 13 Oct 2017 12:02:21 +0200 Subject: [PATCH 013/183] Preparing for outline color mask --- libraries/render-utils/src/OutlineEffect.cpp | 145 ++++++++++++------ libraries/render-utils/src/OutlineEffect.h | 20 ++- .../render-utils/src/RenderDeferredTask.cpp | 2 +- libraries/render-utils/src/model_outline.slf | 21 +++ .../render-utils/src/model_outline_fade.slf | 31 ++++ .../developer/utilities/render/outline.qml | 6 +- 6 files changed, 166 insertions(+), 59 deletions(-) create mode 100644 libraries/render-utils/src/model_outline.slf create mode 100644 libraries/render-utils/src/model_outline_fade.slf diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 375ba462b9..68f1759437 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -76,7 +76,7 @@ gpu::TexturePointer OutlineRessources::getDepthTexture() { return _depthTexture; } -gpu::TexturePointer OutlineRessources::getIDTexture() { +gpu::TexturePointer OutlineRessources::getIdTexture() { if (!_idTexture) { allocate(); } @@ -123,10 +123,13 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); std::vector skinnedShapeKeys{}; + auto colorLoc = maskPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color"); + glm::vec4 idColor{ 1.0f, 0.0f, 0.0f, 0.0f }; // Iterate through all inShapes and render the unskinned args->_shapePipeline = maskPipeline; batch.setPipeline(maskPipeline->pipeline); + batch._glUniform4f(colorLoc, idColor.r, idColor.g, idColor.b, idColor.a); for (auto items : inShapes) { if (items.first.isSkinned()) { skinnedShapeKeys.push_back(items.first); @@ -136,9 +139,11 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con } } + colorLoc = maskSkinnedPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color"); // Reiterate to render the skinned args->_shapePipeline = maskSkinnedPipeline; batch.setPipeline(maskSkinnedPipeline->pipeline); + batch._glUniform4f(colorLoc, idColor.r, idColor.g, idColor.b, idColor.a); for (const auto& key : skinnedShapeKeys) { renderItems(renderContext, inShapes.at(key)); } @@ -250,24 +255,26 @@ const gpu::PipelinePointer& DrawOutline::getPipeline(bool isFilled) { } DebugOutline::DebugOutline() { - _geometryId = DependencyManager::get()->allocateID(); + _geometryDepthId = DependencyManager::get()->allocateID(); + _geometryColorId = DependencyManager::get()->allocateID(); } DebugOutline::~DebugOutline() { auto geometryCache = DependencyManager::get(); if (geometryCache) { - geometryCache->releaseID(_geometryId); + geometryCache->releaseID(_geometryDepthId); + geometryCache->releaseID(_geometryColorId); } } void DebugOutline::configure(const Config& config) { - _isDisplayDepthEnabled = config.viewOutlinedDepth; + _isDisplayEnabled = config.viewMask; } void DebugOutline::run(const render::RenderContextPointer& renderContext, const Inputs& input) { const auto outlineFramebuffer = input; - if (_isDisplayDepthEnabled && outlineFramebuffer) { + if (_isDisplayEnabled && outlineFramebuffer) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; @@ -286,52 +293,101 @@ void DebugOutline::run(const render::RenderContextPointer& renderContext, const batch.setViewTransform(viewMat, true); batch.setModelTransform(Transform()); - batch.setPipeline(getDebugPipeline()); - batch.setResourceTexture(0, outlineFramebuffer->getDepthTexture()); + const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); - const glm::vec4 color(1.0f, 0.5f, 0.2f, 1.0f); - const glm::vec2 bottomLeft(-1.0f, -1.0f); - const glm::vec2 topRight(1.0f, 1.0f); - geometryBuffer->renderQuad(batch, bottomLeft, topRight, color, _geometryId); + batch.setPipeline(getDepthPipeline()); + batch.setResourceTexture(0, outlineFramebuffer->getDepthTexture()); + { + const glm::vec2 bottomLeft(-1.0f, -1.0f); + const glm::vec2 topRight(0.0f, 1.0f); + geometryBuffer->renderQuad(batch, bottomLeft, topRight, color, _geometryDepthId); + } + + batch.setPipeline(getIdPipeline()); + batch.setResourceTexture(0, outlineFramebuffer->getIdTexture()); + { + const glm::vec2 bottomLeft(0.0f, -1.0f); + const glm::vec2 topRight(1.0f, 1.0f); + geometryBuffer->renderQuad(batch, bottomLeft, topRight, color, _geometryColorId); + } batch.setResourceTexture(0, nullptr); }); } } -const gpu::PipelinePointer& DebugOutline::getDebugPipeline() { - if (!_debugPipeline) { - static const std::string VERTEX_SHADER{ debug_deferred_buffer_vert }; - static const std::string FRAGMENT_SHADER{ debug_deferred_buffer_frag }; - static const std::string SOURCE_PLACEHOLDER{ "//SOURCE_PLACEHOLDER" }; - static const auto SOURCE_PLACEHOLDER_INDEX = FRAGMENT_SHADER.find(SOURCE_PLACEHOLDER); - Q_ASSERT_X(SOURCE_PLACEHOLDER_INDEX != std::string::npos, Q_FUNC_INFO, - "Could not find source placeholder"); - static const std::string DEFAULT_DEPTH_SHADER{ +void DebugOutline::initializePipelines() { + static const std::string VERTEX_SHADER{ debug_deferred_buffer_vert }; + static const std::string FRAGMENT_SHADER{ debug_deferred_buffer_frag }; + static const std::string SOURCE_PLACEHOLDER{ "//SOURCE_PLACEHOLDER" }; + static const auto SOURCE_PLACEHOLDER_INDEX = FRAGMENT_SHADER.find(SOURCE_PLACEHOLDER); + Q_ASSERT_X(SOURCE_PLACEHOLDER_INDEX != std::string::npos, Q_FUNC_INFO, + "Could not find source placeholder"); + + auto state = std::make_shared(); + state->setDepthTest(gpu::State::DepthTest(false)); + + const auto vs = gpu::Shader::createVertex(VERTEX_SHADER); + + // Depth shader + { + static const std::string DEPTH_SHADER{ "vec4 getFragmentColor() {" " float Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;" " Zdb = 1.0-(1.0-Zdb)*100;" - " return vec4(Zdb, Zdb, Zdb, 1.0);" - " }" + " return vec4(Zdb, Zdb, Zdb, 1.0); " + "}" }; - auto bakedFragmentShader = FRAGMENT_SHADER; - bakedFragmentShader.replace(SOURCE_PLACEHOLDER_INDEX, SOURCE_PLACEHOLDER.size(), DEFAULT_DEPTH_SHADER); + auto fragmentShader = FRAGMENT_SHADER; + fragmentShader.replace(SOURCE_PLACEHOLDER_INDEX, SOURCE_PLACEHOLDER.size(), DEPTH_SHADER); - static const auto vs = gpu::Shader::createVertex(VERTEX_SHADER); - const auto ps = gpu::Shader::createPixel(bakedFragmentShader); + const auto ps = gpu::Shader::createPixel(fragmentShader); const auto program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding("depthMap", 0)); gpu::Shader::makeProgram(*program, slotBindings); - auto state = std::make_shared(); - state->setDepthTest(gpu::State::DepthTest(false)); - _debugPipeline = gpu::Pipeline::create(program, state); + _depthPipeline = gpu::Pipeline::create(program, state); } - return _debugPipeline; + // ID shader + { + static const std::string ID_SHADER{ + "vec4 getFragmentColor() {" + " return texelFetch(albedoMap, ivec2(gl_FragCoord.xy), 0); " + "}" + }; + + auto fragmentShader = FRAGMENT_SHADER; + fragmentShader.replace(SOURCE_PLACEHOLDER_INDEX, SOURCE_PLACEHOLDER.size(), ID_SHADER); + + const auto ps = gpu::Shader::createPixel(fragmentShader); + const auto program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding("albedoMap", 0)); + gpu::Shader::makeProgram(*program, slotBindings); + + _idPipeline = gpu::Pipeline::create(program, state); + } +} + +const gpu::PipelinePointer& DebugOutline::getDepthPipeline() { + if (!_depthPipeline) { + initializePipelines(); + } + + return _depthPipeline; +} + +const gpu::PipelinePointer& DebugOutline::getIdPipeline() { + if (!_idPipeline) { + initializePipelines(); + } + + return _idPipeline; } DrawOutlineTask::DrawOutlineTask() { @@ -345,19 +401,18 @@ void DrawOutlineTask::configure(const Config& config) { void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { const auto input = inputs.get(); const auto selectedMetas = inputs.getN(0); - const auto shapePlumber = input.get1(); - const auto sceneFrameBuffer = inputs.getN(2); - const auto primaryFramebuffer = inputs.getN(3); - const auto deferredFrameTransform = inputs.getN(4); + const auto sceneFrameBuffer = inputs.getN(1); + const auto primaryFramebuffer = inputs.getN(2); + const auto deferredFrameTransform = inputs.getN(3); // Prepare the ShapePipeline - ShapePlumberPointer shapePlumberZPass = std::make_shared(); + ShapePlumberPointer shapePlumber = std::make_shared(); { auto state = std::make_shared(); state->setDepthTest(true, true, gpu::LESS_EQUAL); state->setColorWriteMask(false, false, false, false); - initMaskPipelines(*shapePlumberZPass, state); + initMaskPipelines(*shapePlumber, state); } const auto outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", selectedMetas); @@ -369,7 +424,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende // Draw depth of outlined objects in separate buffer const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedShapes, sceneFrameBuffer).asVarying(); - const auto outlinedFrameBuffer = task.addJob("OutlineMask", drawMaskInputs, shapePlumberZPass); + const auto outlinedFrameBuffer = task.addJob("OutlineMask", drawMaskInputs, shapePlumber); // Draw outline const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, primaryFramebuffer).asVarying(); @@ -384,36 +439,32 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende #include "skin_model_shadow_vert.h" #include "skin_model_shadow_fade_vert.h" -#include "model_shadow_frag.h" -#include "model_shadow_fade_frag.h" -#include "skin_model_shadow_frag.h" -#include "skin_model_shadow_fade_frag.h" +#include "model_outline_frag.h" +#include "model_outline_fade_frag.h" void DrawOutlineTask::initMaskPipelines(render::ShapePlumber& shapePlumber, gpu::StatePointer state) { auto modelVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); - auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); + auto modelPixel = gpu::Shader::createPixel(std::string(model_outline_frag)); gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withoutSkinned().withoutFade(), modelProgram, state); auto skinVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); - auto skinPixel = gpu::Shader::createPixel(std::string(skin_model_shadow_frag)); - gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, skinPixel); + gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, modelPixel); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withSkinned().withoutFade(), skinProgram, state); auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_shadow_fade_vert)); - auto modelFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag)); + auto modelFadePixel = gpu::Shader::createPixel(std::string(model_outline_fade_frag)); gpu::ShaderPointer modelFadeProgram = gpu::Shader::createProgram(modelFadeVertex, modelFadePixel); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withoutSkinned().withFade(), modelFadeProgram, state); auto skinFadeVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_fade_vert)); - auto skinFadePixel = gpu::Shader::createPixel(std::string(skin_model_shadow_fade_frag)); - gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(skinFadeVertex, skinFadePixel); + gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(skinFadeVertex, modelFadePixel); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withSkinned().withFade(), skinFadeProgram, state); diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index b04f102a83..511ed4a992 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -21,7 +21,7 @@ public: OutlineRessources(); gpu::FramebufferPointer getFramebuffer(); - gpu::TexturePointer getIDTexture(); + gpu::TexturePointer getIdTexture(); gpu::TexturePointer getDepthTexture(); // Update the source framebuffer size which will drive the allocation of all the other resources. @@ -136,11 +136,11 @@ private: class DebugOutlineConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(bool viewOutlinedDepth MEMBER viewOutlinedDepth NOTIFY dirty) + Q_PROPERTY(bool viewMask MEMBER viewMask NOTIFY dirty) public: - bool viewOutlinedDepth{ false }; + bool viewMask{ false }; signals: void dirty(); @@ -160,16 +160,20 @@ public: private: - const gpu::PipelinePointer& getDebugPipeline(); + gpu::PipelinePointer _depthPipeline; + gpu::PipelinePointer _idPipeline; + int _geometryDepthId{ 0 }; + int _geometryColorId{ 0 }; + bool _isDisplayEnabled{ false }; - gpu::PipelinePointer _debugPipeline; - int _geometryId{ 0 }; - bool _isDisplayDepthEnabled{ false }; + const gpu::PipelinePointer& getDepthPipeline(); + const gpu::PipelinePointer& getIdPipeline(); + void initializePipelines(); }; class DrawOutlineTask { public: - using Inputs = render::VaryingSet5; + using Inputs = render::VaryingSet4; using Config = render::Task::Config; using JobModel = render::Task::ModelI; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 45e6fd4ba4..1739f67748 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -173,7 +173,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("ToneMapping", toneMappingInputs); const auto outlineRangeTimer = task.addJob("BeginOutlineRangeTimer", "Outline"); - const auto outlineInputs = DrawOutlineTask::Inputs(selectedItems, shapePlumber, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); + const auto outlineInputs = DrawOutlineTask::Inputs(selectedItems, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); task.addJob("DrawOutline", outlineInputs); task.addJob("EndOutlineRangeTimer", outlineRangeTimer); diff --git a/libraries/render-utils/src/model_outline.slf b/libraries/render-utils/src/model_outline.slf new file mode 100644 index 0000000000..8c11b2b295 --- /dev/null +++ b/libraries/render-utils/src/model_outline.slf @@ -0,0 +1,21 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_outline.frag +// fragment shader +// +// Created by Olivier Prat on 10/13/17. +// Copyright 2017 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 +// + +layout(location = 0) out vec4 _fragColor; + +uniform vec4 color; + +void main(void) { + _fragColor = color; +} diff --git a/libraries/render-utils/src/model_outline_fade.slf b/libraries/render-utils/src/model_outline_fade.slf new file mode 100644 index 0000000000..69ff54dea6 --- /dev/null +++ b/libraries/render-utils/src/model_outline_fade.slf @@ -0,0 +1,31 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_outline_fade.frag +// fragment shader +// +// Created by Olivier Prat on 10/13/17. +// Copyright 2017 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 Fade.slh@> +<$declareFadeFragment()$> + +layout(location = 0) out vec4 _fragColor; + +uniform vec4 color; + +in vec4 _worldPosition; + +void main(void) { + FadeObjectParams fadeParams; + + <$fetchFadeObjectParams(fadeParams)$> + applyFadeClip(fadeParams, _worldPosition.xyz); + + _fragColor = color; +} diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index e17f7c1f1c..1b5cbf6e1c 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -21,10 +21,10 @@ Item { spacing: 8 CheckBox { - text: "View Outlined Depth" - checked: root.debugConfig["viewOutlinedDepth"] + text: "View Mask" + checked: root.debugConfig["viewMask"] onCheckedChanged: { - root.debugConfig["viewOutlinedDepth"] = checked; + root.debugConfig["viewMask"] = checked; } } CheckBox { From 8d79313a9debcdcceebf0a6ebca5e2b849f0787a Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 16 Oct 2017 09:42:58 +0200 Subject: [PATCH 014/183] Working mask rendering and debugging --- libraries/render-utils/src/OutlineEffect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 68f1759437..96a37eca6a 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -410,7 +410,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende { auto state = std::make_shared(); state->setDepthTest(true, true, gpu::LESS_EQUAL); - state->setColorWriteMask(false, false, false, false); + state->setColorWriteMask(true, true, true, true); initMaskPipelines(*shapePlumber, state); } From e42699c0ea615a47eee62c8281fd282b9542c3d6 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 16 Oct 2017 10:57:06 +0200 Subject: [PATCH 015/183] Added multiple selections but still only first linked to outline --- .../ui/overlays/ContextOverlayInterface.cpp | 9 ++-- .../src/ui/overlays/ContextOverlayInterface.h | 7 ++- libraries/render-utils/src/OutlineEffect.cpp | 4 +- libraries/render-utils/src/OutlineEffect.h | 8 +++- .../render-utils/src/RenderDeferredTask.cpp | 43 +++++++++++++------ .../render-utils/src/RenderDeferredTask.h | 4 ++ 6 files changed, 55 insertions(+), 20 deletions(-) diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 8cbb214857..f677dc6550 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -34,7 +34,12 @@ ContextOverlayInterface::ContextOverlayInterface() { _tabletScriptingInterface = DependencyManager::get(); _selectionScriptingInterface = DependencyManager::get(); - _selectionToSceneHandler.initialize("contextOverlayHighlightList"); + _selectionToSceneHandlers[0].initialize("contextOverlayHighlightList"); + connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandlers[0], &SelectionToSceneHandler::selectedItemsListChanged); + for (auto i = 1; i < MAX_HIGHLIGHT_COUNT; i++) { + _selectionToSceneHandlers[i].initialize(QString("contextOverlayHighlightList")+QString::number(i)); + connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandlers[i], &SelectionToSceneHandler::selectedItemsListChanged); + } _entityPropertyFlags += PROP_POSITION; _entityPropertyFlags += PROP_ROTATION; @@ -61,8 +66,6 @@ ContextOverlayInterface::ContextOverlayInterface() { }); auto entityScriptingInterface = DependencyManager::get().data(); connect(entityScriptingInterface, &EntityScriptingInterface::deletingEntity, this, &ContextOverlayInterface::deletingEntity); - - connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandler, &SelectionToSceneHandler::selectedItemsListChanged); } static const uint32_t MOUSE_HW_ID = 0; diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index b4d3ddc0c2..2a96ea3d3e 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -47,6 +47,11 @@ class ContextOverlayInterface : public QObject, public Dependency { OverlayID _contextOverlayID { UNKNOWN_OVERLAY_ID }; std::shared_ptr _contextOverlay { nullptr }; public: + + enum { + MAX_HIGHLIGHT_COUNT = 4 + }; + ContextOverlayInterface(); Q_INVOKABLE QUuid getCurrentEntityWithContextOverlay() { return _currentEntityWithContextOverlay; } @@ -86,7 +91,7 @@ private: void deletingEntity(const EntityItemID& entityItemID); - SelectionToSceneHandler _selectionToSceneHandler; + SelectionToSceneHandler _selectionToSceneHandlers[MAX_HIGHLIGHT_COUNT]; }; #endif // hifi_ContextOverlayInterface_h diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 96a37eca6a..89cedf0676 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -399,8 +399,8 @@ void DrawOutlineTask::configure(const Config& config) { } void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { - const auto input = inputs.get(); - const auto selectedMetas = inputs.getN(0); + const auto groups = inputs.getN(0).get(); + const auto selectedMetas = groups[0]; const auto sceneFrameBuffer = inputs.getN(1); const auto primaryFramebuffer = inputs.getN(2); const auto deferredFrameTransform = inputs.getN(3); diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index 511ed4a992..c32d352a01 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -173,7 +173,13 @@ private: class DrawOutlineTask { public: - using Inputs = render::VaryingSet4; + + enum { + MAX_GROUP_COUNT = 7 + }; + + using Groups = render::VaryingArray; + using Inputs = render::VaryingSet4; using Config = render::Task::Config; using JobModel = render::Task::ModelI; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 1739f67748..c20eb10cf6 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -44,6 +44,7 @@ #include +#include using namespace render; extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false); @@ -57,6 +58,18 @@ void RenderDeferredTask::configure(const Config& config) { } +const render::Varying RenderDeferredTask::addSelectItemJobs(JobModel& task, const char* selectionName, + const render::Varying& metas, + const render::Varying& opaques, + const render::Varying& transparents) { + const auto selectMetaInput = SelectItems::Inputs(metas, Varying()).asVarying(); + const auto selectedMetas = task.addJob("MetaSelection", selectMetaInput, selectionName); + const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas).asVarying(); + const auto selectedMetasAndOpaques = task.addJob("OpaqueSelection", selectMetaAndOpaqueInput, selectionName); + const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques).asVarying(); + return task.addJob("TransparentSelection", selectItemInput, selectionName); +} + void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { const auto& items = input.get(); auto fadeEffect = DependencyManager::get(); @@ -94,15 +107,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // draw a stencil mask in hidden regions of the framebuffer. task.addJob("PrepareStencil", primaryFramebuffer); - // Select items that need to be outlined - const auto selectionName = "contextOverlayHighlightList"; - const auto selectMetaInput = SelectItems::Inputs(metas, Varying()).asVarying(); - const auto selectedMetas = task.addJob("PassTestMetaSelection", selectMetaInput, selectionName); - const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas).asVarying(); - const auto selectedMetasAndOpaques = task.addJob("PassTestOpaqueSelection", selectMetaAndOpaqueInput, selectionName); - const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques).asVarying(); - const auto selectedItems = task.addJob("PassTestTransparentSelection", selectItemInput, selectionName); - // Render opaque objects in DeferredBuffer const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).asVarying(); task.addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber); @@ -172,9 +176,22 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer).asVarying(); task.addJob("ToneMapping", toneMappingInputs); + // Select items that need to be outlined + const auto selectionBaseName = "contextOverlayHighlightList"; + const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents); + DrawOutlineTask::Groups outlineGroups; + outlineGroups[0] = selectedItems; + for (auto i = 1; i < DrawOutlineTask::MAX_GROUP_COUNT; i++) { + std::ostringstream selectionName; + selectionName << selectionBaseName; + selectionName << i; + outlineGroups[i] = addSelectItemJobs(task, selectionName.str().c_str(), metas, opaques, transparents); + } const auto outlineRangeTimer = task.addJob("BeginOutlineRangeTimer", "Outline"); - const auto outlineInputs = DrawOutlineTask::Inputs(selectedItems, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); + + const auto outlineInputs = DrawOutlineTask::Inputs(outlineGroups, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); task.addJob("DrawOutline", outlineInputs); + task.addJob("EndOutlineRangeTimer", outlineRangeTimer); { // DEbug the bounds of the rendered items, still look at the zbuffer @@ -184,6 +201,9 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawLightBounds", lights); task.addJob("DrawZones", zones); + + // Render.getConfig("RenderMainView.DrawSelectionBounds").enabled = true + task.addJob("DrawSelectionBounds", selectedItems); } // Layered Overlays @@ -230,9 +250,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren } task.addJob("DrawZoneStack", deferredFrameTransform); - - // Render.getConfig("RenderMainView.DrawSelectionBounds").enabled = true - task.addJob("DrawSelectionBounds", selectedItems); } // AA job to be revisited diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 452420589b..567e7f6ccd 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -198,6 +198,10 @@ public: void configure(const Config& config); void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); +private: + + static const render::Varying addSelectItemJobs(JobModel& task, const char* selectionName, + const render::Varying& metas, const render::Varying& opaques, const render::Varying& transparents); }; #endif // hifi_RenderDeferredTask_h From 1b67223e0eaaff87363c7f18bf8a0e3c4255943a Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 16 Oct 2017 12:38:44 +0200 Subject: [PATCH 016/183] Preparing for multiple outline groups in shader --- libraries/render-utils/src/Outline.slh | 8 +- libraries/render-utils/src/OutlineEffect.cpp | 221 +++++++++++------- libraries/render-utils/src/OutlineEffect.h | 92 +++++--- libraries/render-utils/src/Outline_shared.slh | 4 + .../render-utils/src/RenderDeferredTask.cpp | 2 +- 5 files changed, 210 insertions(+), 117 deletions(-) diff --git a/libraries/render-utils/src/Outline.slh b/libraries/render-utils/src/Outline.slh index ac56e4c95c..4e71116f79 100644 --- a/libraries/render-utils/src/Outline.slh +++ b/libraries/render-utils/src/Outline.slh @@ -21,11 +21,13 @@ uniform outlineParamsBuffer { uniform sampler2D sceneDepthMap; uniform sampler2D outlinedDepthMap; +uniform sampler2D outlinedIdMap; in vec2 varTexCoord0; out vec4 outFragColor; const float FAR_Z = 1.0; +const float ID_THRESHOLD = 1.f/64.f; const float LINEAR_DEPTH_BIAS = 5e-3; const float OPACITY_EPSILON = 5e-3; @@ -37,10 +39,11 @@ void main(void) { // sides of the silhouette vec2 halfTexel = getInvWidthHeight() / 2; vec2 texCoord0 = varTexCoord0+halfTexel; + vec4 outlinedIdColor = texture(outlinedIdMap, texCoord0); float outlinedDepth = texture(outlinedDepthMap, texCoord0).x; float intensity = 0.0; - if (outlinedDepth < FAR_Z) { + if (outlinedDepth < FAR_Z && distance(outlinedIdColor, params._idColor) < ID_THRESHOLD) { // We're not on the far plane so we are on the outlined object, thus no outline to do! <@if IS_FILLED@> // But we need to fill the interior @@ -75,7 +78,8 @@ void main(void) { if (uv.x>=0.0 && uv.x<=1.0) { outlinedDepth = texture(outlinedDepthMap, uv).x; - intensity += (outlinedDepth < FAR_Z) ? 1.0 : 0.0; + outlinedIdColor = texture(outlinedIdMap, uv); + intensity += (outlinedDepth < FAR_Z && distance(outlinedIdColor, params._idColor) < ID_THRESHOLD) ? 1.0 : 0.0; weight += 1.f; } uv.x += deltaUv.x; diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 89cedf0676..0ffd2581cf 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -83,81 +83,139 @@ gpu::TexturePointer OutlineRessources::getIdTexture() { return _idTexture; } +glm::vec4 encodeIdToColor(unsigned int id) { + union { + struct { + unsigned int r : 2; + unsigned int g : 2; + unsigned int b : 2; + unsigned int a : 2; + }; + unsigned char id; + } groupId; + + assert(id < 254); + groupId.id = id+1; + + glm::vec4 idColor{ groupId.r, groupId.g, groupId.b, groupId.a }; + + // Normalize. Since we put 2 bits into each color component, each component has a maximum + // value of 3. + idColor /= 3.f; + return idColor; +} + void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); - auto& inShapes = inputs.get0(); + auto& groups = inputs.get0(); auto& deferredFrameBuffer = inputs.get1(); - if (!inShapes.empty()) { - RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder; + RenderArgs* args = renderContext->args; + ShapeKey::Builder defaultKeyBuilder; + auto hasOutline = false; - if (!_outlineRessources) { - _outlineRessources = std::make_shared(); + if (!_outlineRessources) { + _outlineRessources = std::make_shared(); + } + _outlineRessources->update(deferredFrameBuffer->getDeferredColorTexture()); + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; + + auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); + auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); + auto colorLoc = maskPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color"); + auto skinnedColorLoc = maskSkinnedPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color"); + unsigned int groupId = 0; + + for (auto& inShapeBounds : groups) { + if (!inShapeBounds.isNull()) { + auto& inShapes = inShapeBounds.get(); + + if (!inShapes.empty()) { + if (!hasOutline) { + batch.setFramebuffer(_outlineRessources->getFramebuffer()); + // Clear it only if it hasn't been done before + batch.clearFramebuffer( + gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, + vec4(0.0f, 0.0f, 0.0f, 0.0f), 1.0f, 0, false); + + // Setup camera, projection and viewport for all items + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + hasOutline = true; + } + + std::vector skinnedShapeKeys{}; + // Encode group id in quantized color + glm::vec4 idColor = encodeIdToColor(groupId); + + // Iterate through all inShapes and render the unskinned + args->_shapePipeline = maskPipeline; + batch.setPipeline(maskPipeline->pipeline); + batch._glUniform4f(colorLoc, idColor.r, idColor.g, idColor.b, idColor.a); + for (auto items : inShapes) { + if (items.first.isSkinned()) { + skinnedShapeKeys.push_back(items.first); + } else { + renderItems(renderContext, items.second); + } + } + + // Reiterate to render the skinned + args->_shapePipeline = maskSkinnedPipeline; + batch.setPipeline(maskSkinnedPipeline->pipeline); + batch._glUniform4f(skinnedColorLoc, idColor.r, idColor.g, idColor.b, idColor.a); + for (const auto& key : skinnedShapeKeys) { + renderItems(renderContext, inShapes.at(key)); + } + } + } + + ++groupId; } - _outlineRessources->update(deferredFrameBuffer->getDeferredColorTexture()); - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - args->_batch = &batch; - - batch.setFramebuffer(_outlineRessources->getFramebuffer()); - // Clear it - batch.clearFramebuffer( - gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, - vec4(0.0f, 0.0f, 0.0f, 0.0f), 1.0f, 0, false); - - // Setup camera, projection and viewport for all items - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - - glm::mat4 projMat; - Transform viewMat; - args->getViewFrustum().evalProjectionMatrix(projMat); - args->getViewFrustum().evalViewTransform(viewMat); - - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - - auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); - auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); - - std::vector skinnedShapeKeys{}; - auto colorLoc = maskPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color"); - glm::vec4 idColor{ 1.0f, 0.0f, 0.0f, 0.0f }; - - // Iterate through all inShapes and render the unskinned - args->_shapePipeline = maskPipeline; - batch.setPipeline(maskPipeline->pipeline); - batch._glUniform4f(colorLoc, idColor.r, idColor.g, idColor.b, idColor.a); - for (auto items : inShapes) { - if (items.first.isSkinned()) { - skinnedShapeKeys.push_back(items.first); - } - else { - renderItems(renderContext, items.second); - } - } - - colorLoc = maskSkinnedPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color"); - // Reiterate to render the skinned - args->_shapePipeline = maskSkinnedPipeline; - batch.setPipeline(maskSkinnedPipeline->pipeline); - batch._glUniform4f(colorLoc, idColor.r, idColor.g, idColor.b, idColor.a); - for (const auto& key : skinnedShapeKeys) { - renderItems(renderContext, inShapes.at(key)); - } - - args->_shapePipeline = nullptr; - args->_batch = nullptr; - }); + args->_shapePipeline = nullptr; + args->_batch = nullptr; + }); + if (hasOutline) { output = _outlineRessources; } else { output = nullptr; } } +PrepareDrawOutline::PrepareDrawOutline() { + +} + +void PrepareDrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { + auto destinationFrameBuffer = inputs; + auto framebufferSize = destinationFrameBuffer->getSize(); + + if (!_primaryWithoutDepthBuffer || framebufferSize != _frameBufferSize) { + // Failing to recreate this frame buffer when the screen has been resized creates a bug on Mac + _primaryWithoutDepthBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithoutDepth")); + _primaryWithoutDepthBuffer->setRenderBuffer(0, destinationFrameBuffer->getRenderBuffer(0)); + _frameBufferSize = framebufferSize; + } + + outputs = _primaryWithoutDepthBuffer; +} + +gpu::PipelinePointer DrawOutline::_pipeline; +gpu::PipelinePointer DrawOutline::_pipelineFilled; + DrawOutline::DrawOutline() { } @@ -170,6 +228,7 @@ void DrawOutline::configure(const Config& config) { _fillOpacityOccluded = config.fillOpacityOccluded; _threshold = config.glow ? 1.f : 1e-3f; _intensity = config.intensity * (config.glow ? 2.f : 1.f); + _hasConfigurationChanged = true; } void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { @@ -179,20 +238,16 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I auto sceneDepthBuffer = inputs.get2(); const auto frameTransform = inputs.get0(); auto outlinedDepthTexture = outlineFrameBuffer->getDepthTexture(); + auto outlinedIdTexture = outlineFrameBuffer->getIdTexture(); auto destinationFrameBuffer = inputs.get3(); auto framebufferSize = glm::ivec2(outlinedDepthTexture->getDimensions()); - if (!_primaryWithoutDepthBuffer || framebufferSize!=_frameBufferSize) { - // Failing to recreate this frame buffer when the screen has been resized creates a bug on Mac - _primaryWithoutDepthBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithoutDepth")); - _primaryWithoutDepthBuffer->setRenderBuffer(0, destinationFrameBuffer->getRenderBuffer(0)); - _frameBufferSize = framebufferSize; - } - if (sceneDepthBuffer) { const auto OPACITY_EPSILON = 5e-3f; auto pipeline = getPipeline(_fillOpacityUnoccluded>OPACITY_EPSILON || _fillOpacityOccluded>OPACITY_EPSILON); auto args = renderContext->args; + + if (_hasConfigurationChanged) { auto& configuration = _configuration.edit(); configuration._color = _color; @@ -201,24 +256,27 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I configuration._fillOpacityOccluded = _fillOpacityOccluded; configuration._threshold = _threshold; configuration._blurKernelSize = _blurKernelSize; - configuration._size.x = _size * _frameBufferSize.y / _frameBufferSize.x; + configuration._size.x = (_size * framebufferSize.y) / framebufferSize.x; configuration._size.y = _size; + configuration._idColor = encodeIdToColor(0); + _hasConfigurationChanged = false; } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); - batch.setFramebuffer(_primaryWithoutDepthBuffer); + batch.setFramebuffer(destinationFrameBuffer); batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); - batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_frameBufferSize, args->_viewport)); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); batch.setPipeline(pipeline); batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer()); batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getPrimaryDepthTexture()); batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthTexture); + batch.setResourceTexture(OUTLINED_ID_SLOT, outlinedIdTexture); batch.draw(gpu::TRIANGLE_STRIP, 4); // Restore previous frame buffer @@ -239,6 +297,7 @@ const gpu::PipelinePointer& DrawOutline::getPipeline(bool isFilled) { slotBindings.insert(gpu::Shader::Binding("deferredFrameTransformBuffer", FRAME_TRANSFORM_SLOT)); slotBindings.insert(gpu::Shader::Binding("sceneDepthMap", SCENE_DEPTH_SLOT)); slotBindings.insert(gpu::Shader::Binding("outlinedDepthMap", OUTLINED_DEPTH_SLOT)); + slotBindings.insert(gpu::Shader::Binding("outlinedIdMap", OUTLINED_ID_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); @@ -400,7 +459,6 @@ void DrawOutlineTask::configure(const Config& config) { void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { const auto groups = inputs.getN(0).get(); - const auto selectedMetas = groups[0]; const auto sceneFrameBuffer = inputs.getN(1); const auto primaryFramebuffer = inputs.getN(2); const auto deferredFrameTransform = inputs.getN(3); @@ -415,19 +473,26 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende initMaskPipelines(*shapePlumber, state); } - const auto outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", selectedMetas); - const auto outlinedItems = task.addJob("OutlineMetaToSubItems", outlinedItemIDs, true); + DrawOutlineMask::Groups sortedBounds; + for (auto i = 0; i < DrawOutline::MAX_GROUP_COUNT; i++) { + const auto groupItems = groups[i]; + const auto outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", groupItems); + const auto outlinedItems = task.addJob("OutlineMetaToSubItems", outlinedItemIDs, true); - // Sort - const auto sortedPipelines = task.addJob("OutlinePipelineSort", outlinedItems); - const auto sortedShapes = task.addJob("OutlineDepthSort", sortedPipelines); + // Sort + const auto sortedPipelines = task.addJob("OutlinePipelineSort", outlinedItems); + sortedBounds[i] = task.addJob("OutlineDepthSort", sortedPipelines); + } // Draw depth of outlined objects in separate buffer - const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedShapes, sceneFrameBuffer).asVarying(); + const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedBounds, sceneFrameBuffer).asVarying(); const auto outlinedFrameBuffer = task.addJob("OutlineMask", drawMaskInputs, shapePlumber); + // Prepare for outline group rendering. + const auto destFrameBuffer = task.addJob("PrepareOutline", primaryFramebuffer); + // Draw outline - const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, primaryFramebuffer).asVarying(); + const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, destFrameBuffer).asVarying(); task.addJob("OutlineEffect", drawOutlineInputs); // Debug outline diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index c32d352a01..ce0b2917a4 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -42,22 +42,22 @@ protected: using OutlineRessourcesPointer = std::shared_ptr; -class DrawOutlineMask { +class PrepareDrawOutline { public: + using Inputs = gpu::FramebufferPointer; + using Outputs = gpu::FramebufferPointer; + using Config = render::Job::Config; + using JobModel = render::Job::ModelIO; - using Inputs = render::VaryingSet2; - // Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer - using Outputs = OutlineRessourcesPointer; - using JobModel = render::Job::ModelIO; + PrepareDrawOutline(); - DrawOutlineMask(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); - void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output); +private: -protected: + gpu::FramebufferPointer _primaryWithoutDepthBuffer; + gpu::Vec2u _frameBufferSize{ 0, 0 }; - render::ShapePlumberPointer _shapePlumber; - OutlineRessourcesPointer _outlineRessources; }; class DrawOutlineConfig : public render::Job::Config { @@ -95,6 +95,10 @@ signals: class DrawOutline { public: + enum { + MAX_GROUP_COUNT = 7 + }; + using Inputs = render::VaryingSet4; using Config = DrawOutlineConfig; using JobModel = render::Job::ModelI; @@ -109,6 +113,7 @@ private: enum { SCENE_DEPTH_SLOT = 0, OUTLINED_DEPTH_SLOT, + OUTLINED_ID_SLOT, OUTLINE_PARAMS_SLOT = 0, FRAME_TRANSFORM_SLOT @@ -118,12 +123,10 @@ private: using OutlineConfigurationBuffer = gpu::StructBuffer; - const gpu::PipelinePointer& getPipeline(bool isFilled); + static const gpu::PipelinePointer& getPipeline(bool isFilled); - gpu::FramebufferPointer _primaryWithoutDepthBuffer; - glm::ivec2 _frameBufferSize {0, 0}; - gpu::PipelinePointer _pipeline; - gpu::PipelinePointer _pipelineFilled; + static gpu::PipelinePointer _pipeline; + static gpu::PipelinePointer _pipelineFilled; OutlineConfigurationBuffer _configuration; glm::vec3 _color; float _size; @@ -132,6 +135,44 @@ private: float _fillOpacityUnoccluded; float _fillOpacityOccluded; float _threshold; + bool _hasConfigurationChanged{ true }; +}; + +class DrawOutlineTask { +public: + + using Groups = render::VaryingArray; + using Inputs = render::VaryingSet4; + using Config = render::Task::Config; + using JobModel = render::Task::ModelI; + + DrawOutlineTask(); + + void configure(const Config& config); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); + +private: + + static void initMaskPipelines(render::ShapePlumber& plumber, gpu::StatePointer state); +}; + +class DrawOutlineMask { +public: + + using Groups = render::VaryingArray; + using Inputs = render::VaryingSet2; + // Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer + using Outputs = OutlineRessourcesPointer; + using JobModel = render::Job::ModelIO; + + DrawOutlineMask(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output); + +protected: + + render::ShapePlumberPointer _shapePlumber; + OutlineRessourcesPointer _outlineRessources; }; class DebugOutlineConfig : public render::Job::Config { @@ -171,27 +212,6 @@ private: void initializePipelines(); }; -class DrawOutlineTask { -public: - - enum { - MAX_GROUP_COUNT = 7 - }; - - using Groups = render::VaryingArray; - using Inputs = render::VaryingSet4; - using Config = render::Task::Config; - using JobModel = render::Task::ModelI; - - DrawOutlineTask(); - - void configure(const Config& config); - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); - -private: - - static void initMaskPipelines(render::ShapePlumber& plumber, gpu::StatePointer state); -}; #endif // hifi_render_utils_OutlineEffect_h diff --git a/libraries/render-utils/src/Outline_shared.slh b/libraries/render-utils/src/Outline_shared.slh index 902bbd20ad..5ce21c85b4 100644 --- a/libraries/render-utils/src/Outline_shared.slh +++ b/libraries/render-utils/src/Outline_shared.slh @@ -2,9 +2,11 @@ #ifdef __cplusplus # define VEC2 glm::vec2 # define VEC3 glm::vec3 +# define VEC4 glm::vec4 #else # define VEC2 vec2 # define VEC3 vec3 +# define VEC4 vec4 #endif struct OutlineParameters @@ -16,6 +18,8 @@ struct OutlineParameters float _fillOpacityUnoccluded; float _fillOpacityOccluded; + VEC4 _idColor; + float _threshold; int _blurKernelSize; float padding2; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index c20eb10cf6..73d8b93c07 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -181,7 +181,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents); DrawOutlineTask::Groups outlineGroups; outlineGroups[0] = selectedItems; - for (auto i = 1; i < DrawOutlineTask::MAX_GROUP_COUNT; i++) { + for (auto i = 1; i < DrawOutline::MAX_GROUP_COUNT; i++) { std::ostringstream selectionName; selectionName << selectionBaseName; selectionName << i; From 70f892e67d47847c60268cfd0469b04f147fc986 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 16 Oct 2017 17:02:13 +0200 Subject: [PATCH 017/183] Ready to plug multiple selections javascript side --- libraries/render-utils/src/Outline.slh | 131 +++++++++++------- libraries/render-utils/src/OutlineEffect.cpp | 32 +++-- libraries/render-utils/src/OutlineEffect.h | 14 +- libraries/render-utils/src/Outline_shared.slh | 6 +- 4 files changed, 112 insertions(+), 71 deletions(-) diff --git a/libraries/render-utils/src/Outline.slh b/libraries/render-utils/src/Outline.slh index 4e71116f79..c58d1c7689 100644 --- a/libraries/render-utils/src/Outline.slh +++ b/libraries/render-utils/src/Outline.slh @@ -16,23 +16,85 @@ <@include Outline_shared.slh@> uniform outlineParamsBuffer { - OutlineParameters params; + OutlineParameters groups[GROUP_COUNT]; }; uniform sampler2D sceneDepthMap; uniform sampler2D outlinedDepthMap; uniform sampler2D outlinedIdMap; +uniform int enabledGroupsMask; in vec2 varTexCoord0; out vec4 outFragColor; const float FAR_Z = 1.0; -const float ID_THRESHOLD = 1.f/64.f; const float LINEAR_DEPTH_BIAS = 5e-3; const float OPACITY_EPSILON = 5e-3; <@func main(IS_FILLED)@> +int getGroupIndexFromColor(vec4 color) { + ivec4 id = ivec4(color * GROUP_ID_COLOR_COMPONENT_MAX) << ivec4(0, GROUP_ID_COLOR_COMPONENT_BITS, GROUP_ID_COLOR_COMPONENT_BITS*2, GROUP_ID_COLOR_COMPONENT_BITS*3); + return (id.r | id.g | id.b | id.a) - 1; +} + +vec4 computeGroupOutline(int centerGroupId, float centerDepth, int groupId, vec2 texCoord) { + float intensity = 0.0; + + if (centerGroupId==groupId && centerDepth < FAR_Z) { + // We're on the outlined object, thus no outline to do! +<@if IS_FILLED@> + OutlineParameters groupParams = groups[groupId]; + + // But we need to fill the interior + float sceneDepth = texture(sceneDepthMap, texCoord).x; + // Transform to linear depth for better precision + centerDepth = -evalZeyeFromZdb(centerDepth); + sceneDepth = -evalZeyeFromZdb(sceneDepth); + + // Are we occluded? + intensity = (sceneDepth < (centerDepth-LINEAR_DEPTH_BIAS)) ? groupParams._fillOpacityOccluded : groupParams._fillOpacityUnoccluded; + return vec4(groupParams._color.rgb, intensity); +<@else@> + return vec4(0,0,0,0); +<@endif@> + } else { + OutlineParameters groupParams = groups[groupId]; + float weight = 0.0; + vec2 deltaUv = groupParams._size / groupParams._blurKernelSize; + vec2 lineStartUv = texCoord - groupParams._size / 2.0; + vec2 uv; + int x; + int y; + + for (y=0 ; y=0.0 && uv.y<=1.0) { + for (x=0 ; x=0.0 && uv.x<=1.0) + { + vec4 outlinedIdColor = texture(outlinedIdMap, uv); + float outlinedDepth = texture(outlinedDepthMap, uv).x; + int outlinedId = getGroupIndexFromColor(outlinedIdColor); + intensity += (outlinedDepth - // But we need to fill the interior - float sceneDepth = texture(sceneDepthMap, texCoord0).x; - // Transform to linear depth for better precision - outlinedDepth = -evalZeyeFromZdb(outlinedDepth); - sceneDepth = -evalZeyeFromZdb(sceneDepth); - - // Are we occluded? - if (sceneDepth < (outlinedDepth-LINEAR_DEPTH_BIAS)) { - intensity = params._fillOpacityOccluded; - } else { - intensity = params._fillOpacityUnoccluded; + vec4 finalColor = vec4(0,0,0,0); + int groupMask = 1; + for (int i=0 ; i - discard; -<@endif@> - } else { - float weight = 0.0; - vec2 deltaUv = params._size / params._blurKernelSize; - vec2 lineStartUv = texCoord0 - params._size / 2.0; - vec2 uv; - int x; - int y; - - for (y=0 ; y=0.0 && uv.y<=1.0) { - for (x=0 ; x=0.0 && uv.x<=1.0) - { - outlinedDepth = texture(outlinedDepthMap, uv).x; - outlinedIdColor = texture(outlinedIdMap, uv); - intensity += (outlinedDepth < FAR_Z && distance(outlinedIdColor, params._idColor) < ID_THRESHOLD) ? 1.0 : 0.0; - weight += 1.f; - } - uv.x += deltaUv.x; - } - } - } - - intensity /= weight; - if (intensity < OPACITY_EPSILON) { - discard; - } - - intensity = min(1.0, intensity / params._threshold) * params._intensity; + groupMask <<= 1; } - outFragColor = vec4(params._color.rgb, intensity); + if (finalColor.a < OPACITY_EPSILON) { + discard; + } + outFragColor = finalColor; } <@endfunc@> diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 0ffd2581cf..2cb19826f4 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -94,6 +94,8 @@ glm::vec4 encodeIdToColor(unsigned int id) { unsigned char id; } groupId; + static_assert(GROUP_ID_COLOR_COMPONENT_BITS == 2, "Assuming two bits per component contrary to GLSL shader code. See Outline_shared.slh"); + assert(id < 254); groupId.id = id+1; @@ -101,7 +103,7 @@ glm::vec4 encodeIdToColor(unsigned int id) { // Normalize. Since we put 2 bits into each color component, each component has a maximum // value of 3. - idColor /= 3.f; + idColor /= GROUP_ID_COLOR_COMPONENT_MAX; return idColor; } @@ -250,15 +252,19 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I if (_hasConfigurationChanged) { auto& configuration = _configuration.edit(); - configuration._color = _color; - configuration._intensity = _intensity; - configuration._fillOpacityUnoccluded = _fillOpacityUnoccluded; - configuration._fillOpacityOccluded = _fillOpacityOccluded; - configuration._threshold = _threshold; - configuration._blurKernelSize = _blurKernelSize; - configuration._size.x = (_size * framebufferSize.y) / framebufferSize.x; - configuration._size.y = _size; - configuration._idColor = encodeIdToColor(0); + + for (auto groupId = 0; groupId < MAX_GROUP_COUNT; groupId++) { + auto& groupConfig = configuration._groups[groupId]; + + groupConfig._color = _color; + groupConfig._intensity = _intensity; + groupConfig._fillOpacityUnoccluded = _fillOpacityUnoccluded; + groupConfig._fillOpacityOccluded = _fillOpacityOccluded; + groupConfig._threshold = _threshold; + groupConfig._blurKernelSize = _blurKernelSize; + groupConfig._size.x = (_size * framebufferSize.y) / framebufferSize.x; + groupConfig._size.y = _size; + } _hasConfigurationChanged = false; } @@ -272,15 +278,15 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); batch.setPipeline(pipeline); + auto enabledGroupsLoc = pipeline->getProgram()->getUniforms().findLocation("enabledGroupsMask"); + batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer()); batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getPrimaryDepthTexture()); batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthTexture); batch.setResourceTexture(OUTLINED_ID_SLOT, outlinedIdTexture); + batch._glUniform1i(enabledGroupsLoc, 1); batch.draw(gpu::TRIANGLE_STRIP, 4); - - // Restore previous frame buffer - batch.setFramebuffer(destinationFrameBuffer); }); } } diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index ce0b2917a4..6e4c0a18a8 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -94,9 +94,13 @@ signals: }; class DrawOutline { +private: + +#include "Outline_shared.slh" + public: enum { - MAX_GROUP_COUNT = 7 + MAX_GROUP_COUNT = GROUP_COUNT }; using Inputs = render::VaryingSet4; @@ -116,12 +120,14 @@ private: OUTLINED_ID_SLOT, OUTLINE_PARAMS_SLOT = 0, - FRAME_TRANSFORM_SLOT + FRAME_TRANSFORM_SLOT, }; -#include "Outline_shared.slh" + struct OutlineConfiguration { + OutlineParameters _groups[MAX_GROUP_COUNT]; + }; - using OutlineConfigurationBuffer = gpu::StructBuffer; + using OutlineConfigurationBuffer = gpu::StructBuffer; static const gpu::PipelinePointer& getPipeline(bool isFilled); diff --git a/libraries/render-utils/src/Outline_shared.slh b/libraries/render-utils/src/Outline_shared.slh index 5ce21c85b4..98d803c28b 100644 --- a/libraries/render-utils/src/Outline_shared.slh +++ b/libraries/render-utils/src/Outline_shared.slh @@ -9,6 +9,10 @@ # define VEC4 vec4 #endif +#define GROUP_COUNT 7 +#define GROUP_ID_COLOR_COMPONENT_BITS 2 +#define GROUP_ID_COLOR_COMPONENT_MAX 3 + struct OutlineParameters { VEC3 _color; @@ -18,8 +22,6 @@ struct OutlineParameters float _fillOpacityUnoccluded; float _fillOpacityOccluded; - VEC4 _idColor; - float _threshold; int _blurKernelSize; float padding2; From 9ed5185a3ea86e8be67dc3c5d698103694d1808d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 17 Oct 2017 10:01:06 +0200 Subject: [PATCH 018/183] Multiple outline group config working --- libraries/render-utils/src/Outline.slh | 2 +- libraries/render-utils/src/OutlineEffect.cpp | 71 ++++--- libraries/render-utils/src/OutlineEffect.h | 121 ++++++----- libraries/render-utils/src/Outline_shared.slh | 4 +- .../developer/utilities/render/outline.qml | 188 ++++++++++-------- 5 files changed, 234 insertions(+), 152 deletions(-) diff --git a/libraries/render-utils/src/Outline.slh b/libraries/render-utils/src/Outline.slh index c58d1c7689..bc71cabf1e 100644 --- a/libraries/render-utils/src/Outline.slh +++ b/libraries/render-utils/src/Outline.slh @@ -53,7 +53,7 @@ vec4 computeGroupOutline(int centerGroupId, float centerDepth, int groupId, vec2 sceneDepth = -evalZeyeFromZdb(sceneDepth); // Are we occluded? - intensity = (sceneDepth < (centerDepth-LINEAR_DEPTH_BIAS)) ? groupParams._fillOpacityOccluded : groupParams._fillOpacityUnoccluded; + intensity = (sceneDepth < (centerDepth-LINEAR_DEPTH_BIAS)) ? groupParams._occludedFillOpacity : groupParams._unoccludedFillOpacity; return vec4(groupParams._color.rgb, intensity); <@else@> return vec4(0,0,0,0); diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 2cb19826f4..74a29e8237 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -215,6 +215,17 @@ void PrepareDrawOutline::run(const render::RenderContextPointer& renderContext, outputs = _primaryWithoutDepthBuffer; } +int DrawOutlineConfig::getGroupCount() const { + return Outline::MAX_GROUP_COUNT; +} + +void DrawOutlineConfig::setGroup(int value) { + assert(value >= 0 && value < Outline::MAX_GROUP_COUNT); + group = std::min(value, Outline::MAX_GROUP_COUNT); + group = std::max(group, 0); + emit dirty(); +} + gpu::PipelinePointer DrawOutline::_pipeline; gpu::PipelinePointer DrawOutline::_pipelineFilled; @@ -222,15 +233,34 @@ DrawOutline::DrawOutline() { } void DrawOutline::configure(const Config& config) { - _color = config.color; - _blurKernelSize = std::min(10, std::max(2, (int)floorf(config.width*2 + 0.5f))); - // Size is in normalized screen height. We decide that for outline width = 1, this is equal to 1/400. - _size = config.width / 400.f; - _fillOpacityUnoccluded = config.fillOpacityUnoccluded; - _fillOpacityOccluded = config.fillOpacityOccluded; - _threshold = config.glow ? 1.f : 1e-3f; - _intensity = config.intensity * (config.glow ? 2.f : 1.f); - _hasConfigurationChanged = true; + auto& configuration = _configuration.edit(); + const auto OPACITY_EPSILON = 5e-3f; + + bool someFilled = false; + bool isFilled; + + for (auto groupId = 0; groupId < MAX_GROUP_COUNT; groupId++) { + auto& dstGroupConfig = configuration._groups[groupId]; + auto& srcGroupConfig = config.groupParameters[groupId]; + + dstGroupConfig._color = srcGroupConfig.color; + dstGroupConfig._intensity = srcGroupConfig.intensity * (srcGroupConfig.glow ? 2.f : 1.f); + dstGroupConfig._unoccludedFillOpacity = srcGroupConfig.unoccludedFillOpacity; + dstGroupConfig._occludedFillOpacity = srcGroupConfig.occludedFillOpacity; + dstGroupConfig._threshold = srcGroupConfig.glow ? 1.f : 1e-3f; + dstGroupConfig._blurKernelSize = std::min(10, std::max(2, (int)floorf(srcGroupConfig.width * 2 + 0.5f))); + // Size is in normalized screen height. We decide that for outline width = 1, this is equal to 1/400. + _sizes[groupId] = srcGroupConfig.width / 400.0f; + + isFilled = (srcGroupConfig.unoccludedFillOpacity > OPACITY_EPSILON || srcGroupConfig.occludedFillOpacity > OPACITY_EPSILON); + someFilled = someFilled || isFilled; + } + + if (someFilled) { + _mode = M_SOME_FILLED; + } else { + _mode = M_ALL_UNFILLED; + } } void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { @@ -245,27 +275,20 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I auto framebufferSize = glm::ivec2(outlinedDepthTexture->getDimensions()); if (sceneDepthBuffer) { - const auto OPACITY_EPSILON = 5e-3f; - auto pipeline = getPipeline(_fillOpacityUnoccluded>OPACITY_EPSILON || _fillOpacityOccluded>OPACITY_EPSILON); + auto pipeline = getPipeline(); auto args = renderContext->args; - if (_hasConfigurationChanged) + if (_framebufferSize != framebufferSize) { auto& configuration = _configuration.edit(); for (auto groupId = 0; groupId < MAX_GROUP_COUNT; groupId++) { auto& groupConfig = configuration._groups[groupId]; - groupConfig._color = _color; - groupConfig._intensity = _intensity; - groupConfig._fillOpacityUnoccluded = _fillOpacityUnoccluded; - groupConfig._fillOpacityOccluded = _fillOpacityOccluded; - groupConfig._threshold = _threshold; - groupConfig._blurKernelSize = _blurKernelSize; - groupConfig._size.x = (_size * framebufferSize.y) / framebufferSize.x; - groupConfig._size.y = _size; + groupConfig._size.x = (_sizes[groupId] * framebufferSize.y) / framebufferSize.x; + groupConfig._size.y = _sizes[groupId]; } - _hasConfigurationChanged = false; + _framebufferSize = framebufferSize; } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { @@ -292,7 +315,7 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I } } -const gpu::PipelinePointer& DrawOutline::getPipeline(bool isFilled) { +const gpu::PipelinePointer& DrawOutline::getPipeline() { if (!_pipeline) { auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); auto ps = gpu::Shader::createPixel(std::string(Outline_frag)); @@ -316,7 +339,7 @@ const gpu::PipelinePointer& DrawOutline::getPipeline(bool isFilled) { gpu::Shader::makeProgram(*program, slotBindings); _pipelineFilled = gpu::Pipeline::create(program, state); } - return isFilled ? _pipelineFilled : _pipeline; + return _mode == M_SOME_FILLED ? _pipelineFilled : _pipeline; } DebugOutline::DebugOutline() { @@ -480,7 +503,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende } DrawOutlineMask::Groups sortedBounds; - for (auto i = 0; i < DrawOutline::MAX_GROUP_COUNT; i++) { + for (auto i = 0; i < Outline::MAX_GROUP_COUNT; i++) { const auto groupItems = groups[i]; const auto outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", groupItems); const auto outlinedItems = task.addJob("OutlineMetaToSubItems", outlinedItemIDs, true); diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index 6e4c0a18a8..bc10fc5e41 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -60,41 +60,8 @@ private: }; -class DrawOutlineConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(bool glow MEMBER glow NOTIFY dirty) - Q_PROPERTY(float width MEMBER width NOTIFY dirty) - Q_PROPERTY(float intensity MEMBER intensity NOTIFY dirty) - Q_PROPERTY(float colorR READ getColorR WRITE setColorR NOTIFY dirty) - Q_PROPERTY(float colorG READ getColorG WRITE setColorG NOTIFY dirty) - Q_PROPERTY(float colorB READ getColorB WRITE setColorB NOTIFY dirty) - Q_PROPERTY(float fillOpacityUnoccluded MEMBER fillOpacityUnoccluded NOTIFY dirty) - Q_PROPERTY(float fillOpacityOccluded MEMBER fillOpacityOccluded NOTIFY dirty) - -public: - - void setColorR(float value) { color.r = value; emit dirty(); } - float getColorR() const { return color.r; } - - void setColorG(float value) { color.g = value; emit dirty(); } - float getColorG() const { return color.g; } - - void setColorB(float value) { color.b = value; emit dirty(); } - float getColorB() const { return color.b; } - - glm::vec3 color{ 1.f, 0.7f, 0.2f }; - float width{ 2.0f }; - float intensity{ 0.9f }; - float fillOpacityUnoccluded{ 0.0f }; - float fillOpacityOccluded{ 0.0f }; - bool glow{ false }; - -signals: - void dirty(); -}; - -class DrawOutline { -private: +class Outline { +protected: #include "Outline_shared.slh" @@ -102,6 +69,68 @@ public: enum { MAX_GROUP_COUNT = GROUP_COUNT }; +}; + +class DrawOutlineConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(int group MEMBER group WRITE setGroup NOTIFY dirty); + Q_PROPERTY(bool glow READ isGlow WRITE setGlow NOTIFY dirty) + Q_PROPERTY(float width READ getWidth WRITE setWidth NOTIFY dirty) + Q_PROPERTY(float intensity READ getIntensity WRITE setIntensity NOTIFY dirty) + Q_PROPERTY(float colorR READ getColorR WRITE setColorR NOTIFY dirty) + Q_PROPERTY(float colorG READ getColorG WRITE setColorG NOTIFY dirty) + Q_PROPERTY(float colorB READ getColorB WRITE setColorB NOTIFY dirty) + Q_PROPERTY(float unoccludedFillOpacity READ getUnoccludedFillOpacity WRITE setUnoccludedFillOpacity NOTIFY dirty) + Q_PROPERTY(float occludedFillOpacity READ getOccludedFillOpacity WRITE setOccludedFillOpacity NOTIFY dirty) + +public: + + struct GroupParameters { + glm::vec3 color{ 1.f, 0.7f, 0.2f }; + float width{ 2.0f }; + float intensity{ 0.9f }; + float unoccludedFillOpacity{ 0.0f }; + float occludedFillOpacity{ 0.0f }; + bool glow{ false }; + }; + + int getGroupCount() const; + + void setColorR(float value) { groupParameters[group].color.r = value; emit dirty(); } + float getColorR() const { return groupParameters[group].color.r; } + + void setColorG(float value) { groupParameters[group].color.g = value; emit dirty(); } + float getColorG() const { return groupParameters[group].color.g; } + + void setColorB(float value) { groupParameters[group].color.b = value; emit dirty(); } + float getColorB() const { return groupParameters[group].color.b; } + + void setGlow(bool value) { groupParameters[group].glow = value; emit dirty(); } + bool isGlow() const { return groupParameters[group].glow; } + + void setWidth(float value) { groupParameters[group].width = value; emit dirty(); } + float getWidth() const { return groupParameters[group].width; } + + void setIntensity(float value) { groupParameters[group].intensity = value; emit dirty(); } + float getIntensity() const { return groupParameters[group].intensity; } + + void setUnoccludedFillOpacity(float value) { groupParameters[group].unoccludedFillOpacity = value; emit dirty(); } + float getUnoccludedFillOpacity() const { return groupParameters[group].unoccludedFillOpacity; } + + void setOccludedFillOpacity(float value) { groupParameters[group].occludedFillOpacity = value; emit dirty(); } + float getOccludedFillOpacity() const { return groupParameters[group].occludedFillOpacity; } + + void setGroup(int value); + + int group{ 0 }; + GroupParameters groupParameters[Outline::MAX_GROUP_COUNT]; + +signals: + void dirty(); +}; + +class DrawOutline : public Outline { +public: using Inputs = render::VaryingSet4; using Config = DrawOutlineConfig; @@ -127,27 +156,27 @@ private: OutlineParameters _groups[MAX_GROUP_COUNT]; }; + enum Mode { + M_ALL_UNFILLED, + M_SOME_FILLED, + }; + using OutlineConfigurationBuffer = gpu::StructBuffer; - static const gpu::PipelinePointer& getPipeline(bool isFilled); + const gpu::PipelinePointer& getPipeline(); static gpu::PipelinePointer _pipeline; static gpu::PipelinePointer _pipelineFilled; OutlineConfigurationBuffer _configuration; - glm::vec3 _color; - float _size; - int _blurKernelSize; - float _intensity; - float _fillOpacityUnoccluded; - float _fillOpacityOccluded; - float _threshold; - bool _hasConfigurationChanged{ true }; + glm::ivec2 _framebufferSize{ 0,0 }; + Mode _mode{ M_ALL_UNFILLED }; + float _sizes[MAX_GROUP_COUNT]; }; class DrawOutlineTask { public: - using Groups = render::VaryingArray; + using Groups = render::VaryingArray; using Inputs = render::VaryingSet4; using Config = render::Task::Config; using JobModel = render::Task::ModelI; @@ -165,7 +194,7 @@ private: class DrawOutlineMask { public: - using Groups = render::VaryingArray; + using Groups = render::VaryingArray; using Inputs = render::VaryingSet2; // Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer using Outputs = OutlineRessourcesPointer; diff --git a/libraries/render-utils/src/Outline_shared.slh b/libraries/render-utils/src/Outline_shared.slh index 98d803c28b..bda67c49d6 100644 --- a/libraries/render-utils/src/Outline_shared.slh +++ b/libraries/render-utils/src/Outline_shared.slh @@ -19,8 +19,8 @@ struct OutlineParameters float _intensity; VEC2 _size; - float _fillOpacityUnoccluded; - float _fillOpacityOccluded; + float _unoccludedFillOpacity; + float _occludedFillOpacity; float _threshold; int _blurKernelSize; diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index 1b5cbf6e1c..1270c696d1 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -20,6 +20,24 @@ Item { Column { spacing: 8 + ComboBox { + id: groupBox + model: ["Group 0", "Group 1", "Group 2", "Group 3", "Group 4"] + Timer { + id: postpone + interval: 100; running: false; repeat: false + onTriggered: { paramWidgetLoader.sourceComponent = paramWidgets } + } + onCurrentIndexChanged: { + // This is a hack to be sure the widgets below properly reflect the change of category: delete the Component + // by setting the loader source to Null and then recreate it 100ms later + root.drawConfig["group"] = currentIndex + paramWidgetLoader.sourceComponent = undefined; + postpone.interval = 100 + postpone.start() + } + } + CheckBox { text: "View Mask" checked: root.debugConfig["viewMask"] @@ -27,93 +45,105 @@ Item { root.debugConfig["viewMask"] = checked; } } - CheckBox { - text: "Glow" - checked: root.drawConfig["glow"] - onCheckedChanged: { - root.drawConfig["glow"] = checked; - } - } - ConfigSlider { - label: "Width" - integral: false - config: root.drawConfig - property: "width" - max: 15.0 - min: 0.0 - width: 280 - } - ConfigSlider { - label: "Intensity" - integral: false - config: root.drawConfig - property: "intensity" - max: 1.0 - min: 0.0 - width: 280 - } - GroupBox { - title: "Color" - width: 280 + Component { + id: paramWidgets Column { spacing: 8 + CheckBox { + text: "Glow" + checked: root.drawConfig["glow"] + onCheckedChanged: { + drawConfig["glow"] = checked; + } + } + ConfigSlider { + label: "Width" + integral: false + config: root.drawConfig + property: "width" + max: 15.0 + min: 0.0 + width: 280 + } + ConfigSlider { + label: "Intensity" + integral: false + config: root.drawConfig + property: "intensity" + max: 1.0 + min: 0.0 + width: 280 + } - ConfigSlider { - label: "Red" - integral: false - config: root.drawConfig - property: "colorR" - max: 1.0 - min: 0.0 - width: 270 - } - ConfigSlider { - label: "Green" - integral: false - config: root.drawConfig - property: "colorG" - max: 1.0 - min: 0.0 - width: 270 - } - ConfigSlider { - label: "Blue" - integral: false - config: root.drawConfig - property: "colorB" - max: 1.0 - min: 0.0 - width: 270 + GroupBox { + title: "Color" + width: 280 + Column { + spacing: 8 + + ConfigSlider { + label: "Red" + integral: false + config: root.drawConfig + property: "colorR" + max: 1.0 + min: 0.0 + width: 270 + } + ConfigSlider { + label: "Green" + integral: false + config: root.drawConfig + property: "colorG" + max: 1.0 + min: 0.0 + width: 270 + } + ConfigSlider { + label: "Blue" + integral: false + config: root.drawConfig + property: "colorB" + max: 1.0 + min: 0.0 + width: 270 + } + } + } + + GroupBox { + title: "Fill Opacity" + width: 280 + Column { + spacing: 8 + + ConfigSlider { + label: "Unoccluded" + integral: false + config: root.drawConfig + property: "fillOpacityUnoccluded" + max: 1.0 + min: 0.0 + width: 270 + } + ConfigSlider { + label: "Occluded" + integral: false + config: root.drawConfig + property: "fillOpacityOccluded" + max: 1.0 + min: 0.0 + width: 270 + } + } } } } - GroupBox { - title: "Fill Opacity" - width: 280 - Column { - spacing: 8 - - ConfigSlider { - label: "Unoccluded" - integral: false - config: root.drawConfig - property: "fillOpacityUnoccluded" - max: 1.0 - min: 0.0 - width: 270 - } - ConfigSlider { - label: "Occluded" - integral: false - config: root.drawConfig - property: "fillOpacityOccluded" - max: 1.0 - min: 0.0 - width: 270 - } - } + Loader { + id: paramWidgetLoader + sourceComponent: paramWidgets } } } From 76589316dfef0f308355fc7a387ce6a4b20b7982 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 17 Oct 2017 10:24:05 +0200 Subject: [PATCH 019/183] Working debug script with multiple selection --- .../src/ui/overlays/ContextOverlayInterface.h | 2 +- .../utilities/render/debugOutline.js | 99 ++++++++++++++++++- .../developer/utilities/render/outline.qml | 4 +- 3 files changed, 101 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index 2a96ea3d3e..28e3707f99 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -49,7 +49,7 @@ class ContextOverlayInterface : public QObject, public Dependency { public: enum { - MAX_HIGHLIGHT_COUNT = 4 + MAX_HIGHLIGHT_COUNT = 5 }; ContextOverlayInterface(); diff --git a/scripts/developer/utilities/render/debugOutline.js b/scripts/developer/utilities/render/debugOutline.js index e333ab5869..ac75197933 100644 --- a/scripts/developer/utilities/render/debugOutline.js +++ b/scripts/developer/utilities/render/debugOutline.js @@ -17,4 +17,101 @@ var window = new OverlayWindow({ width: 285, height: 370, }); -window.closed.connect(function() { Script.stop(); }); \ No newline at end of file +window.closed.connect(function() { Script.stop(); }); + +"use strict"; + +// Created by Sam Gondelman on 9/7/2017 +// Copyright 2017 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 + +(function() { // BEGIN LOCAL_SCOPE + +var END_DIMENSIONS = { + x: 0.15, + y: 0.15, + z: 0.15 +}; +var COLOR = {red: 97, green: 247, blue: 255}; +var end = { + type: "sphere", + dimensions: END_DIMENSIONS, + color: COLOR, + ignoreRayIntersection: true, + alpha: 1.0, + visible: true +} + +var COLOR2 = {red: 247, green: 97, blue: 255}; +var end2 = { + type: "sphere", + dimensions: END_DIMENSIONS, + color: COLOR2, + ignoreRayIntersection: true, + alpha: 1.0, + visible: true +} + +var renderStates = [{name: "test", end: end}]; +var defaultRenderStates = [{name: "test", distance: 20.0, end: end2}]; + +var ray = LaserPointers.createLaserPointer({ + joint: "Mouse", + filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS | RayPick.PICK_AVATARS | RayPick.PICK_INVISIBLE | RayPick.PICK_NONCOLLIDABLE, + renderStates: renderStates, + defaultRenderStates: defaultRenderStates, + enabled: true +}); + +function cleanup() { + LaserPointers.removeLaserPointer(ray); +} +Script.scriptEnding.connect(cleanup); + +var prevID = 0; +var prevType = ""; +function update() { + // you have to do this repeatedly because there's a bug but I'll fix it + LaserPointers.setRenderState(ray, "test"); + + var result = LaserPointers.getPrevRayPickResult(ray); + var selectionName = "contextOverlayHighlightList" + var outlineGroupIndex = Render.getConfig("RenderMainView.OutlineEffect").group + + if (outlineGroupIndex>0) { + selectionName += outlineGroupIndex + } + + if (result.type != RayPick.INTERSECTED_NONE) { + if (result.objectID != prevID) { + if (prevID != 0) { + Selection.removeFromSelectedItemsList(selectionName, prevType, prevID) + } + + var typeName = "" + if (result.type == RayPick.INTERSECTED_ENTITY) { + typeName = "entity" + } else if (result.type == RayPick.INTERSECTED_OVERLAY) { + typeName = "overlay" + } else if (result.type == RayPick.INTERSECTED_AVATAR) { + typeName = "avatar" + } + + Selection.addToSelectedItemsList(selectionName, typeName, result.objectID) + //print("type: " + result.type + ", id: " + result.objectID); + + prevID = result.objectID; + prevType = typeName; + } + } else { + if (prevID != 0) { + Selection.removeFromSelectedItemsList(selectionName, prevType, prevID) + } + prevID = 0; + } +} +Script.update.connect(update); + +}()); // END LOCAL_SCOPE \ No newline at end of file diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index 1270c696d1..d62e3b8899 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -122,7 +122,7 @@ Item { label: "Unoccluded" integral: false config: root.drawConfig - property: "fillOpacityUnoccluded" + property: "unoccludedFillOpacity" max: 1.0 min: 0.0 width: 270 @@ -131,7 +131,7 @@ Item { label: "Occluded" integral: false config: root.drawConfig - property: "fillOpacityOccluded" + property: "occludedFillOpacity" max: 1.0 min: 0.0 width: 270 From 25b3549e042f9e21438d0236c4610a641c4c5bb3 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 18 Oct 2017 15:00:53 +0200 Subject: [PATCH 020/183] Working multiple outlines except debugging scripts which applies config to all outlines and graphics bug when filled --- .../ui/overlays/ContextOverlayInterface.cpp | 2 +- .../src/ui/overlays/ContextOverlayInterface.h | 6 +- libraries/render-utils/src/Outline.slh | 81 +--- libraries/render-utils/src/OutlineEffect.cpp | 423 ++++++------------ libraries/render-utils/src/OutlineEffect.h | 178 +++----- libraries/render-utils/src/Outline_shared.slh | 4 - .../render-utils/src/RenderDeferredTask.cpp | 2 +- libraries/render-utils/src/model_outline.slf | 21 - .../render-utils/src/model_outline_fade.slf | 31 -- libraries/render/src/render/Scene.h | 5 + .../utilities/render/debugOutline.js | 12 +- .../developer/utilities/render/outline.qml | 12 +- 12 files changed, 251 insertions(+), 526 deletions(-) delete mode 100644 libraries/render-utils/src/model_outline.slf delete mode 100644 libraries/render-utils/src/model_outline_fade.slf diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index f677dc6550..3a3026d5ae 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -36,7 +36,7 @@ ContextOverlayInterface::ContextOverlayInterface() { _selectionToSceneHandlers[0].initialize("contextOverlayHighlightList"); connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandlers[0], &SelectionToSceneHandler::selectedItemsListChanged); - for (auto i = 1; i < MAX_HIGHLIGHT_COUNT; i++) { + for (auto i = 1; i < render::Scene::MAX_OUTLINE_COUNT ; i++) { _selectionToSceneHandlers[i].initialize(QString("contextOverlayHighlightList")+QString::number(i)); connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandlers[i], &SelectionToSceneHandler::selectedItemsListChanged); } diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index 28e3707f99..3d33d2a802 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -48,10 +48,6 @@ class ContextOverlayInterface : public QObject, public Dependency { std::shared_ptr _contextOverlay { nullptr }; public: - enum { - MAX_HIGHLIGHT_COUNT = 5 - }; - ContextOverlayInterface(); Q_INVOKABLE QUuid getCurrentEntityWithContextOverlay() { return _currentEntityWithContextOverlay; } @@ -91,7 +87,7 @@ private: void deletingEntity(const EntityItemID& entityItemID); - SelectionToSceneHandler _selectionToSceneHandlers[MAX_HIGHLIGHT_COUNT]; + SelectionToSceneHandler _selectionToSceneHandlers[render::Scene::MAX_OUTLINE_COUNT]; }; #endif // hifi_ContextOverlayInterface_h diff --git a/libraries/render-utils/src/Outline.slh b/libraries/render-utils/src/Outline.slh index bc71cabf1e..fe9594cc12 100644 --- a/libraries/render-utils/src/Outline.slh +++ b/libraries/render-utils/src/Outline.slh @@ -16,13 +16,11 @@ <@include Outline_shared.slh@> uniform outlineParamsBuffer { - OutlineParameters groups[GROUP_COUNT]; + OutlineParameters params; }; uniform sampler2D sceneDepthMap; uniform sampler2D outlinedDepthMap; -uniform sampler2D outlinedIdMap; -uniform int enabledGroupsMask; in vec2 varTexCoord0; out vec4 outFragColor; @@ -33,52 +31,47 @@ const float OPACITY_EPSILON = 5e-3; <@func main(IS_FILLED)@> -int getGroupIndexFromColor(vec4 color) { - ivec4 id = ivec4(color * GROUP_ID_COLOR_COMPONENT_MAX) << ivec4(0, GROUP_ID_COLOR_COMPONENT_BITS, GROUP_ID_COLOR_COMPONENT_BITS*2, GROUP_ID_COLOR_COMPONENT_BITS*3); - return (id.r | id.g | id.b | id.a) - 1; -} - -vec4 computeGroupOutline(int centerGroupId, float centerDepth, int groupId, vec2 texCoord) { +void main(void) { + // We offset by half a texel to be centered on the depth sample. If we don't do this + // the blur will have a different width between the left / right sides and top / bottom + // sides of the silhouette + vec2 halfTexel = getInvWidthHeight() / 2; + vec2 texCoord0 = varTexCoord0+halfTexel; + float outlinedDepth = texture(outlinedDepthMap, texCoord0).x; float intensity = 0.0; - if (centerGroupId==groupId && centerDepth < FAR_Z) { - // We're on the outlined object, thus no outline to do! + if (outlinedDepth < FAR_Z) { + // We're not on the far plane so we are on the outlined object, thus no outline to do! <@if IS_FILLED@> - OutlineParameters groupParams = groups[groupId]; - // But we need to fill the interior - float sceneDepth = texture(sceneDepthMap, texCoord).x; + float sceneDepth = texture(sceneDepthMap, texCoord0).x; // Transform to linear depth for better precision - centerDepth = -evalZeyeFromZdb(centerDepth); + outlinedDepth = -evalZeyeFromZdb(outlinedDepth); sceneDepth = -evalZeyeFromZdb(sceneDepth); // Are we occluded? - intensity = (sceneDepth < (centerDepth-LINEAR_DEPTH_BIAS)) ? groupParams._occludedFillOpacity : groupParams._unoccludedFillOpacity; - return vec4(groupParams._color.rgb, intensity); + intensity = sceneDepth < (outlinedDepth-LINEAR_DEPTH_BIAS) ? params._occludedFillOpacity : params._unoccludedFillOpacity; <@else@> - return vec4(0,0,0,0); + discard; <@endif@> } else { - OutlineParameters groupParams = groups[groupId]; float weight = 0.0; - vec2 deltaUv = groupParams._size / groupParams._blurKernelSize; - vec2 lineStartUv = texCoord - groupParams._size / 2.0; + vec2 deltaUv = params._size / params._blurKernelSize; + vec2 lineStartUv = texCoord0 - params._size / 2.0; vec2 uv; int x; int y; - for (y=0 ; y=0.0 && uv.y<=1.0) { - for (x=0 ; x=0.0 && uv.x<=1.0) { - vec4 outlinedIdColor = texture(outlinedIdMap, uv); - float outlinedDepth = texture(outlinedDepthMap, uv).x; - int outlinedId = getGroupIndexFromColor(outlinedIdColor); - intensity += (outlinedDepth diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 74a29e8237..d00819d0f2 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -18,6 +18,7 @@ #include "gpu/Context.h" #include "gpu/StandardShaderLib.h" +#include #include "surfaceGeometry_copyDepth_frag.h" #include "debug_deferred_buffer_vert.h" @@ -30,22 +31,29 @@ using namespace render; OutlineRessources::OutlineRessources() { } -void OutlineRessources::update(const gpu::TexturePointer& colorBuffer) { +void OutlineRessources::update(const gpu::FramebufferPointer& primaryFrameBuffer) { + auto newFrameSize = glm::ivec2(primaryFrameBuffer->getSize()); + // If the depth buffer or size changed, we need to delete our FBOs and recreate them at the // new correct dimensions. - if (_depthTexture) { - auto newFrameSize = glm::ivec2(colorBuffer->getDimensions()); + if (_depthFrameBuffer) { if (_frameSize != newFrameSize) { _frameSize = newFrameSize; clear(); } } + if (!_colorFrameBuffer) { + if (_frameSize != newFrameSize) { + _frameSize = newFrameSize; + // Failing to recreate this frame buffer when the screen has been resized creates a bug on Mac + _colorFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithoutDepth")); + _colorFrameBuffer->setRenderBuffer(0, primaryFrameBuffer->getRenderBuffer(0)); + } + } } void OutlineRessources::clear() { - _frameBuffer.reset(); - _depthTexture.reset(); - _idTexture.reset(); + _depthFrameBuffer.reset(); } void OutlineRessources::allocate() { @@ -53,177 +61,95 @@ void OutlineRessources::allocate() { auto width = _frameSize.x; auto height = _frameSize.y; auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); - - _idTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_2, width, height)); - _depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(depthFormat, width, height)); + auto depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(depthFormat, width, height)); - _frameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); - _frameBuffer->setDepthStencilBuffer(_depthTexture, depthFormat); - _frameBuffer->setRenderBuffer(0, _idTexture); + _depthFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); + _depthFrameBuffer->setDepthStencilBuffer(depthTexture, depthFormat); } -gpu::FramebufferPointer OutlineRessources::getFramebuffer() { - if (!_frameBuffer) { +gpu::FramebufferPointer OutlineRessources::getDepthFramebuffer() { + if (!_depthFrameBuffer) { allocate(); } - return _frameBuffer; + return _depthFrameBuffer; } gpu::TexturePointer OutlineRessources::getDepthTexture() { - if (!_depthTexture) { - allocate(); - } - return _depthTexture; -} - -gpu::TexturePointer OutlineRessources::getIdTexture() { - if (!_idTexture) { - allocate(); - } - return _idTexture; -} - -glm::vec4 encodeIdToColor(unsigned int id) { - union { - struct { - unsigned int r : 2; - unsigned int g : 2; - unsigned int b : 2; - unsigned int a : 2; - }; - unsigned char id; - } groupId; - - static_assert(GROUP_ID_COLOR_COMPONENT_BITS == 2, "Assuming two bits per component contrary to GLSL shader code. See Outline_shared.slh"); - - assert(id < 254); - groupId.id = id+1; - - glm::vec4 idColor{ groupId.r, groupId.g, groupId.b, groupId.a }; - - // Normalize. Since we put 2 bits into each color component, each component has a maximum - // value of 3. - idColor /= GROUP_ID_COLOR_COMPONENT_MAX; - return idColor; -} - -void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) { - assert(renderContext->args); - assert(renderContext->args->hasViewFrustum()); - auto& groups = inputs.get0(); - auto& deferredFrameBuffer = inputs.get1(); - - RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder; - auto hasOutline = false; - - if (!_outlineRessources) { - _outlineRessources = std::make_shared(); - } - _outlineRessources->update(deferredFrameBuffer->getDeferredColorTexture()); - - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - args->_batch = &batch; - - auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); - auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); - auto colorLoc = maskPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color"); - auto skinnedColorLoc = maskSkinnedPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color"); - unsigned int groupId = 0; - - for (auto& inShapeBounds : groups) { - if (!inShapeBounds.isNull()) { - auto& inShapes = inShapeBounds.get(); - - if (!inShapes.empty()) { - if (!hasOutline) { - batch.setFramebuffer(_outlineRessources->getFramebuffer()); - // Clear it only if it hasn't been done before - batch.clearFramebuffer( - gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, - vec4(0.0f, 0.0f, 0.0f, 0.0f), 1.0f, 0, false); - - // Setup camera, projection and viewport for all items - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - - glm::mat4 projMat; - Transform viewMat; - args->getViewFrustum().evalProjectionMatrix(projMat); - args->getViewFrustum().evalViewTransform(viewMat); - - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - hasOutline = true; - } - - std::vector skinnedShapeKeys{}; - // Encode group id in quantized color - glm::vec4 idColor = encodeIdToColor(groupId); - - // Iterate through all inShapes and render the unskinned - args->_shapePipeline = maskPipeline; - batch.setPipeline(maskPipeline->pipeline); - batch._glUniform4f(colorLoc, idColor.r, idColor.g, idColor.b, idColor.a); - for (auto items : inShapes) { - if (items.first.isSkinned()) { - skinnedShapeKeys.push_back(items.first); - } else { - renderItems(renderContext, items.second); - } - } - - // Reiterate to render the skinned - args->_shapePipeline = maskSkinnedPipeline; - batch.setPipeline(maskSkinnedPipeline->pipeline); - batch._glUniform4f(skinnedColorLoc, idColor.r, idColor.g, idColor.b, idColor.a); - for (const auto& key : skinnedShapeKeys) { - renderItems(renderContext, inShapes.at(key)); - } - } - } - - ++groupId; - } - - args->_shapePipeline = nullptr; - args->_batch = nullptr; - }); - - if (hasOutline) { - output = _outlineRessources; - } else { - output = nullptr; - } + return getDepthFramebuffer()->getDepthStencilBuffer(); } PrepareDrawOutline::PrepareDrawOutline() { - + _ressources = std::make_shared(); } void PrepareDrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { auto destinationFrameBuffer = inputs; - auto framebufferSize = destinationFrameBuffer->getSize(); - if (!_primaryWithoutDepthBuffer || framebufferSize != _frameBufferSize) { - // Failing to recreate this frame buffer when the screen has been resized creates a bug on Mac - _primaryWithoutDepthBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithoutDepth")); - _primaryWithoutDepthBuffer->setRenderBuffer(0, destinationFrameBuffer->getRenderBuffer(0)); - _frameBufferSize = framebufferSize; + _ressources->update(destinationFrameBuffer); + outputs = _ressources; +} + +void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { + assert(renderContext->args); + assert(renderContext->args->hasViewFrustum()); + auto& inShapes = inputs.get0(); + + if (!inShapes.empty()) { + auto ressources = inputs.get1(); + + RenderArgs* args = renderContext->args; + ShapeKey::Builder defaultKeyBuilder; + + outputs = args->_viewport; + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; + + auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); + auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); + + batch.setFramebuffer(ressources->getDepthFramebuffer()); + batch.clearDepthFramebuffer(1.0f); + + // Setup camera, projection and viewport for all items + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + + std::vector skinnedShapeKeys{}; + + // Iterate through all inShapes and render the unskinned + args->_shapePipeline = maskPipeline; + batch.setPipeline(maskPipeline->pipeline); + for (auto items : inShapes) { + if (items.first.isSkinned()) { + skinnedShapeKeys.push_back(items.first); + } else { + renderItems(renderContext, items.second); + } + } + + // Reiterate to render the skinned + args->_shapePipeline = maskSkinnedPipeline; + batch.setPipeline(maskSkinnedPipeline->pipeline); + for (const auto& key : skinnedShapeKeys) { + renderItems(renderContext, inShapes.at(key)); + } + + args->_shapePipeline = nullptr; + args->_batch = nullptr; + }); + } else { + // Outline rect should be null as there are no outlined shapes + outputs = glm::ivec4(0, 0, 0, 0); } - - outputs = _primaryWithoutDepthBuffer; -} - -int DrawOutlineConfig::getGroupCount() const { - return Outline::MAX_GROUP_COUNT; -} - -void DrawOutlineConfig::setGroup(int value) { - assert(value >= 0 && value < Outline::MAX_GROUP_COUNT); - group = std::min(value, Outline::MAX_GROUP_COUNT); - group = std::max(group, 0); - emit dirty(); } gpu::PipelinePointer DrawOutline::_pipeline; @@ -236,41 +162,28 @@ void DrawOutline::configure(const Config& config) { auto& configuration = _configuration.edit(); const auto OPACITY_EPSILON = 5e-3f; - bool someFilled = false; - bool isFilled; + configuration._color = config.color; + configuration._intensity = config.intensity * (config.glow ? 2.f : 1.f); + configuration._unoccludedFillOpacity = config.unoccludedFillOpacity; + configuration._occludedFillOpacity = config.occludedFillOpacity; + configuration._threshold = config.glow ? 1.f : 1e-3f; + configuration._blurKernelSize = std::min(10, std::max(2, (int)floorf(config.width * 3 + 0.5f))); + // Size is in normalized screen height. We decide that for outline width = 1, this is equal to 1/400. + _size = config.width / 400.0f; + configuration._size.x = (_size * _framebufferSize.y) / _framebufferSize.x; + configuration._size.y = _size; - for (auto groupId = 0; groupId < MAX_GROUP_COUNT; groupId++) { - auto& dstGroupConfig = configuration._groups[groupId]; - auto& srcGroupConfig = config.groupParameters[groupId]; - - dstGroupConfig._color = srcGroupConfig.color; - dstGroupConfig._intensity = srcGroupConfig.intensity * (srcGroupConfig.glow ? 2.f : 1.f); - dstGroupConfig._unoccludedFillOpacity = srcGroupConfig.unoccludedFillOpacity; - dstGroupConfig._occludedFillOpacity = srcGroupConfig.occludedFillOpacity; - dstGroupConfig._threshold = srcGroupConfig.glow ? 1.f : 1e-3f; - dstGroupConfig._blurKernelSize = std::min(10, std::max(2, (int)floorf(srcGroupConfig.width * 2 + 0.5f))); - // Size is in normalized screen height. We decide that for outline width = 1, this is equal to 1/400. - _sizes[groupId] = srcGroupConfig.width / 400.0f; - - isFilled = (srcGroupConfig.unoccludedFillOpacity > OPACITY_EPSILON || srcGroupConfig.occludedFillOpacity > OPACITY_EPSILON); - someFilled = someFilled || isFilled; - } - - if (someFilled) { - _mode = M_SOME_FILLED; - } else { - _mode = M_ALL_UNFILLED; - } + _isFilled = (config.unoccludedFillOpacity > OPACITY_EPSILON || config.occludedFillOpacity > OPACITY_EPSILON); } void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { auto outlineFrameBuffer = inputs.get1(); + auto outlineRect = inputs.get4(); - if (outlineFrameBuffer) { + if (outlineFrameBuffer && outlineRect.z>0 && outlineRect.w>0) { auto sceneDepthBuffer = inputs.get2(); const auto frameTransform = inputs.get0(); auto outlinedDepthTexture = outlineFrameBuffer->getDepthTexture(); - auto outlinedIdTexture = outlineFrameBuffer->getIdTexture(); auto destinationFrameBuffer = inputs.get3(); auto framebufferSize = glm::ivec2(outlinedDepthTexture->getDimensions()); @@ -281,13 +194,8 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I if (_framebufferSize != framebufferSize) { auto& configuration = _configuration.edit(); - - for (auto groupId = 0; groupId < MAX_GROUP_COUNT; groupId++) { - auto& groupConfig = configuration._groups[groupId]; - - groupConfig._size.x = (_sizes[groupId] * framebufferSize.y) / framebufferSize.x; - groupConfig._size.y = _sizes[groupId]; - } + configuration._size.x = (_size * framebufferSize.y) / framebufferSize.x; + configuration._size.y = _size; _framebufferSize = framebufferSize; } @@ -301,14 +209,10 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); batch.setPipeline(pipeline); - auto enabledGroupsLoc = pipeline->getProgram()->getUniforms().findLocation("enabledGroupsMask"); - batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer()); batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getPrimaryDepthTexture()); batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthTexture); - batch.setResourceTexture(OUTLINED_ID_SLOT, outlinedIdTexture); - batch._glUniform1i(enabledGroupsLoc, 1); batch.draw(gpu::TRIANGLE_STRIP, 4); }); } @@ -326,7 +230,6 @@ const gpu::PipelinePointer& DrawOutline::getPipeline() { slotBindings.insert(gpu::Shader::Binding("deferredFrameTransformBuffer", FRAME_TRANSFORM_SLOT)); slotBindings.insert(gpu::Shader::Binding("sceneDepthMap", SCENE_DEPTH_SLOT)); slotBindings.insert(gpu::Shader::Binding("outlinedDepthMap", OUTLINED_DEPTH_SLOT)); - slotBindings.insert(gpu::Shader::Binding("outlinedIdMap", OUTLINED_ID_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); @@ -339,19 +242,17 @@ const gpu::PipelinePointer& DrawOutline::getPipeline() { gpu::Shader::makeProgram(*program, slotBindings); _pipelineFilled = gpu::Pipeline::create(program, state); } - return _mode == M_SOME_FILLED ? _pipelineFilled : _pipeline; + return _isFilled ? _pipelineFilled : _pipeline; } DebugOutline::DebugOutline() { _geometryDepthId = DependencyManager::get()->allocateID(); - _geometryColorId = DependencyManager::get()->allocateID(); } DebugOutline::~DebugOutline() { auto geometryCache = DependencyManager::get(); if (geometryCache) { geometryCache->releaseID(_geometryDepthId); - geometryCache->releaseID(_geometryColorId); } } @@ -360,9 +261,9 @@ void DebugOutline::configure(const Config& config) { } void DebugOutline::run(const render::RenderContextPointer& renderContext, const Inputs& input) { - const auto outlineFramebuffer = input; + const auto outlineRessources = input; - if (_isDisplayEnabled && outlineFramebuffer) { + if (_isDisplayEnabled && outlineRessources) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; @@ -384,20 +285,10 @@ void DebugOutline::run(const render::RenderContextPointer& renderContext, const const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); batch.setPipeline(getDepthPipeline()); - batch.setResourceTexture(0, outlineFramebuffer->getDepthTexture()); - { - const glm::vec2 bottomLeft(-1.0f, -1.0f); - const glm::vec2 topRight(0.0f, 1.0f); - geometryBuffer->renderQuad(batch, bottomLeft, topRight, color, _geometryDepthId); - } - - batch.setPipeline(getIdPipeline()); - batch.setResourceTexture(0, outlineFramebuffer->getIdTexture()); - { - const glm::vec2 bottomLeft(0.0f, -1.0f); - const glm::vec2 topRight(1.0f, 1.0f); - geometryBuffer->renderQuad(batch, bottomLeft, topRight, color, _geometryColorId); - } + batch.setResourceTexture(0, outlineRessources->getDepthTexture()); + const glm::vec2 bottomLeft(-1.0f, -1.0f); + const glm::vec2 topRight(1.0f, 1.0f); + geometryBuffer->renderQuad(batch, bottomLeft, topRight, color, _geometryDepthId); batch.setResourceTexture(0, nullptr); }); @@ -439,27 +330,6 @@ void DebugOutline::initializePipelines() { _depthPipeline = gpu::Pipeline::create(program, state); } - - // ID shader - { - static const std::string ID_SHADER{ - "vec4 getFragmentColor() {" - " return texelFetch(albedoMap, ivec2(gl_FragCoord.xy), 0); " - "}" - }; - - auto fragmentShader = FRAGMENT_SHADER; - fragmentShader.replace(SOURCE_PLACEHOLDER_INDEX, SOURCE_PLACEHOLDER.size(), ID_SHADER); - - const auto ps = gpu::Shader::createPixel(fragmentShader); - const auto program = gpu::Shader::createProgram(vs, ps); - - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding("albedoMap", 0)); - gpu::Shader::makeProgram(*program, slotBindings); - - _idPipeline = gpu::Pipeline::create(program, state); - } } const gpu::PipelinePointer& DebugOutline::getDepthPipeline() { @@ -470,14 +340,6 @@ const gpu::PipelinePointer& DebugOutline::getDepthPipeline() { return _depthPipeline; } -const gpu::PipelinePointer& DebugOutline::getIdPipeline() { - if (!_idPipeline) { - initializePipelines(); - } - - return _idPipeline; -} - DrawOutlineTask::DrawOutlineTask() { } @@ -496,70 +358,63 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende ShapePlumberPointer shapePlumber = std::make_shared(); { auto state = std::make_shared(); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - state->setColorWriteMask(true, true, true, true); - + state->setDepthTest(true, true, gpu::LESS); + state->setColorWriteMask(false, false, false, false); initMaskPipelines(*shapePlumber, state); } - DrawOutlineMask::Groups sortedBounds; - for (auto i = 0; i < Outline::MAX_GROUP_COUNT; i++) { + // Prepare for outline group rendering. + const auto outlineRessources = task.addJob("PrepareOutline", primaryFramebuffer); + + for (auto i = 0; i < render::Scene::MAX_OUTLINE_COUNT; i++) { const auto groupItems = groups[i]; const auto outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", groupItems); const auto outlinedItems = task.addJob("OutlineMetaToSubItems", outlinedItemIDs, true); // Sort const auto sortedPipelines = task.addJob("OutlinePipelineSort", outlinedItems); - sortedBounds[i] = task.addJob("OutlineDepthSort", sortedPipelines); + const auto sortedBounds = task.addJob("OutlineDepthSort", sortedPipelines); + + // Draw depth of outlined objects in separate buffer + std::string name; + { + std::ostringstream stream; + stream << "OutlineMask" << i; + name = stream.str(); + } + const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedBounds, outlineRessources).asVarying(); + const auto outlinedRect = task.addJob(name, drawMaskInputs, shapePlumber); + + // Draw outline + { + std::ostringstream stream; + stream << "OutlineEffect" << i; + name = stream.str(); + } + const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlineRessources, sceneFrameBuffer, primaryFramebuffer, outlinedRect).asVarying(); + task.addJob(name, drawOutlineInputs); } - // Draw depth of outlined objects in separate buffer - const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedBounds, sceneFrameBuffer).asVarying(); - const auto outlinedFrameBuffer = task.addJob("OutlineMask", drawMaskInputs, shapePlumber); - - // Prepare for outline group rendering. - const auto destFrameBuffer = task.addJob("PrepareOutline", primaryFramebuffer); - - // Draw outline - const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, destFrameBuffer).asVarying(); - task.addJob("OutlineEffect", drawOutlineInputs); - // Debug outline - task.addJob("OutlineDebug", outlinedFrameBuffer); + task.addJob("OutlineDebug", outlineRessources); } #include "model_shadow_vert.h" -#include "model_shadow_fade_vert.h" #include "skin_model_shadow_vert.h" -#include "skin_model_shadow_fade_vert.h" -#include "model_outline_frag.h" -#include "model_outline_fade_frag.h" +#include "model_shadow_frag.h" void DrawOutlineTask::initMaskPipelines(render::ShapePlumber& shapePlumber, gpu::StatePointer state) { auto modelVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); - auto modelPixel = gpu::Shader::createPixel(std::string(model_outline_frag)); + auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel); shapePlumber.addPipeline( - ShapeKey::Filter::Builder().withoutSkinned().withoutFade(), + ShapeKey::Filter::Builder().withoutSkinned(), modelProgram, state); auto skinVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, modelPixel); shapePlumber.addPipeline( - ShapeKey::Filter::Builder().withSkinned().withoutFade(), + ShapeKey::Filter::Builder().withSkinned(), skinProgram, state); - - auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_shadow_fade_vert)); - auto modelFadePixel = gpu::Shader::createPixel(std::string(model_outline_fade_frag)); - gpu::ShaderPointer modelFadeProgram = gpu::Shader::createProgram(modelFadeVertex, modelFadePixel); - shapePlumber.addPipeline( - ShapeKey::Filter::Builder().withoutSkinned().withFade(), - modelFadeProgram, state); - - auto skinFadeVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_fade_vert)); - gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(skinFadeVertex, modelFadePixel); - shapePlumber.addPipeline( - ShapeKey::Filter::Builder().withSkinned().withFade(), - skinFadeProgram, state); } diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index bc10fc5e41..b1c2e3c3dd 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -20,12 +20,13 @@ class OutlineRessources { public: OutlineRessources(); - gpu::FramebufferPointer getFramebuffer(); - gpu::TexturePointer getIdTexture(); + gpu::FramebufferPointer getDepthFramebuffer(); gpu::TexturePointer getDepthTexture(); + gpu::FramebufferPointer getColorFramebuffer() { return _colorFrameBuffer; } + // Update the source framebuffer size which will drive the allocation of all the other resources. - void update(const gpu::TexturePointer& colorBuffer); + void update(const gpu::FramebufferPointer& primaryFrameBuffer); const glm::ivec2& getSourceFrameSize() const { return _frameSize; } protected: @@ -33,9 +34,8 @@ protected: void clear(); void allocate(); - gpu::FramebufferPointer _frameBuffer; - gpu::TexturePointer _depthTexture; - gpu::TexturePointer _idTexture; + gpu::FramebufferPointer _depthFrameBuffer; + gpu::FramebufferPointer _colorFrameBuffer; glm::ivec2 _frameSize; }; @@ -45,9 +45,8 @@ using OutlineRessourcesPointer = std::shared_ptr; class PrepareDrawOutline { public: using Inputs = gpu::FramebufferPointer; - using Outputs = gpu::FramebufferPointer; - using Config = render::Job::Config; - using JobModel = render::Job::ModelIO; + using Outputs = OutlineRessourcesPointer; + using JobModel = render::Job::ModelIO; PrepareDrawOutline(); @@ -55,84 +54,63 @@ public: private: - gpu::FramebufferPointer _primaryWithoutDepthBuffer; - gpu::Vec2u _frameBufferSize{ 0, 0 }; + OutlineRessourcesPointer _ressources; }; -class Outline { +class DrawOutlineMask { +public: + + using Inputs = render::VaryingSet2; + using Outputs = glm::ivec4; + using JobModel = render::Job::ModelIO; + + DrawOutlineMask(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); + protected: -#include "Outline_shared.slh" - -public: - enum { - MAX_GROUP_COUNT = GROUP_COUNT - }; + render::ShapePlumberPointer _shapePlumber; }; class DrawOutlineConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(int group MEMBER group WRITE setGroup NOTIFY dirty); - Q_PROPERTY(bool glow READ isGlow WRITE setGlow NOTIFY dirty) - Q_PROPERTY(float width READ getWidth WRITE setWidth NOTIFY dirty) - Q_PROPERTY(float intensity READ getIntensity WRITE setIntensity NOTIFY dirty) + Q_PROPERTY(bool glow MEMBER glow NOTIFY dirty) + Q_PROPERTY(float width MEMBER width NOTIFY dirty) + Q_PROPERTY(float intensity MEMBER intensity NOTIFY dirty) Q_PROPERTY(float colorR READ getColorR WRITE setColorR NOTIFY dirty) Q_PROPERTY(float colorG READ getColorG WRITE setColorG NOTIFY dirty) Q_PROPERTY(float colorB READ getColorB WRITE setColorB NOTIFY dirty) - Q_PROPERTY(float unoccludedFillOpacity READ getUnoccludedFillOpacity WRITE setUnoccludedFillOpacity NOTIFY dirty) - Q_PROPERTY(float occludedFillOpacity READ getOccludedFillOpacity WRITE setOccludedFillOpacity NOTIFY dirty) + Q_PROPERTY(float unoccludedFillOpacity MEMBER unoccludedFillOpacity NOTIFY dirty) + Q_PROPERTY(float occludedFillOpacity MEMBER occludedFillOpacity NOTIFY dirty) public: - struct GroupParameters { - glm::vec3 color{ 1.f, 0.7f, 0.2f }; - float width{ 2.0f }; - float intensity{ 0.9f }; - float unoccludedFillOpacity{ 0.0f }; - float occludedFillOpacity{ 0.0f }; - bool glow{ false }; - }; + void setColorR(float value) { color.r = value; emit dirty(); } + float getColorR() const { return color.r; } - int getGroupCount() const; + void setColorG(float value) { color.g = value; emit dirty(); } + float getColorG() const { return color.g; } - void setColorR(float value) { groupParameters[group].color.r = value; emit dirty(); } - float getColorR() const { return groupParameters[group].color.r; } + void setColorB(float value) { color.b = value; emit dirty(); } + float getColorB() const { return color.b; } - void setColorG(float value) { groupParameters[group].color.g = value; emit dirty(); } - float getColorG() const { return groupParameters[group].color.g; } - - void setColorB(float value) { groupParameters[group].color.b = value; emit dirty(); } - float getColorB() const { return groupParameters[group].color.b; } - - void setGlow(bool value) { groupParameters[group].glow = value; emit dirty(); } - bool isGlow() const { return groupParameters[group].glow; } - - void setWidth(float value) { groupParameters[group].width = value; emit dirty(); } - float getWidth() const { return groupParameters[group].width; } - - void setIntensity(float value) { groupParameters[group].intensity = value; emit dirty(); } - float getIntensity() const { return groupParameters[group].intensity; } - - void setUnoccludedFillOpacity(float value) { groupParameters[group].unoccludedFillOpacity = value; emit dirty(); } - float getUnoccludedFillOpacity() const { return groupParameters[group].unoccludedFillOpacity; } - - void setOccludedFillOpacity(float value) { groupParameters[group].occludedFillOpacity = value; emit dirty(); } - float getOccludedFillOpacity() const { return groupParameters[group].occludedFillOpacity; } - - void setGroup(int value); - - int group{ 0 }; - GroupParameters groupParameters[Outline::MAX_GROUP_COUNT]; + glm::vec3 color{ 1.f, 0.7f, 0.2f }; + float width{ 2.0f }; + float intensity{ 0.9f }; + float unoccludedFillOpacity{ 0.0f }; + float occludedFillOpacity{ 0.0f }; + bool glow{ false }; signals: void dirty(); }; -class DrawOutline : public Outline { +class DrawOutline { public: - using Inputs = render::VaryingSet4; + using Inputs = render::VaryingSet5; using Config = DrawOutlineConfig; using JobModel = render::Job::ModelI; @@ -143,71 +121,27 @@ public: private: +#include "Outline_shared.slh" + enum { SCENE_DEPTH_SLOT = 0, OUTLINED_DEPTH_SLOT, - OUTLINED_ID_SLOT, OUTLINE_PARAMS_SLOT = 0, FRAME_TRANSFORM_SLOT, }; - struct OutlineConfiguration { - OutlineParameters _groups[MAX_GROUP_COUNT]; - }; - - enum Mode { - M_ALL_UNFILLED, - M_SOME_FILLED, - }; - - using OutlineConfigurationBuffer = gpu::StructBuffer; + using OutlineConfigurationBuffer = gpu::StructBuffer; const gpu::PipelinePointer& getPipeline(); static gpu::PipelinePointer _pipeline; static gpu::PipelinePointer _pipelineFilled; + OutlineConfigurationBuffer _configuration; glm::ivec2 _framebufferSize{ 0,0 }; - Mode _mode{ M_ALL_UNFILLED }; - float _sizes[MAX_GROUP_COUNT]; -}; - -class DrawOutlineTask { -public: - - using Groups = render::VaryingArray; - using Inputs = render::VaryingSet4; - using Config = render::Task::Config; - using JobModel = render::Task::ModelI; - - DrawOutlineTask(); - - void configure(const Config& config); - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); - -private: - - static void initMaskPipelines(render::ShapePlumber& plumber, gpu::StatePointer state); -}; - -class DrawOutlineMask { -public: - - using Groups = render::VaryingArray; - using Inputs = render::VaryingSet2; - // Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer - using Outputs = OutlineRessourcesPointer; - using JobModel = render::Job::ModelIO; - - DrawOutlineMask(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - - void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output); - -protected: - - render::ShapePlumberPointer _shapePlumber; - OutlineRessourcesPointer _outlineRessources; + bool _isFilled{ false }; + float _size; }; class DebugOutlineConfig : public render::Job::Config { @@ -237,16 +171,30 @@ public: private: gpu::PipelinePointer _depthPipeline; - gpu::PipelinePointer _idPipeline; int _geometryDepthId{ 0 }; - int _geometryColorId{ 0 }; bool _isDisplayEnabled{ false }; const gpu::PipelinePointer& getDepthPipeline(); - const gpu::PipelinePointer& getIdPipeline(); void initializePipelines(); }; +class DrawOutlineTask { +public: + + using Groups = render::VaryingArray; + using Inputs = render::VaryingSet4; + using Config = render::Task::Config; + using JobModel = render::Task::ModelI; + + DrawOutlineTask(); + + void configure(const Config& config); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); + +private: + + static void initMaskPipelines(render::ShapePlumber& plumber, gpu::StatePointer state); +}; #endif // hifi_render_utils_OutlineEffect_h diff --git a/libraries/render-utils/src/Outline_shared.slh b/libraries/render-utils/src/Outline_shared.slh index bda67c49d6..2ebece8903 100644 --- a/libraries/render-utils/src/Outline_shared.slh +++ b/libraries/render-utils/src/Outline_shared.slh @@ -9,10 +9,6 @@ # define VEC4 vec4 #endif -#define GROUP_COUNT 7 -#define GROUP_ID_COLOR_COMPONENT_BITS 2 -#define GROUP_ID_COLOR_COMPONENT_MAX 3 - struct OutlineParameters { VEC3 _color; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 73d8b93c07..54c2248d8b 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -181,7 +181,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents); DrawOutlineTask::Groups outlineGroups; outlineGroups[0] = selectedItems; - for (auto i = 1; i < DrawOutline::MAX_GROUP_COUNT; i++) { + for (auto i = 1; i < render::Scene::MAX_OUTLINE_COUNT; i++) { std::ostringstream selectionName; selectionName << selectionBaseName; selectionName << i; diff --git a/libraries/render-utils/src/model_outline.slf b/libraries/render-utils/src/model_outline.slf deleted file mode 100644 index 8c11b2b295..0000000000 --- a/libraries/render-utils/src/model_outline.slf +++ /dev/null @@ -1,21 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_outline.frag -// fragment shader -// -// Created by Olivier Prat on 10/13/17. -// Copyright 2017 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 -// - -layout(location = 0) out vec4 _fragColor; - -uniform vec4 color; - -void main(void) { - _fragColor = color; -} diff --git a/libraries/render-utils/src/model_outline_fade.slf b/libraries/render-utils/src/model_outline_fade.slf deleted file mode 100644 index 69ff54dea6..0000000000 --- a/libraries/render-utils/src/model_outline_fade.slf +++ /dev/null @@ -1,31 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_outline_fade.frag -// fragment shader -// -// Created by Olivier Prat on 10/13/17. -// Copyright 2017 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 Fade.slh@> -<$declareFadeFragment()$> - -layout(location = 0) out vec4 _fragColor; - -uniform vec4 color; - -in vec4 _worldPosition; - -void main(void) { - FadeObjectParams fadeParams; - - <$fetchFadeObjectParams(fadeParams)$> - applyFadeClip(fadeParams, _worldPosition.xyz); - - _fragColor = color; -} diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index fef2077897..04a285bcd1 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -102,6 +102,11 @@ typedef std::queue TransactionQueue; // Items are notified accordingly on any update message happening class Scene { public: + + enum { + MAX_OUTLINE_COUNT = 16 + }; + Scene(glm::vec3 origin, float size); ~Scene(); diff --git a/scripts/developer/utilities/render/debugOutline.js b/scripts/developer/utilities/render/debugOutline.js index ac75197933..8e8a00f912 100644 --- a/scripts/developer/utilities/render/debugOutline.js +++ b/scripts/developer/utilities/render/debugOutline.js @@ -54,6 +54,15 @@ var end2 = { visible: true } +var outlineGroupIndex = 0 + +function setOutlineGroupIndex(index) { + print("Switching to outline group "+index) + outlineGroupIndex = index +} + +window.fromQml.connect(setOutlineGroupIndex); + var renderStates = [{name: "test", end: end}]; var defaultRenderStates = [{name: "test", distance: 20.0, end: end2}]; @@ -78,7 +87,6 @@ function update() { var result = LaserPointers.getPrevRayPickResult(ray); var selectionName = "contextOverlayHighlightList" - var outlineGroupIndex = Render.getConfig("RenderMainView.OutlineEffect").group if (outlineGroupIndex>0) { selectionName += outlineGroupIndex @@ -100,7 +108,7 @@ function update() { } Selection.addToSelectedItemsList(selectionName, typeName, result.objectID) - //print("type: " + result.type + ", id: " + result.objectID); + print("OUTLINE " + outlineGroupIndex + " picked type: " + result.type + ", id: " + result.objectID); prevID = result.objectID; prevType = typeName; diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index d62e3b8899..1e19b2cac9 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -15,7 +15,8 @@ import "configSlider" Item { id: root property var debugConfig: Render.getConfig("RenderMainView.OutlineDebug") - property var drawConfig: Render.getConfig("RenderMainView.OutlineEffect") + property var drawConfig: Render.getConfig("RenderMainView.OutlineEffect0") + signal sendToScript(var message); Column { spacing: 8 @@ -26,12 +27,15 @@ Item { Timer { id: postpone interval: 100; running: false; repeat: false - onTriggered: { paramWidgetLoader.sourceComponent = paramWidgets } + onTriggered: { + paramWidgetLoader.sourceComponent = paramWidgets; + sendToScript(currentIndex) + } } onCurrentIndexChanged: { - // This is a hack to be sure the widgets below properly reflect the change of category: delete the Component + // This is a hack to be sure the widgets below properly reflect the change of index: delete the Component // by setting the loader source to Null and then recreate it 100ms later - root.drawConfig["group"] = currentIndex + root.drawConfig = Render.getConfig("RenderMainView.OutlineEffect"+currentIndex) paramWidgetLoader.sourceComponent = undefined; postpone.interval = 100 postpone.start() From 8cabd1c9530c2395053df294ea76546a180c0837 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 18 Oct 2017 15:06:54 +0200 Subject: [PATCH 021/183] Fixed graphics bug with filled --- libraries/render-utils/src/OutlineEffect.cpp | 6 +++--- libraries/render-utils/src/OutlineEffect.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index d00819d0f2..d028e028d4 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -178,13 +178,13 @@ void DrawOutline::configure(const Config& config) { void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { auto outlineFrameBuffer = inputs.get1(); - auto outlineRect = inputs.get4(); + auto outlineRect = inputs.get3(); if (outlineFrameBuffer && outlineRect.z>0 && outlineRect.w>0) { auto sceneDepthBuffer = inputs.get2(); const auto frameTransform = inputs.get0(); auto outlinedDepthTexture = outlineFrameBuffer->getDepthTexture(); - auto destinationFrameBuffer = inputs.get3(); + auto destinationFrameBuffer = outlineFrameBuffer->getColorFramebuffer(); auto framebufferSize = glm::ivec2(outlinedDepthTexture->getDimensions()); if (sceneDepthBuffer) { @@ -391,7 +391,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende stream << "OutlineEffect" << i; name = stream.str(); } - const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlineRessources, sceneFrameBuffer, primaryFramebuffer, outlinedRect).asVarying(); + const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlineRessources, sceneFrameBuffer, outlinedRect).asVarying(); task.addJob(name, drawOutlineInputs); } diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index b1c2e3c3dd..a099166267 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -110,7 +110,7 @@ signals: class DrawOutline { public: - using Inputs = render::VaryingSet5; + using Inputs = render::VaryingSet4; using Config = DrawOutlineConfig; using JobModel = render::Job::ModelI; From f63b4a64b050ded997e33b577565903cfbd019bc Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 18 Oct 2017 16:02:38 +0200 Subject: [PATCH 022/183] Working debugging script with tabs --- .../utilities/render/debugOutline.js | 6 +- .../developer/utilities/render/outline.qml | 211 +++++++++--------- 2 files changed, 106 insertions(+), 111 deletions(-) diff --git a/scripts/developer/utilities/render/debugOutline.js b/scripts/developer/utilities/render/debugOutline.js index 8e8a00f912..5ac7bcd6aa 100644 --- a/scripts/developer/utilities/render/debugOutline.js +++ b/scripts/developer/utilities/render/debugOutline.js @@ -14,8 +14,8 @@ var qml = Script.resolvePath('outline.qml'); var window = new OverlayWindow({ title: 'Outline', source: qml, - width: 285, - height: 370, + width: 400, + height: 400, }); window.closed.connect(function() { Script.stop(); }); @@ -108,7 +108,7 @@ function update() { } Selection.addToSelectedItemsList(selectionName, typeName, result.objectID) - print("OUTLINE " + outlineGroupIndex + " picked type: " + result.type + ", id: " + result.objectID); + //print("OUTLINE " + outlineGroupIndex + " picked type: " + result.type + ", id: " + result.objectID); prevID = result.objectID; prevType = typeName; diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index 1e19b2cac9..c686af33c6 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -15,34 +15,14 @@ import "configSlider" Item { id: root property var debugConfig: Render.getConfig("RenderMainView.OutlineDebug") - property var drawConfig: Render.getConfig("RenderMainView.OutlineEffect0") signal sendToScript(var message); Column { spacing: 8 - - ComboBox { - id: groupBox - model: ["Group 0", "Group 1", "Group 2", "Group 3", "Group 4"] - Timer { - id: postpone - interval: 100; running: false; repeat: false - onTriggered: { - paramWidgetLoader.sourceComponent = paramWidgets; - sendToScript(currentIndex) - } - } - onCurrentIndexChanged: { - // This is a hack to be sure the widgets below properly reflect the change of index: delete the Component - // by setting the loader source to Null and then recreate it 100ms later - root.drawConfig = Render.getConfig("RenderMainView.OutlineEffect"+currentIndex) - paramWidgetLoader.sourceComponent = undefined; - postpone.interval = 100 - postpone.start() - } - } + anchors.fill: parent CheckBox { + id: debug text: "View Mask" checked: root.debugConfig["viewMask"] onCheckedChanged: { @@ -50,104 +30,119 @@ Item { } } - Component { - id: paramWidgets - Column { - spacing: 8 - CheckBox { - text: "Glow" - checked: root.drawConfig["glow"] - onCheckedChanged: { - drawConfig["glow"] = checked; - } - } - ConfigSlider { - label: "Width" - integral: false - config: root.drawConfig - property: "width" - max: 15.0 - min: 0.0 - width: 280 - } - ConfigSlider { - label: "Intensity" - integral: false - config: root.drawConfig - property: "intensity" - max: 1.0 - min: 0.0 - width: 280 - } + TabView { + id: tabs + width: 384 + height: 400 - GroupBox { - title: "Color" - width: 280 - Column { - spacing: 8 + onCurrentIndexChanged: { + sendToScript(currentIndex) + } - ConfigSlider { - label: "Red" - integral: false - config: root.drawConfig - property: "colorR" - max: 1.0 - min: 0.0 - width: 270 - } - ConfigSlider { - label: "Green" - integral: false - config: root.drawConfig - property: "colorG" - max: 1.0 - min: 0.0 - width: 270 - } - ConfigSlider { - label: "Blue" - integral: false - config: root.drawConfig - property: "colorB" - max: 1.0 - min: 0.0 - width: 270 + Component { + id: paramWidgets + + Column { + spacing: 8 + + CheckBox { + id: glow + text: "Glow" + checked: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex)["glow"] + onCheckedChanged: { + Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex)["glow"] = checked; } } - } + ConfigSlider { + label: "Width" + integral: false + config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) + property: "width" + max: 15.0 + min: 0.0 + width: 280 + } + ConfigSlider { + label: "Intensity" + integral: false + config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) + property: "intensity" + max: 1.0 + min: 0.0 + width: 280 + } - GroupBox { - title: "Fill Opacity" - width: 280 - Column { - spacing: 8 + GroupBox { + title: "Color" + width: 280 + Column { + spacing: 8 - ConfigSlider { - label: "Unoccluded" - integral: false - config: root.drawConfig - property: "unoccludedFillOpacity" - max: 1.0 - min: 0.0 - width: 270 - } - ConfigSlider { - label: "Occluded" - integral: false - config: root.drawConfig - property: "occludedFillOpacity" - max: 1.0 - min: 0.0 - width: 270 + ConfigSlider { + label: "Red" + integral: false + config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) + property: "colorR" + max: 1.0 + min: 0.0 + width: 270 + } + ConfigSlider { + label: "Green" + integral: false + config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) + property: "colorG" + max: 1.0 + min: 0.0 + width: 270 + } + ConfigSlider { + label: "Blue" + integral: false + config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) + property: "colorB" + max: 1.0 + min: 0.0 + width: 270 + } + } + } + + GroupBox { + title: "Fill Opacity" + width: 280 + Column { + spacing: 8 + + ConfigSlider { + label: "Unoccluded" + integral: false + config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) + property: "unoccludedFillOpacity" + max: 1.0 + min: 0.0 + width: 270 + } + ConfigSlider { + label: "Occluded" + integral: false + config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) + property: "occludedFillOpacity" + max: 1.0 + min: 0.0 + width: 270 + } } } } } } + } - Loader { - id: paramWidgetLoader - sourceComponent: paramWidgets + Component.onCompleted: { + for (var i=0 ; i<4 ; i++) { + var outlinePage = tabs.addTab("Outl. "+i, paramWidgets) + outlinePage.active = true } } } From f890c5bb8cac7e5cd28726088058791b85a55131 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 18 Oct 2017 19:40:03 +0200 Subject: [PATCH 023/183] Added project rect and scissor test. Need to increase bounds to take into account blur width --- libraries/render-utils/src/OutlineEffect.cpp | 83 +++++++++++++++++--- libraries/render-utils/src/OutlineEffect.h | 4 +- libraries/shared/src/ViewFrustum.cpp | 55 +++++++------ libraries/shared/src/ViewFrustum.h | 5 ++ 4 files changed, 112 insertions(+), 35 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index d028e028d4..36faee8119 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -11,6 +11,9 @@ #include "OutlineEffect.h" #include "GeometryCache.h" +#include "RenderUtilsLogging.h" + +#include "CubeProjectedPolygon.h" #include #include @@ -99,8 +102,13 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con RenderArgs* args = renderContext->args; ShapeKey::Builder defaultKeyBuilder; + auto framebufferSize = ressources->getSourceFrameSize(); - outputs = args->_viewport; + // First thing we do is determine the projected bounding rect of all the outlined items + auto outlinedRect = computeOutlineRect(inShapes, args->getViewFrustum(), framebufferSize); + qCDebug(renderutils) << "Outline rect is " << outlinedRect.x << ' ' << outlinedRect.y << ' ' << outlinedRect.z << ' ' << outlinedRect.w; + + outputs = outlinedRect; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -108,18 +116,17 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); - batch.setFramebuffer(ressources->getDepthFramebuffer()); - batch.clearDepthFramebuffer(1.0f); - - // Setup camera, projection and viewport for all items - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - glm::mat4 projMat; Transform viewMat; args->getViewFrustum().evalProjectionMatrix(projMat); args->getViewFrustum().evalViewTransform(viewMat); + batch.setStateScissorRect(outlinedRect); + batch.setFramebuffer(ressources->getDepthFramebuffer()); + batch.clearDepthFramebuffer(1.0f, true); + + // Setup camera, projection and viewport for all items + batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); @@ -152,6 +159,49 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con } } +glm::ivec4 DrawOutlineMask::computeOutlineRect(const render::ShapeBounds& shapes, + const ViewFrustum& viewFrustum, glm::ivec2 frameSize) { + glm::vec4 minMaxBounds{ + std::numeric_limits::max(), + std::numeric_limits::max(), + -std::numeric_limits::max(), + -std::numeric_limits::max(), + }; + + for (const auto& keyShapes : shapes) { + const auto& items = keyShapes.second; + + for (const auto& item : items) { + const auto& aabb = item.bound; + const auto projectedCube = viewFrustum.getProjectedPolygon(aabb); + + if (projectedCube.getAnyInView()) { + minMaxBounds.x = std::min(minMaxBounds.x, projectedCube.getMinX()); + minMaxBounds.y = std::min(minMaxBounds.y, projectedCube.getMinY()); + minMaxBounds.z = std::max(minMaxBounds.z, projectedCube.getMaxX()); + minMaxBounds.w = std::max(minMaxBounds.w, projectedCube.getMaxY()); + } + } + } + + if (minMaxBounds.x != std::numeric_limits::max()) { + const glm::vec2 halfFrameSize{ frameSize.x*0.5f, frameSize.y*0.5f }; + glm::ivec4 rect; + + minMaxBounds += 1.0f; + rect.x = glm::clamp((int)floorf(minMaxBounds.x * halfFrameSize.x), 0, frameSize.x); + rect.y = glm::clamp((int)floorf(minMaxBounds.y * halfFrameSize.y), 0, frameSize.y); + rect.z = glm::clamp((int)ceilf(minMaxBounds.z * halfFrameSize.x), 0, frameSize.x); + rect.w = glm::clamp((int)ceilf(minMaxBounds.w * halfFrameSize.y), 0, frameSize.y); + + rect.z -= rect.x; + rect.w -= rect.y; + return rect; + } else { + return glm::ivec4(0, 0, 0, 0); + } +} + gpu::PipelinePointer DrawOutline::_pipeline; gpu::PipelinePointer DrawOutline::_pipelineFilled; @@ -203,6 +253,7 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I batch.enableStereo(false); batch.setFramebuffer(destinationFrameBuffer); + batch.setStateScissorRect(outlineRect); batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); @@ -235,6 +286,7 @@ const gpu::PipelinePointer& DrawOutline::getPipeline() { gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setDepthTest(gpu::State::DepthTest(false, false)); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + state->setScissorEnable(true); _pipeline = gpu::Pipeline::create(program, state); ps = gpu::Shader::createPixel(std::string(Outline_filled_frag)); @@ -261,7 +313,8 @@ void DebugOutline::configure(const Config& config) { } void DebugOutline::run(const render::RenderContextPointer& renderContext, const Inputs& input) { - const auto outlineRessources = input; + const auto outlineRessources = input.get0(); + const auto outlineRect = input.get1(); if (_isDisplayEnabled && outlineRessources) { assert(renderContext->args); @@ -271,6 +324,7 @@ void DebugOutline::run(const render::RenderContextPointer& renderContext, const gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(outlineRect); const auto geometryBuffer = DependencyManager::get(); @@ -305,6 +359,7 @@ void DebugOutline::initializePipelines() { auto state = std::make_shared(); state->setDepthTest(gpu::State::DepthTest(false)); + state->setScissorEnable(true); const auto vs = gpu::Shader::createVertex(VERTEX_SHADER); @@ -360,16 +415,18 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende auto state = std::make_shared(); state->setDepthTest(true, true, gpu::LESS); state->setColorWriteMask(false, false, false, false); + state->setScissorEnable(true); initMaskPipelines(*shapePlumber, state); } // Prepare for outline group rendering. const auto outlineRessources = task.addJob("PrepareOutline", primaryFramebuffer); + render::Varying outline0Rect; for (auto i = 0; i < render::Scene::MAX_OUTLINE_COUNT; i++) { const auto groupItems = groups[i]; const auto outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", groupItems); - const auto outlinedItems = task.addJob("OutlineMetaToSubItems", outlinedItemIDs, true); + const auto outlinedItems = task.addJob("OutlineMetaToSubItems", outlinedItemIDs); // Sort const auto sortedPipelines = task.addJob("OutlinePipelineSort", outlinedItems); @@ -384,6 +441,9 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende } const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedBounds, outlineRessources).asVarying(); const auto outlinedRect = task.addJob(name, drawMaskInputs, shapePlumber); + if (i == 0) { + outline0Rect = outlinedRect; + } // Draw outline { @@ -396,7 +456,8 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende } // Debug outline - task.addJob("OutlineDebug", outlineRessources); + const auto debugInputs = DebugOutline::Inputs(outlineRessources, const_cast(outline0Rect)).asVarying(); + task.addJob("OutlineDebug", debugInputs); } #include "model_shadow_vert.h" diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index a099166267..878bdf2c04 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -72,6 +72,8 @@ public: protected: render::ShapePlumberPointer _shapePlumber; + + static glm::ivec4 computeOutlineRect(const render::ShapeBounds& shapes, const ViewFrustum& viewFrustum, glm::ivec2 frameSize); }; class DrawOutlineConfig : public render::Job::Config { @@ -158,7 +160,7 @@ signals: class DebugOutline { public: - using Inputs = OutlineRessourcesPointer; + using Inputs = render::VaryingSet2; using Config = DebugOutlineConfig; using JobModel = render::Job::ModelI; diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index 978221e167..f08c85a38a 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -504,16 +504,17 @@ const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERT {6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // back, top, left }; -CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const { +template +CubeProjectedPolygon ViewFrustum::computeProjectedPolygon(const TBOX& box) const { const glm::vec3& bottomNearRight = box.getCorner(); glm::vec3 topFarLeft = box.calcTopFarLeft(); - int lookUp = ((_position.x < bottomNearRight.x) ) // 1 = right | compute 6-bit - + ((_position.x > topFarLeft.x ) << 1) // 2 = left | code to - + ((_position.y < bottomNearRight.y) << 2) // 4 = bottom | classify camera - + ((_position.y > topFarLeft.y ) << 3) // 8 = top | with respect to - + ((_position.z < bottomNearRight.z) << 4) // 16 = front/near | the 6 defining - + ((_position.z > topFarLeft.z ) << 5); // 32 = back/far | planes + int lookUp = ((_position.x < bottomNearRight.x)) // 1 = right | compute 6-bit + + ((_position.x > topFarLeft.x) << 1) // 2 = left | code to + + ((_position.y < bottomNearRight.y) << 2) // 4 = bottom | classify camera + + ((_position.y > topFarLeft.y) << 3) // 8 = top | with respect to + + ((_position.z < bottomNearRight.z) << 4) // 16 = front/near | the 6 defining + + ((_position.z > topFarLeft.z) << 5); // 32 = back/far | planes int vertexCount = hullVertexLookup[lookUp][0]; //look up number of vertices @@ -524,8 +525,8 @@ CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const { bool anyPointsInView = false; // assume the worst! if (vertexCount) { allPointsInView = true; // assume the best! - for(int i = 0; i < vertexCount; i++) { - int vertexNum = hullVertexLookup[lookUp][i+1]; + for (int i = 0; i < vertexCount; i++) { + int vertexNum = hullVertexLookup[lookUp][i + 1]; glm::vec3 point = box.getVertex((BoxVertex)vertexNum); glm::vec2 projectedPoint = projectPoint(point, pointInView); allPointsInView = allPointsInView && pointInView; @@ -538,24 +539,24 @@ CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const { // NOTE: This clipping does not improve our overall performance. It basically causes more polygons to // end up in the same quad/half and so the polygon lists get longer, and that's more calls to polygon.occludes() if ( (projectedPolygon.getMaxX() > PolygonClip::RIGHT_OF_CLIPPING_WINDOW ) || - (projectedPolygon.getMaxY() > PolygonClip::TOP_OF_CLIPPING_WINDOW ) || - (projectedPolygon.getMaxX() < PolygonClip::LEFT_OF_CLIPPING_WINDOW ) || - (projectedPolygon.getMaxY() < PolygonClip::BOTTOM_OF_CLIPPING_WINDOW) ) { + (projectedPolygon.getMaxY() > PolygonClip::TOP_OF_CLIPPING_WINDOW ) || + (projectedPolygon.getMaxX() < PolygonClip::LEFT_OF_CLIPPING_WINDOW ) || + (projectedPolygon.getMaxY() < PolygonClip::BOTTOM_OF_CLIPPING_WINDOW) ) { - CoverageRegion::_clippedPolygons++; + CoverageRegion::_clippedPolygons++; - glm::vec2* clippedVertices; - int clippedVertexCount; - PolygonClip::clipToScreen(projectedPolygon.getVertices(), vertexCount, clippedVertices, clippedVertexCount); + glm::vec2* clippedVertices; + int clippedVertexCount; + PolygonClip::clipToScreen(projectedPolygon.getVertices(), vertexCount, clippedVertices, clippedVertexCount); - // Now reset the vertices of our projectedPolygon object - projectedPolygon.setVertexCount(clippedVertexCount); - for(int i = 0; i < clippedVertexCount; i++) { - projectedPolygon.setVertex(i, clippedVertices[i]); - } - delete[] clippedVertices; + // Now reset the vertices of our projectedPolygon object + projectedPolygon.setVertexCount(clippedVertexCount); + for(int i = 0; i < clippedVertexCount; i++) { + projectedPolygon.setVertex(i, clippedVertices[i]); + } + delete[] clippedVertices; - lookUp += PROJECTION_CLIPPED; + lookUp += PROJECTION_CLIPPED; } ***/ } @@ -568,6 +569,14 @@ CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const { return projectedPolygon; } +CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const { + return computeProjectedPolygon(box); +} + +CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AABox& box) const { + return computeProjectedPolygon(box); +} + // Similar strategy to getProjectedPolygon() we use the knowledge of camera position relative to the // axis-aligned voxels to determine which of the voxels vertices must be the furthest. No need for // squares and square-roots. Just compares. diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h index d1b88fb2a5..c428e83397 100644 --- a/libraries/shared/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -119,6 +119,7 @@ public: glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const; CubeProjectedPolygon getProjectedPolygon(const AACube& box) const; + CubeProjectedPolygon getProjectedPolygon(const AABox& box) const; void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const; float distanceToCamera(const glm::vec3& point) const; @@ -169,6 +170,10 @@ private: // Used to project points glm::mat4 _ourModelViewProjectionMatrix; + + template + CubeProjectedPolygon computeProjectedPolygon(const TBOX& box) const; + }; using ViewFrustumPointer = std::shared_ptr; From cc30c0b841dd5a6baef7fe61411870d3b509f8c8 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 19 Oct 2017 11:35:26 +0200 Subject: [PATCH 024/183] Expanded scissor rect with outline blur width --- libraries/render-utils/src/OutlineEffect.cpp | 48 +++++++++++++++++--- libraries/render-utils/src/OutlineEffect.h | 19 +++++++- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 36faee8119..918f769277 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -81,6 +81,10 @@ gpu::TexturePointer OutlineRessources::getDepthTexture() { return getDepthFramebuffer()->getDepthStencilBuffer(); } +OutlineSharedParameters::OutlineSharedParameters() { + std::fill(_blurPixelWidths.begin(), _blurPixelWidths.end(), 0); +} + PrepareDrawOutline::PrepareDrawOutline() { _ressources = std::make_shared(); } @@ -92,6 +96,13 @@ void PrepareDrawOutline::run(const render::RenderContextPointer& renderContext, outputs = _ressources; } +DrawOutlineMask::DrawOutlineMask(unsigned int outlineIndex, + render::ShapePlumberPointer shapePlumber, OutlineSharedParametersPointer parameters) : + _outlineIndex{ outlineIndex }, + _shapePlumber { shapePlumber }, + _parameters{ parameters } { +} + void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); @@ -106,9 +117,12 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con // First thing we do is determine the projected bounding rect of all the outlined items auto outlinedRect = computeOutlineRect(inShapes, args->getViewFrustum(), framebufferSize); + auto blurPixelWidth = _parameters->_blurPixelWidths[_outlineIndex]; qCDebug(renderutils) << "Outline rect is " << outlinedRect.x << ' ' << outlinedRect.y << ' ' << outlinedRect.z << ' ' << outlinedRect.w; - outputs = outlinedRect; + // Add 1 pixel of extra margin to be on the safe side + outputs = expandRect(outlinedRect, blurPixelWidth+1, framebufferSize); + outlinedRect = expandRect(outputs, blurPixelWidth+1, framebufferSize); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -202,10 +216,28 @@ glm::ivec4 DrawOutlineMask::computeOutlineRect(const render::ShapeBounds& shapes } } +glm::ivec4 DrawOutlineMask::expandRect(glm::ivec4 rect, int amount, glm::ivec2 frameSize) { + // Go bo back to min max values + rect.z += rect.x; + rect.w += rect.y; + + rect.x = std::max(0, rect.x - amount); + rect.y = std::max(0, rect.y - amount); + rect.z = std::min(frameSize.x, rect.z + amount); + rect.w = std::min(frameSize.y, rect.w + amount); + + // Back to width height + rect.z -= rect.x; + rect.w -= rect.y; + return rect; +} + gpu::PipelinePointer DrawOutline::_pipeline; gpu::PipelinePointer DrawOutline::_pipelineFilled; -DrawOutline::DrawOutline() { +DrawOutline::DrawOutline(unsigned int outlineIndex, OutlineSharedParametersPointer parameters) : + _outlineIndex{ outlineIndex }, + _parameters{ parameters } { } void DrawOutline::configure(const Config& config) { @@ -222,7 +254,7 @@ void DrawOutline::configure(const Config& config) { _size = config.width / 400.0f; configuration._size.x = (_size * _framebufferSize.y) / _framebufferSize.x; configuration._size.y = _size; - + _parameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y); _isFilled = (config.unoccludedFillOpacity > OPACITY_EPSILON || config.occludedFillOpacity > OPACITY_EPSILON); } @@ -247,18 +279,19 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I configuration._size.x = (_size * framebufferSize.y) / framebufferSize.x; configuration._size.y = _size; _framebufferSize = framebufferSize; + _parameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y); } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); batch.setFramebuffer(destinationFrameBuffer); - batch.setStateScissorRect(outlineRect); batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); batch.setPipeline(pipeline); + batch.setStateScissorRect(outlineRect); batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer()); @@ -410,7 +443,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende const auto deferredFrameTransform = inputs.getN(3); // Prepare the ShapePipeline - ShapePlumberPointer shapePlumber = std::make_shared(); + auto shapePlumber = std::make_shared(); { auto state = std::make_shared(); state->setDepthTest(true, true, gpu::LESS); @@ -418,6 +451,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende state->setScissorEnable(true); initMaskPipelines(*shapePlumber, state); } + auto sharedParameters = std::make_shared(); // Prepare for outline group rendering. const auto outlineRessources = task.addJob("PrepareOutline", primaryFramebuffer); @@ -440,7 +474,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende name = stream.str(); } const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedBounds, outlineRessources).asVarying(); - const auto outlinedRect = task.addJob(name, drawMaskInputs, shapePlumber); + const auto outlinedRect = task.addJob(name, drawMaskInputs, i, shapePlumber, sharedParameters); if (i == 0) { outline0Rect = outlinedRect; } @@ -452,7 +486,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende name = stream.str(); } const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlineRessources, sceneFrameBuffer, outlinedRect).asVarying(); - task.addJob(name, drawOutlineInputs); + task.addJob(name, drawOutlineInputs, i, sharedParameters); } // Debug outline diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index 878bdf2c04..ab603ecab6 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -42,6 +42,16 @@ protected: using OutlineRessourcesPointer = std::shared_ptr; +class OutlineSharedParameters { +public: + + OutlineSharedParameters(); + + std::array _blurPixelWidths; +}; + +using OutlineSharedParametersPointer = std::shared_ptr; + class PrepareDrawOutline { public: using Inputs = gpu::FramebufferPointer; @@ -65,15 +75,18 @@ public: using Outputs = glm::ivec4; using JobModel = render::Job::ModelIO; - DrawOutlineMask(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + DrawOutlineMask(unsigned int outlineIndex, render::ShapePlumberPointer shapePlumber, OutlineSharedParametersPointer parameters); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); protected: + unsigned int _outlineIndex; render::ShapePlumberPointer _shapePlumber; + OutlineSharedParametersPointer _parameters; static glm::ivec4 computeOutlineRect(const render::ShapeBounds& shapes, const ViewFrustum& viewFrustum, glm::ivec2 frameSize); + static glm::ivec4 expandRect(glm::ivec4 rect, int amount, glm::ivec2 frameSize); }; class DrawOutlineConfig : public render::Job::Config { @@ -116,7 +129,7 @@ public: using Config = DrawOutlineConfig; using JobModel = render::Job::ModelI; - DrawOutline(); + DrawOutline(unsigned int outlineIndex, OutlineSharedParametersPointer parameters); void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); @@ -140,6 +153,8 @@ private: static gpu::PipelinePointer _pipeline; static gpu::PipelinePointer _pipelineFilled; + unsigned int _outlineIndex; + OutlineSharedParametersPointer _parameters; OutlineConfigurationBuffer _configuration; glm::ivec2 _framebufferSize{ 0,0 }; bool _isFilled{ false }; From 111966b987bc5115628a83a623475b8c2117456d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 19 Oct 2017 12:39:34 +0200 Subject: [PATCH 025/183] Fixed potential bug with outline frame buffer allocations. Still problems with avatar outline rect --- libraries/render-utils/src/OutlineEffect.cpp | 53 ++++++++++---------- libraries/render-utils/src/OutlineEffect.h | 8 +-- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 918f769277..6e313d262a 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -37,43 +37,36 @@ OutlineRessources::OutlineRessources() { void OutlineRessources::update(const gpu::FramebufferPointer& primaryFrameBuffer) { auto newFrameSize = glm::ivec2(primaryFrameBuffer->getSize()); - // If the depth buffer or size changed, we need to delete our FBOs and recreate them at the + // If the buffer size changed, we need to delete our FBOs and recreate them at the // new correct dimensions. - if (_depthFrameBuffer) { - if (_frameSize != newFrameSize) { - _frameSize = newFrameSize; - clear(); + if (_frameSize != newFrameSize) { + _frameSize = newFrameSize; + allocateDepthBuffer(primaryFrameBuffer); + allocateColorBuffer(primaryFrameBuffer); + } else { + if (!_depthFrameBuffer) { + allocateDepthBuffer(primaryFrameBuffer); } - } - if (!_colorFrameBuffer) { - if (_frameSize != newFrameSize) { - _frameSize = newFrameSize; - // Failing to recreate this frame buffer when the screen has been resized creates a bug on Mac - _colorFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithoutDepth")); - _colorFrameBuffer->setRenderBuffer(0, primaryFrameBuffer->getRenderBuffer(0)); + if (!_colorFrameBuffer) { + allocateColorBuffer(primaryFrameBuffer); } } } -void OutlineRessources::clear() { - _depthFrameBuffer.reset(); +void OutlineRessources::allocateColorBuffer(const gpu::FramebufferPointer& primaryFrameBuffer) { + _colorFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithoutDepth")); + _colorFrameBuffer->setRenderBuffer(0, primaryFrameBuffer->getRenderBuffer(0)); } -void OutlineRessources::allocate() { - - auto width = _frameSize.x; - auto height = _frameSize.y; +void OutlineRessources::allocateDepthBuffer(const gpu::FramebufferPointer& primaryFrameBuffer) { auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); - auto depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(depthFormat, width, height)); - + auto depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(depthFormat, _frameSize.x, _frameSize.y)); _depthFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); _depthFrameBuffer->setDepthStencilBuffer(depthTexture, depthFormat); } gpu::FramebufferPointer OutlineRessources::getDepthFramebuffer() { - if (!_depthFrameBuffer) { - allocate(); - } + assert(_depthFrameBuffer); return _depthFrameBuffer; } @@ -81,6 +74,11 @@ gpu::TexturePointer OutlineRessources::getDepthTexture() { return getDepthFramebuffer()->getDepthStencilBuffer(); } +gpu::FramebufferPointer OutlineRessources::getColorFramebuffer() { + assert(_colorFrameBuffer); + return _colorFrameBuffer; +} + OutlineSharedParameters::OutlineSharedParameters() { std::fill(_blurPixelWidths.begin(), _blurPixelWidths.end(), 0); } @@ -305,6 +303,11 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I const gpu::PipelinePointer& DrawOutline::getPipeline() { if (!_pipeline) { + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setDepthTest(gpu::State::DepthTest(false, false)); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + state->setScissorEnable(true); + auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); auto ps = gpu::Shader::createPixel(std::string(Outline_frag)); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); @@ -316,10 +319,6 @@ const gpu::PipelinePointer& DrawOutline::getPipeline() { slotBindings.insert(gpu::Shader::Binding("outlinedDepthMap", OUTLINED_DEPTH_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(gpu::State::DepthTest(false, false)); - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); - state->setScissorEnable(true); _pipeline = gpu::Pipeline::create(program, state); ps = gpu::Shader::createPixel(std::string(Outline_filled_frag)); diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index ab603ecab6..b4be75484e 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -23,7 +23,7 @@ public: gpu::FramebufferPointer getDepthFramebuffer(); gpu::TexturePointer getDepthTexture(); - gpu::FramebufferPointer getColorFramebuffer() { return _colorFrameBuffer; } + gpu::FramebufferPointer getColorFramebuffer(); // Update the source framebuffer size which will drive the allocation of all the other resources. void update(const gpu::FramebufferPointer& primaryFrameBuffer); @@ -31,13 +31,13 @@ public: protected: - void clear(); - void allocate(); - gpu::FramebufferPointer _depthFrameBuffer; gpu::FramebufferPointer _colorFrameBuffer; glm::ivec2 _frameSize; + + void allocateColorBuffer(const gpu::FramebufferPointer& primaryFrameBuffer); + void allocateDepthBuffer(const gpu::FramebufferPointer& primaryFrameBuffer); }; using OutlineRessourcesPointer = std::shared_ptr; From 382262da3db5d47d0d21c03e8e9ee8d96633c19c Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 19 Oct 2017 16:23:13 +0200 Subject: [PATCH 026/183] Working scissor with correct projected bounding box rect --- libraries/render-utils/src/OutlineEffect.cpp | 13 +-- libraries/shared/src/ViewFrustum.cpp | 96 ++++++++++++++++++-- libraries/shared/src/ViewFrustum.h | 1 + 3 files changed, 98 insertions(+), 12 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 6e313d262a..19d3847e50 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -185,13 +185,14 @@ glm::ivec4 DrawOutlineMask::computeOutlineRect(const render::ShapeBounds& shapes for (const auto& item : items) { const auto& aabb = item.bound; - const auto projectedCube = viewFrustum.getProjectedPolygon(aabb); + glm::vec2 bottomLeft; + glm::vec2 topRight; - if (projectedCube.getAnyInView()) { - minMaxBounds.x = std::min(minMaxBounds.x, projectedCube.getMinX()); - minMaxBounds.y = std::min(minMaxBounds.y, projectedCube.getMinY()); - minMaxBounds.z = std::max(minMaxBounds.z, projectedCube.getMaxX()); - minMaxBounds.w = std::max(minMaxBounds.w, projectedCube.getMaxY()); + if (viewFrustum.getProjectedRect(aabb, bottomLeft, topRight)) { + minMaxBounds.x = std::min(minMaxBounds.x, bottomLeft.x); + minMaxBounds.y = std::min(minMaxBounds.y, bottomLeft.y); + minMaxBounds.z = std::max(minMaxBounds.z, topRight.x); + minMaxBounds.w = std::max(minMaxBounds.w, topRight.y); } } } diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index f08c85a38a..747b39f79e 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include @@ -509,12 +510,12 @@ CubeProjectedPolygon ViewFrustum::computeProjectedPolygon(const TBOX& box) const const glm::vec3& bottomNearRight = box.getCorner(); glm::vec3 topFarLeft = box.calcTopFarLeft(); - int lookUp = ((_position.x < bottomNearRight.x)) // 1 = right | compute 6-bit - + ((_position.x > topFarLeft.x) << 1) // 2 = left | code to - + ((_position.y < bottomNearRight.y) << 2) // 4 = bottom | classify camera - + ((_position.y > topFarLeft.y) << 3) // 8 = top | with respect to - + ((_position.z < bottomNearRight.z) << 4) // 16 = front/near | the 6 defining - + ((_position.z > topFarLeft.z) << 5); // 32 = back/far | planes + int lookUp = ((_position.x < bottomNearRight.x)) // 1 = right | compute 6-bit + + ((_position.x > topFarLeft.x) << 1) // 2 = left | code to + + ((_position.y < bottomNearRight.y) << 2) // 4 = bottom | classify camera + + ((_position.y > topFarLeft.y) << 3) // 8 = top | with respect to + + ((_position.z < bottomNearRight.z) << 4) // 16 = front/near | the 6 defining + + ((_position.z > topFarLeft.z) << 5); // 32 = back/far | planes int vertexCount = hullVertexLookup[lookUp][0]; //look up number of vertices @@ -577,6 +578,89 @@ CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AABox& box) const { return computeProjectedPolygon(box); } +bool ViewFrustum::getProjectedRect(const AABox& box, glm::vec2& bottomLeft, glm::vec2& topRight) const { + using Edge = std::pair; + + const int VERTEX_COUNT = 8; + const int EDGE_COUNT = 12; + // In theory, after clipping a box with a plane, only 4 new vertices at max + // should be created but due to potential imprecisions (edge almost parallel to + // near plane for instance) there might be more + const int MAX_VERTEX_COUNT = VERTEX_COUNT + 4 + 2; + + std::array vertices; + std::array boxEdges{ + Edge(BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR), + Edge(TOP_LEFT_NEAR, TOP_RIGHT_NEAR), + Edge(BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR), + Edge(TOP_LEFT_FAR, TOP_RIGHT_FAR), + Edge(BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR), + Edge(BOTTOM_LEFT_FAR, TOP_LEFT_FAR), + Edge(BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR), + Edge(BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR), + Edge(BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR), + Edge(TOP_LEFT_NEAR, TOP_LEFT_FAR), + Edge(BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR), + Edge(TOP_RIGHT_NEAR, TOP_RIGHT_FAR) + }; + std::array distancesToNearPlane; + std::bitset areVerticesInside; + int vertexCount = VERTEX_COUNT; + int i; + + // Clip the hull with the near plane. + const auto& nearPlane = _planes[NEAR_PLANE]; + + for (i = 0; i < VERTEX_COUNT; i++) { + vertices[i] = box.getVertex(static_cast(i)); + distancesToNearPlane[i] = nearPlane.distance(vertices[i]); + } + + for (i = 0; i < EDGE_COUNT; i++) { + const auto& edgeVertexIndices = boxEdges[i]; + const auto& startVertex = vertices[edgeVertexIndices.first]; + const auto& endVertex = vertices[edgeVertexIndices.second]; + float startVertexDistance = distancesToNearPlane[edgeVertexIndices.first]; + float endVertexDistance = distancesToNearPlane[edgeVertexIndices.second]; + bool isStartPointInside = startVertexDistance >= 0.0f; + bool isEndPointInside = endVertexDistance >= 0.0f; + + areVerticesInside.set(edgeVertexIndices.first, isStartPointInside); + areVerticesInside.set(edgeVertexIndices.second, isEndPointInside); + + if (isStartPointInside != isEndPointInside) { + // One of the two vertices is behind the near plane so add a new clipped vertex + // add tag it as projectable. + vertices[vertexCount] = startVertex + (endVertex - startVertex) * (startVertexDistance / (startVertexDistance - endVertexDistance)); + areVerticesInside.set(vertexCount); + vertexCount++; + } + } + + // Project points that are inside + bottomLeft.x = std::numeric_limits::max(); + bottomLeft.y = std::numeric_limits::max(); + topRight.x = -std::numeric_limits::max(); + topRight.y = -std::numeric_limits::max(); + for (i = 0; i < vertexCount; i++) { + if (areVerticesInside[i]) { + bool isPointInside; + auto projectedPoint = projectPoint(vertices[i], isPointInside); + bottomLeft.x = std::min(bottomLeft.x, projectedPoint.x); + bottomLeft.y = std::min(bottomLeft.y, projectedPoint.y); + topRight.x = std::max(topRight.x, projectedPoint.x); + topRight.y = std::max(topRight.y, projectedPoint.y); + } + } + + bottomLeft.x = glm::clamp(bottomLeft.x, -1.0f, 1.0f); + bottomLeft.y = glm::clamp(bottomLeft.y, -1.0f, 1.0f); + topRight.x = glm::clamp(topRight.x, -1.0f, 1.0f); + topRight.y = glm::clamp(topRight.y, -1.0f, 1.0f); + + return areVerticesInside.any(); +} + // Similar strategy to getProjectedPolygon() we use the knowledge of camera position relative to the // axis-aligned voxels to determine which of the voxels vertices must be the furthest. No need for // squares and square-roots. Just compares. diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h index c428e83397..98f666d666 100644 --- a/libraries/shared/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -120,6 +120,7 @@ public: glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const; CubeProjectedPolygon getProjectedPolygon(const AACube& box) const; CubeProjectedPolygon getProjectedPolygon(const AABox& box) const; + bool getProjectedRect(const AABox& box, glm::vec2& bottomLeft, glm::vec2& topRight) const; void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const; float distanceToCamera(const glm::vec3& point) const; From fc66dcfdea154849606a90354806f156da05fea4 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 19 Oct 2017 16:52:29 +0200 Subject: [PATCH 027/183] Added outline to statsGPU script --- libraries/render-utils/src/RenderDeferredTask.cpp | 4 ++-- scripts/developer/utilities/render/statsGPU.qml | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 54c2248d8b..dc4bdd14cc 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -176,6 +176,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer).asVarying(); task.addJob("ToneMapping", toneMappingInputs); + const auto outlineRangeTimer = task.addJob("BeginOutlineRangeTimer", "Outline"); // Select items that need to be outlined const auto selectionBaseName = "contextOverlayHighlightList"; const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents); @@ -187,12 +188,11 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren selectionName << i; outlineGroups[i] = addSelectItemJobs(task, selectionName.str().c_str(), metas, opaques, transparents); } - const auto outlineRangeTimer = task.addJob("BeginOutlineRangeTimer", "Outline"); const auto outlineInputs = DrawOutlineTask::Inputs(outlineGroups, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); task.addJob("DrawOutline", outlineInputs); - task.addJob("EndOutlineRangeTimer", outlineRangeTimer); + task.addJob("OutlineRangeTimer", outlineRangeTimer); { // DEbug the bounds of the rendered items, still look at the zbuffer task.addJob("DrawMetaBounds", metas); diff --git a/scripts/developer/utilities/render/statsGPU.qml b/scripts/developer/utilities/render/statsGPU.qml index 6b80f00af3..8d284c11ca 100644 --- a/scripts/developer/utilities/render/statsGPU.qml +++ b/scripts/developer/utilities/render/statsGPU.qml @@ -65,6 +65,13 @@ Item { label: "tone and post", color: "#FF0000" } + , + { + object: Render.getConfig("RenderMainView.OutlineRangeTimer"), + prop: "gpuRunTime", + label: "outline", + color: "#FFFF00" + } ] } PlotPerf { @@ -105,6 +112,13 @@ Item { label: "tone and post", color: "#FF0000" } + , + { + object: Render.getConfig("RenderMainView.OutlineRangeTimer"), + prop: "batchRunTime", + label: "outline", + color: "#FFFF00" + } ] } } From 410b1904cdb230c9f4bc079ced67f674ef1793d3 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 19 Oct 2017 17:36:16 +0200 Subject: [PATCH 028/183] Fixed bug in outline.qml that associated outline tab to wrong outline job config --- libraries/render-utils/src/OutlineEffect.cpp | 36 ++--- libraries/render-utils/src/OutlineEffect.h | 5 +- libraries/render/src/render/Scene.h | 2 +- .../developer/utilities/render/outline.qml | 126 ++++-------------- .../render/outlinePage/OutlinePage.qml | 113 ++++++++++++++++ .../utilities/render/outlinePage/qmldir | 1 + 6 files changed, 159 insertions(+), 124 deletions(-) create mode 100644 scripts/developer/utilities/render/outlinePage/OutlinePage.qml create mode 100644 scripts/developer/utilities/render/outlinePage/qmldir diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 19d3847e50..a4286474f9 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -98,7 +98,7 @@ DrawOutlineMask::DrawOutlineMask(unsigned int outlineIndex, render::ShapePlumberPointer shapePlumber, OutlineSharedParametersPointer parameters) : _outlineIndex{ outlineIndex }, _shapePlumber { shapePlumber }, - _parameters{ parameters } { + _sharedParameters{ parameters } { } void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { @@ -115,8 +115,8 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con // First thing we do is determine the projected bounding rect of all the outlined items auto outlinedRect = computeOutlineRect(inShapes, args->getViewFrustum(), framebufferSize); - auto blurPixelWidth = _parameters->_blurPixelWidths[_outlineIndex]; - qCDebug(renderutils) << "Outline rect is " << outlinedRect.x << ' ' << outlinedRect.y << ' ' << outlinedRect.z << ' ' << outlinedRect.w; + auto blurPixelWidth = _sharedParameters->_blurPixelWidths[_outlineIndex]; + //qCDebug(renderutils) << "Outline rect is " << outlinedRect.x << ' ' << outlinedRect.y << ' ' << outlinedRect.z << ' ' << outlinedRect.w; // Add 1 pixel of extra margin to be on the safe side outputs = expandRect(outlinedRect, blurPixelWidth+1, framebufferSize); @@ -236,25 +236,25 @@ gpu::PipelinePointer DrawOutline::_pipelineFilled; DrawOutline::DrawOutline(unsigned int outlineIndex, OutlineSharedParametersPointer parameters) : _outlineIndex{ outlineIndex }, - _parameters{ parameters } { + _sharedParameters{ parameters } { } void DrawOutline::configure(const Config& config) { - auto& configuration = _configuration.edit(); const auto OPACITY_EPSILON = 5e-3f; - configuration._color = config.color; - configuration._intensity = config.intensity * (config.glow ? 2.f : 1.f); - configuration._unoccludedFillOpacity = config.unoccludedFillOpacity; - configuration._occludedFillOpacity = config.occludedFillOpacity; - configuration._threshold = config.glow ? 1.f : 1e-3f; - configuration._blurKernelSize = std::min(10, std::max(2, (int)floorf(config.width * 3 + 0.5f))); + _parameters._color = config.color; + _parameters._intensity = config.intensity * (config.glow ? 2.0f : 1.0f); + _parameters._unoccludedFillOpacity = config.unoccludedFillOpacity; + _parameters._occludedFillOpacity = config.occludedFillOpacity; + _parameters._threshold = config.glow ? 1.0f : 1e-3f; + _parameters._blurKernelSize = std::min(10, std::max(2, (int)floorf(config.width * 3 + 0.5f))); // Size is in normalized screen height. We decide that for outline width = 1, this is equal to 1/400. _size = config.width / 400.0f; - configuration._size.x = (_size * _framebufferSize.y) / _framebufferSize.x; - configuration._size.y = _size; - _parameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y); + _parameters._size.x = (_size * _framebufferSize.y) / _framebufferSize.x; + _parameters._size.y = _size; + _sharedParameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y); _isFilled = (config.unoccludedFillOpacity > OPACITY_EPSILON || config.occludedFillOpacity > OPACITY_EPSILON); + _configuration.edit() = _parameters; } void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { @@ -274,11 +274,11 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I if (_framebufferSize != framebufferSize) { - auto& configuration = _configuration.edit(); - configuration._size.x = (_size * framebufferSize.y) / framebufferSize.x; - configuration._size.y = _size; + _parameters._size.x = (_size * framebufferSize.y) / framebufferSize.x; + _parameters._size.y = _size; _framebufferSize = framebufferSize; - _parameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y); + _sharedParameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y); + _configuration.edit() = _parameters; } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index b4be75484e..ee5e503de9 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -83,7 +83,7 @@ protected: unsigned int _outlineIndex; render::ShapePlumberPointer _shapePlumber; - OutlineSharedParametersPointer _parameters; + OutlineSharedParametersPointer _sharedParameters; static glm::ivec4 computeOutlineRect(const render::ShapeBounds& shapes, const ViewFrustum& viewFrustum, glm::ivec2 frameSize); static glm::ivec4 expandRect(glm::ivec4 rect, int amount, glm::ivec2 frameSize); @@ -154,7 +154,8 @@ private: static gpu::PipelinePointer _pipelineFilled; unsigned int _outlineIndex; - OutlineSharedParametersPointer _parameters; + OutlineParameters _parameters; + OutlineSharedParametersPointer _sharedParameters; OutlineConfigurationBuffer _configuration; glm::ivec2 _framebufferSize{ 0,0 }; bool _isFilled{ false }; diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 04a285bcd1..1f3b9a72c3 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -104,7 +104,7 @@ class Scene { public: enum { - MAX_OUTLINE_COUNT = 16 + MAX_OUTLINE_COUNT = 8 }; Scene(glm::vec3 origin, float size); diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index c686af33c6..578f0857dc 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -10,7 +10,7 @@ // import QtQuick 2.5 import QtQuick.Controls 1.4 -import "configSlider" +import "outlinePage" Item { id: root @@ -39,110 +39,30 @@ Item { sendToScript(currentIndex) } - Component { - id: paramWidgets - - Column { - spacing: 8 - - CheckBox { - id: glow - text: "Glow" - checked: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex)["glow"] - onCheckedChanged: { - Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex)["glow"] = checked; - } - } - ConfigSlider { - label: "Width" - integral: false - config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) - property: "width" - max: 15.0 - min: 0.0 - width: 280 - } - ConfigSlider { - label: "Intensity" - integral: false - config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) - property: "intensity" - max: 1.0 - min: 0.0 - width: 280 - } - - GroupBox { - title: "Color" - width: 280 - Column { - spacing: 8 - - ConfigSlider { - label: "Red" - integral: false - config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) - property: "colorR" - max: 1.0 - min: 0.0 - width: 270 - } - ConfigSlider { - label: "Green" - integral: false - config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) - property: "colorG" - max: 1.0 - min: 0.0 - width: 270 - } - ConfigSlider { - label: "Blue" - integral: false - config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) - property: "colorB" - max: 1.0 - min: 0.0 - width: 270 - } - } - } - - GroupBox { - title: "Fill Opacity" - width: 280 - Column { - spacing: 8 - - ConfigSlider { - label: "Unoccluded" - integral: false - config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) - property: "unoccludedFillOpacity" - max: 1.0 - min: 0.0 - width: 270 - } - ConfigSlider { - label: "Occluded" - integral: false - config: Render.getConfig("RenderMainView.OutlineEffect"+tabs.currentIndex) - property: "occludedFillOpacity" - max: 1.0 - min: 0.0 - width: 270 - } - } - } + Tab { + title: "Outl.0" + OutlinePage { + outlineIndex: 0 + } + } + Tab { + title: "Outl.1" + OutlinePage { + outlineIndex: 1 + } + } + Tab { + title: "Outl.2" + OutlinePage { + outlineIndex: 2 + } + } + Tab { + title: "Outl.3" + OutlinePage { + outlineIndex: 3 } } } } - - Component.onCompleted: { - for (var i=0 ; i<4 ; i++) { - var outlinePage = tabs.addTab("Outl. "+i, paramWidgets) - outlinePage.active = true - } - } } diff --git a/scripts/developer/utilities/render/outlinePage/OutlinePage.qml b/scripts/developer/utilities/render/outlinePage/OutlinePage.qml new file mode 100644 index 0000000000..849f71bdb4 --- /dev/null +++ b/scripts/developer/utilities/render/outlinePage/OutlinePage.qml @@ -0,0 +1,113 @@ +// +// outlinePage.qml +// developer/utilities/render +// +// Olivier Prat, created on 08/08/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import "../configSlider" + +Item { + id: root + property var outlineIndex: 0 + property var drawConfig: Render.getConfig("RenderMainView.OutlineEffect"+outlineIndex) + + Column { + spacing: 8 + + CheckBox { + id: glow + text: "Glow" + checked: root.drawConfig["glow"] + onCheckedChanged: { + paramWidgets.drawConfig["glow"] = checked; + } + } + ConfigSlider { + label: "Width" + integral: false + config: root.drawConfig + property: "width" + max: 15.0 + min: 0.0 + width: 280 + } + ConfigSlider { + label: "Intensity" + integral: false + config: root.drawConfig + property: "intensity" + max: 1.0 + min: 0.0 + width: 280 + } + + GroupBox { + title: "Color" + width: 280 + Column { + spacing: 8 + + ConfigSlider { + label: "Red" + integral: false + config: root.drawConfig + property: "colorR" + max: 1.0 + min: 0.0 + width: 270 + } + ConfigSlider { + label: "Green" + integral: false + config: root.drawConfig + property: "colorG" + max: 1.0 + min: 0.0 + width: 270 + } + ConfigSlider { + label: "Blue" + integral: false + config: root.drawConfig + property: "colorB" + max: 1.0 + min: 0.0 + width: 270 + } + } + } + + GroupBox { + title: "Fill Opacity" + width: 280 + Column { + spacing: 8 + + ConfigSlider { + label: "Unoccluded" + integral: false + config: root.drawConfig + property: "unoccludedFillOpacity" + max: 1.0 + min: 0.0 + width: 270 + } + ConfigSlider { + label: "Occluded" + integral: false + config: root.drawConfig + property: "occludedFillOpacity" + max: 1.0 + min: 0.0 + width: 270 + } + } + } + } +} diff --git a/scripts/developer/utilities/render/outlinePage/qmldir b/scripts/developer/utilities/render/outlinePage/qmldir new file mode 100644 index 0000000000..56f5d45414 --- /dev/null +++ b/scripts/developer/utilities/render/outlinePage/qmldir @@ -0,0 +1 @@ +OutlinePage 1.0 OutlinePage.qml \ No newline at end of file From 6acff216d919ab1c7976cb1b17367cb525128f5a Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 19 Oct 2017 19:00:09 +0200 Subject: [PATCH 029/183] Reduced blur tap for slightly better performance --- libraries/render-utils/src/OutlineEffect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index a4286474f9..8822bcc649 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -247,7 +247,7 @@ void DrawOutline::configure(const Config& config) { _parameters._unoccludedFillOpacity = config.unoccludedFillOpacity; _parameters._occludedFillOpacity = config.occludedFillOpacity; _parameters._threshold = config.glow ? 1.0f : 1e-3f; - _parameters._blurKernelSize = std::min(10, std::max(2, (int)floorf(config.width * 3 + 0.5f))); + _parameters._blurKernelSize = std::min(7, std::max(2, (int)floorf(config.width * 3 + 0.5f))); // Size is in normalized screen height. We decide that for outline width = 1, this is equal to 1/400. _size = config.width / 400.0f; _parameters._size.x = (_size * _framebufferSize.y) / _framebufferSize.x; From 3227b9d64ad37e557ad38da4bccba2143f867327 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 20 Oct 2017 09:50:37 +0200 Subject: [PATCH 030/183] Fixed potential bug when item doesn't have a payload --- libraries/render/src/render/FilterTask.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/render/src/render/FilterTask.cpp b/libraries/render/src/render/FilterTask.cpp index 49a9ada91e..f60f5895b7 100644 --- a/libraries/render/src/render/FilterTask.cpp +++ b/libraries/render/src/render/FilterTask.cpp @@ -118,8 +118,9 @@ void MetaToSubItems::run(const RenderContextPointer& renderContext, const ItemBo for (auto idBound : inItems) { auto& item = scene->getItem(idBound.id); - - item.fetchMetaSubItems(outItems); + if (item.exist()) { + item.fetchMetaSubItems(outItems); + } } } @@ -132,8 +133,9 @@ void IDsToBounds::run(const RenderContextPointer& renderContext, const ItemIDs& if (!_disableAABBs) { for (auto id : inItems) { auto& item = scene->getItem(id); - - outItems.emplace_back(ItemBound{ id, item.getBound() }); + if (item.exist()) { + outItems.emplace_back(ItemBound{ id, item.getBound() }); + } } } else { for (auto id : inItems) { From 732fe3b8dbc1e4f23cede8a319c2360f2b4d6151 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 20 Oct 2017 11:32:43 +0200 Subject: [PATCH 031/183] Improved outline debugging script for easier test plan --- .../scripting/SelectionScriptingInterface.cpp | 6 ++ .../scripting/SelectionScriptingInterface.h | 1 + .../utilities/render/debugOutline.js | 85 +++++++++++++------ .../developer/utilities/render/outline.qml | 31 +++++-- 4 files changed, 90 insertions(+), 33 deletions(-) diff --git a/interface/src/scripting/SelectionScriptingInterface.cpp b/interface/src/scripting/SelectionScriptingInterface.cpp index 808396c901..1adf5650dd 100644 --- a/interface/src/scripting/SelectionScriptingInterface.cpp +++ b/interface/src/scripting/SelectionScriptingInterface.cpp @@ -71,6 +71,12 @@ bool SelectionScriptingInterface::removeFromSelectedItemsList(const QString& lis return false; } +bool SelectionScriptingInterface::clearSelectedItemsList(const QString& listName) { + _selectedItemsListMap.insert(listName, GameplayObjects()); + emit selectedItemsListChanged(listName); + return true; +} + template bool SelectionScriptingInterface::addToGameplayObjects(const QString& listName, T idToAdd) { GameplayObjects currentList = _selectedItemsListMap.value(listName); currentList.addToGameplayObjects(idToAdd); diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h index d1a372c5c4..28c1713050 100644 --- a/interface/src/scripting/SelectionScriptingInterface.h +++ b/interface/src/scripting/SelectionScriptingInterface.h @@ -61,6 +61,7 @@ public: Q_INVOKABLE bool addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id); Q_INVOKABLE bool removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id); + Q_INVOKABLE bool clearSelectedItemsList(const QString& listName); signals: void selectedItemsListChanged(const QString& listName); diff --git a/scripts/developer/utilities/render/debugOutline.js b/scripts/developer/utilities/render/debugOutline.js index 5ac7bcd6aa..c01fbd3c76 100644 --- a/scripts/developer/utilities/render/debugOutline.js +++ b/scripts/developer/utilities/render/debugOutline.js @@ -55,14 +55,7 @@ var end2 = { } var outlineGroupIndex = 0 - -function setOutlineGroupIndex(index) { - print("Switching to outline group "+index) - outlineGroupIndex = index -} - -window.fromQml.connect(setOutlineGroupIndex); - +var isSelectionAddEnabled = false var renderStates = [{name: "test", end: end}]; var defaultRenderStates = [{name: "test", distance: 20.0, end: end2}]; @@ -71,33 +64,64 @@ var ray = LaserPointers.createLaserPointer({ filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS | RayPick.PICK_AVATARS | RayPick.PICK_INVISIBLE | RayPick.PICK_NONCOLLIDABLE, renderStates: renderStates, defaultRenderStates: defaultRenderStates, - enabled: true + enabled: false }); +function getSelectionName() { + var selectionName = "contextOverlayHighlightList" + + if (outlineGroupIndex>0) { + selectionName += outlineGroupIndex + } + return selectionName +} + +function fromQml(message) { + tokens = message.split(' ') + print("Received '"+message+"' from outline.qml") + if (tokens[0]=="outline") { + outlineGroupIndex = parseInt(tokens[1]) + print("Switching to outline group "+outlineGroupIndex) + } else if (tokens[0]=="pick") { + var isPickingEnabled = tokens[1]=='true' + print("Ray picking set to "+isPickingEnabled.toString()) + if (isPickingEnabled) { + LaserPointers.enableLaserPointer(ray) + } else { + LaserPointers.disableLaserPointer(ray) + } + } else if (tokens[0]=="add") { + isSelectionAddEnabled = tokens[1]=='true' + print("Add to selection set to "+isSelectionAddEnabled.toString()) + if (!isSelectionAddEnabled) { + Selection.clearSelectedItemsList(getSelectionName()) + } + } +} + +window.fromQml.connect(fromQml); + function cleanup() { LaserPointers.removeLaserPointer(ray); } Script.scriptEnding.connect(cleanup); -var prevID = 0; -var prevType = ""; -function update() { +var prevID = 0 +var prevType = "" +var selectedID = 0 +var selectedType = "" +var time = 0 +function update(deltaTime) { + // you have to do this repeatedly because there's a bug but I'll fix it LaserPointers.setRenderState(ray, "test"); var result = LaserPointers.getPrevRayPickResult(ray); - var selectionName = "contextOverlayHighlightList" - - if (outlineGroupIndex>0) { - selectionName += outlineGroupIndex - } + var selectionName = getSelectionName() if (result.type != RayPick.INTERSECTED_NONE) { + time += deltaTime if (result.objectID != prevID) { - if (prevID != 0) { - Selection.removeFromSelectedItemsList(selectionName, prevType, prevID) - } - var typeName = "" if (result.type == RayPick.INTERSECTED_ENTITY) { typeName = "entity" @@ -107,19 +131,28 @@ function update() { typeName = "avatar" } - Selection.addToSelectedItemsList(selectionName, typeName, result.objectID) - //print("OUTLINE " + outlineGroupIndex + " picked type: " + result.type + ", id: " + result.objectID); - prevID = result.objectID; prevType = typeName; + time = 0 + } else if (time>1.0 && prevID!=selectedID) { + if (prevID != 0 && !isSelectionAddEnabled) { + Selection.removeFromSelectedItemsList(selectionName, selectedType, selectedID) + } + selectedID = prevID + selectedType = prevType + Selection.addToSelectedItemsList(selectionName, selectedType, selectedID) + //print("OUTLINE " + outlineGroupIndex + " picked type: " + result.type + ", id: " + result.objectID); } } else { - if (prevID != 0) { + if (prevID != 0 && !isSelectionAddEnabled) { Selection.removeFromSelectedItemsList(selectionName, prevType, prevID) } - prevID = 0; + prevID = 0 + selectedID = 0 + time = 0 } } + Script.update.connect(update); }()); // END LOCAL_SCOPE \ No newline at end of file diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index 578f0857dc..39acd854ac 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -21,12 +21,29 @@ Item { spacing: 8 anchors.fill: parent - CheckBox { - id: debug - text: "View Mask" - checked: root.debugConfig["viewMask"] - onCheckedChanged: { - root.debugConfig["viewMask"] = checked; + Row { + spacing: 8 + CheckBox { + id: debug + text: "View Mask" + checked: root.debugConfig["viewMask"] + onCheckedChanged: { + root.debugConfig["viewMask"] = checked; + } + } + CheckBox { + text: "Hover select" + checked: false + onCheckedChanged: { + sendToScript("pick "+checked.toString()) + } + } + CheckBox { + text: "Add to selection" + checked: false + onCheckedChanged: { + sendToScript("add "+checked.toString()) + } } } @@ -36,7 +53,7 @@ Item { height: 400 onCurrentIndexChanged: { - sendToScript(currentIndex) + sendToScript("outline "+currentIndex) } Tab { From 2d49cc1a7561db478730e131243c8aa9f11cd479 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 20 Oct 2017 12:04:20 +0200 Subject: [PATCH 032/183] Fixed bug in debugOutline script --- scripts/developer/utilities/render/debugOutline.js | 12 +++++++----- .../utilities/render/outlinePage/OutlinePage.qml | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/scripts/developer/utilities/render/debugOutline.js b/scripts/developer/utilities/render/debugOutline.js index c01fbd3c76..72585e07fb 100644 --- a/scripts/developer/utilities/render/debugOutline.js +++ b/scripts/developer/utilities/render/debugOutline.js @@ -56,8 +56,10 @@ var end2 = { var outlineGroupIndex = 0 var isSelectionAddEnabled = false +var isSelectionEnabled = false var renderStates = [{name: "test", end: end}]; var defaultRenderStates = [{name: "test", distance: 20.0, end: end2}]; +var time = 0 var ray = LaserPointers.createLaserPointer({ joint: "Mouse", @@ -83,13 +85,14 @@ function fromQml(message) { outlineGroupIndex = parseInt(tokens[1]) print("Switching to outline group "+outlineGroupIndex) } else if (tokens[0]=="pick") { - var isPickingEnabled = tokens[1]=='true' - print("Ray picking set to "+isPickingEnabled.toString()) - if (isPickingEnabled) { + isSelectionEnabled = tokens[1]=='true' + print("Ray picking set to "+isSelectionEnabled.toString()) + if (isSelectionEnabled) { LaserPointers.enableLaserPointer(ray) } else { LaserPointers.disableLaserPointer(ray) } + time = 0 } else if (tokens[0]=="add") { isSelectionAddEnabled = tokens[1]=='true' print("Add to selection set to "+isSelectionAddEnabled.toString()) @@ -110,7 +113,6 @@ var prevID = 0 var prevType = "" var selectedID = 0 var selectedType = "" -var time = 0 function update(deltaTime) { // you have to do this repeatedly because there's a bug but I'll fix it @@ -119,7 +121,7 @@ function update(deltaTime) { var result = LaserPointers.getPrevRayPickResult(ray); var selectionName = getSelectionName() - if (result.type != RayPick.INTERSECTED_NONE) { + if (isSelectionEnabled && result.type != RayPick.INTERSECTED_NONE) { time += deltaTime if (result.objectID != prevID) { var typeName = "" diff --git a/scripts/developer/utilities/render/outlinePage/OutlinePage.qml b/scripts/developer/utilities/render/outlinePage/OutlinePage.qml index 849f71bdb4..f8976162ab 100644 --- a/scripts/developer/utilities/render/outlinePage/OutlinePage.qml +++ b/scripts/developer/utilities/render/outlinePage/OutlinePage.qml @@ -25,7 +25,7 @@ Item { text: "Glow" checked: root.drawConfig["glow"] onCheckedChanged: { - paramWidgets.drawConfig["glow"] = checked; + root.drawConfig["glow"] = checked; } } ConfigSlider { From 43f9db5b70ea2aa025948ee1e9e693984f09d2e4 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 23 Oct 2017 11:08:13 +0200 Subject: [PATCH 033/183] Fixed small bug due to half texel offset in outline shader --- libraries/render-utils/src/Outline.slh | 10 +++++----- libraries/render-utils/src/OutlineEffect.cpp | 2 +- .../utilities/render/outlinePage/OutlinePage.qml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/render-utils/src/Outline.slh b/libraries/render-utils/src/Outline.slh index fe9594cc12..aeaf20a24a 100644 --- a/libraries/render-utils/src/Outline.slh +++ b/libraries/render-utils/src/Outline.slh @@ -35,16 +35,14 @@ void main(void) { // We offset by half a texel to be centered on the depth sample. If we don't do this // the blur will have a different width between the left / right sides and top / bottom // sides of the silhouette - vec2 halfTexel = getInvWidthHeight() / 2; - vec2 texCoord0 = varTexCoord0+halfTexel; - float outlinedDepth = texture(outlinedDepthMap, texCoord0).x; + float outlinedDepth = texture(outlinedDepthMap, varTexCoord0).x; float intensity = 0.0; if (outlinedDepth < FAR_Z) { // We're not on the far plane so we are on the outlined object, thus no outline to do! <@if IS_FILLED@> // But we need to fill the interior - float sceneDepth = texture(sceneDepthMap, texCoord0).x; + float sceneDepth = texture(sceneDepthMap, varTexCoord0).x; // Transform to linear depth for better precision outlinedDepth = -evalZeyeFromZdb(outlinedDepth); sceneDepth = -evalZeyeFromZdb(sceneDepth); @@ -55,6 +53,8 @@ void main(void) { discard; <@endif@> } else { + vec2 halfTexel = getInvWidthHeight() / 2; + vec2 texCoord0 = varTexCoord0+halfTexel; float weight = 0.0; vec2 deltaUv = params._size / params._blurKernelSize; vec2 lineStartUv = texCoord0 - params._size / 2.0; @@ -72,7 +72,7 @@ void main(void) { { outlinedDepth = texture(outlinedDepthMap, uv).x; intensity += (outlinedDepth < FAR_Z) ? 1.0 : 0.0; - weight += 1.f; + weight += 1.0; } uv.x += deltaUv.x; } diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 8822bcc649..ca67347ecf 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -446,7 +446,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende auto shapePlumber = std::make_shared(); { auto state = std::make_shared(); - state->setDepthTest(true, true, gpu::LESS); + state->setDepthTest(true, true, gpu::LESS_EQUAL); state->setColorWriteMask(false, false, false, false); state->setScissorEnable(true); initMaskPipelines(*shapePlumber, state); diff --git a/scripts/developer/utilities/render/outlinePage/OutlinePage.qml b/scripts/developer/utilities/render/outlinePage/OutlinePage.qml index f8976162ab..a78bf02d3e 100644 --- a/scripts/developer/utilities/render/outlinePage/OutlinePage.qml +++ b/scripts/developer/utilities/render/outlinePage/OutlinePage.qml @@ -33,7 +33,7 @@ Item { integral: false config: root.drawConfig property: "width" - max: 15.0 + max: 5.0 min: 0.0 width: 280 } From 7011fd3731ef9bf10217deac219604bf1d2314f6 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 23 Oct 2017 15:46:11 +0200 Subject: [PATCH 034/183] Removed Mac and Ubuntu warnings --- libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp | 2 ++ libraries/shared/src/ViewFrustum.cpp | 24 +++++++++---------- .../utilities/render/debugOutline.js | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp index 27319e1696..528a2b524b 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp @@ -501,6 +501,7 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E break; } case gpu::COMPRESSED: + case gpu::NUINT2: case gpu::NUM_TYPES: { // quiet compiler Q_UNREACHABLE(); } @@ -551,6 +552,7 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E break; } case gpu::COMPRESSED: + case gpu::NUINT2: case gpu::NUM_TYPES: { // quiet compiler Q_UNREACHABLE(); } diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index 747b39f79e..f3eb165c51 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -590,18 +590,18 @@ bool ViewFrustum::getProjectedRect(const AABox& box, glm::vec2& bottomLeft, glm: std::array vertices; std::array boxEdges{ - Edge(BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR), - Edge(TOP_LEFT_NEAR, TOP_RIGHT_NEAR), - Edge(BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR), - Edge(TOP_LEFT_FAR, TOP_RIGHT_FAR), - Edge(BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR), - Edge(BOTTOM_LEFT_FAR, TOP_LEFT_FAR), - Edge(BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR), - Edge(BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR), - Edge(BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR), - Edge(TOP_LEFT_NEAR, TOP_LEFT_FAR), - Edge(BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR), - Edge(TOP_RIGHT_NEAR, TOP_RIGHT_FAR) + Edge{BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR}, + Edge{TOP_LEFT_NEAR, TOP_RIGHT_NEAR}, + Edge{BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR}, + Edge{TOP_LEFT_FAR, TOP_RIGHT_FAR}, + Edge{BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, + Edge{BOTTOM_LEFT_FAR, TOP_LEFT_FAR}, + Edge{BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR}, + Edge{BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR}, + Edge{BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR}, + Edge{TOP_LEFT_NEAR, TOP_LEFT_FAR}, + Edge{BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR}, + Edge{TOP_RIGHT_NEAR, TOP_RIGHT_FAR} }; std::array distancesToNearPlane; std::bitset areVerticesInside; diff --git a/scripts/developer/utilities/render/debugOutline.js b/scripts/developer/utilities/render/debugOutline.js index 72585e07fb..ce32d61e1b 100644 --- a/scripts/developer/utilities/render/debugOutline.js +++ b/scripts/developer/utilities/render/debugOutline.js @@ -143,7 +143,7 @@ function update(deltaTime) { selectedID = prevID selectedType = prevType Selection.addToSelectedItemsList(selectionName, selectedType, selectedID) - //print("OUTLINE " + outlineGroupIndex + " picked type: " + result.type + ", id: " + result.objectID); + print("OUTLINE " + outlineGroupIndex + " picked type: " + result.type + ", id: " + result.objectID); } } else { if (prevID != 0 && !isSelectionAddEnabled) { From 68ed061ce59ae59a5c88444b7f3349ae02967b40 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 23 Oct 2017 16:49:42 +0200 Subject: [PATCH 035/183] Again, fix for Mac warning --- libraries/shared/src/ViewFrustum.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index f3eb165c51..dcbfd83ec7 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -589,7 +589,7 @@ bool ViewFrustum::getProjectedRect(const AABox& box, glm::vec2& bottomLeft, glm: const int MAX_VERTEX_COUNT = VERTEX_COUNT + 4 + 2; std::array vertices; - std::array boxEdges{ + std::array boxEdges{ { Edge{BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR}, Edge{TOP_LEFT_NEAR, TOP_RIGHT_NEAR}, Edge{BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR}, @@ -602,7 +602,7 @@ bool ViewFrustum::getProjectedRect(const AABox& box, glm::vec2& bottomLeft, glm: Edge{TOP_LEFT_NEAR, TOP_LEFT_FAR}, Edge{BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR}, Edge{TOP_RIGHT_NEAR, TOP_RIGHT_FAR} - }; + } }; std::array distancesToNearPlane; std::bitset areVerticesInside; int vertexCount = VERTEX_COUNT; From 99ec2aec4a8c63a4d59525fe3e718562d9ec6ca5 Mon Sep 17 00:00:00 2001 From: vladest Date: Mon, 23 Oct 2017 20:44:13 +0200 Subject: [PATCH 036/183] Prevent scripts log window open several times --- interface/src/Application.cpp | 18 ++++++++++++++---- interface/src/Application.h | 4 ++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0b99ce5004..d03ff8f1da 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5800,6 +5800,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe ClipboardScriptingInterface* clipboardScriptable = new ClipboardScriptingInterface(); scriptEngine->registerGlobalObject("Clipboard", clipboardScriptable); connect(scriptEngine.data(), &ScriptEngine::finished, clipboardScriptable, &ClipboardScriptingInterface::deleteLater); + connect(scriptEngine.data(), &ScriptEngine::finished, this, &Application::cleanupRunningScripts); scriptEngine->registerGlobalObject("Overlays", &_overlays); qScriptRegisterMetaType(scriptEngine.data(), OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue); @@ -6213,10 +6214,15 @@ void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const } void Application::showScriptLogs() { - auto scriptEngines = DependencyManager::get(); - QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation(); - defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js"); - scriptEngines->loadScript(defaultScriptsLoc.toString()); + if (!_runningScripts.contains("debugWindow.js")) { + auto scriptEngines = DependencyManager::get(); + QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation(); + defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js"); + ScriptEnginePointer sePointer = scriptEngines->loadScript(defaultScriptsLoc.toString()); + _runningScripts["debugWindow.js"] = sePointer; + } else { + qWarning() << "Scripts Log already running"; + } } void Application::showAssetServerWidget(QString filePath) { @@ -7311,6 +7317,10 @@ void Application::switchDisplayMode() { _previousHMDWornStatus = currentHMDWornStatus; } +void Application::cleanupRunningScripts(const QString &fileNameString, ScriptEnginePointer) { + _runningScripts.remove(QUrl(fileNameString).fileName()); +} + void Application::startHMDStandBySession() { _autoSwitchDisplayModeSupportedHMDPlugin->startStandBySession(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index b6c09bbd87..65b6dd2c9e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -451,6 +451,8 @@ private slots: void handleSandboxStatus(QNetworkReply* reply); void switchDisplayMode(); + + void cleanupRunningScripts(const QString& fileNameString, ScriptEnginePointer); private: static void initDisplay(); void init(); @@ -720,5 +722,7 @@ private: std::atomic _pendingIdleEvent { false }; std::atomic _pendingRenderEvent { false }; + + QHash _runningScripts; }; #endif // hifi_Application_h From c55f93813237d2a3010237b0e5dcc6ded12f1f82 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 24 Oct 2017 22:09:00 +0200 Subject: [PATCH 037/183] Code style fix --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d03ff8f1da..05ec8a5df1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7317,7 +7317,7 @@ void Application::switchDisplayMode() { _previousHMDWornStatus = currentHMDWornStatus; } -void Application::cleanupRunningScripts(const QString &fileNameString, ScriptEnginePointer) { +void Application::cleanupRunningScripts(const QString& fileNameString, ScriptEnginePointer) { _runningScripts.remove(QUrl(fileNameString).fileName()); } From b820f397fcba7488cb316d9f6d7ef9a1c6ba8cf7 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 26 Oct 2017 08:39:22 -0700 Subject: [PATCH 038/183] Fix zero-divide. --- libraries/model/src/model/Haze.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/libraries/model/src/model/Haze.h b/libraries/model/src/model/Haze.h index fe606bf083..29eedcd372 100644 --- a/libraries/model/src/model/Haze.h +++ b/libraries/model/src/model/Haze.h @@ -30,10 +30,25 @@ namespace model { -LOG_P_005 / hazeRange_m.z); } - inline float convertHazeRangeToHazeRangeFactor(const float hazeRange_m) { return (-LOG_P_005 / hazeRange_m); } + + inline float convertHazeRangeToHazeRangeFactor(const float hazeRange_m) { + // limit range to no less than 1.0 metres + if (hazeRange_m < 1.0f) { + return -LOG_P_005; + } + else { + return -LOG_P_005 / hazeRange_m; + } + } inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeAltitude_m) { - return -LOG_P_005 / hazeAltitude_m; + // limit altitude to no less than 1.0 metres + if (hazeAltitude_m < 1.0) { + return -LOG_P_005; + } + else { + return -LOG_P_005 / hazeAltitude_m; + } } // Derivation (s is the proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5 From c5c996f18677dc598e3b4c94d56ff0bf7c9b9446 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 26 Oct 2017 09:21:38 -0700 Subject: [PATCH 039/183] Cleanup. --- libraries/model/src/model/Haze.h | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/libraries/model/src/model/Haze.h b/libraries/model/src/model/Haze.h index 29eedcd372..2ffdd2333b 100644 --- a/libraries/model/src/model/Haze.h +++ b/libraries/model/src/model/Haze.h @@ -16,8 +16,8 @@ #include "NumericalConstants.h" namespace model { - const float LOG_P_005 = (float)log(0.05); - const float LOG_P_05 = (float)log(0.5); + const float LOG_P_005 = logf(0.05f); + const float LOG_P_05 = logf(0.5f); // Derivation (d is distance, b is haze coefficient, f is attenuation, solve for f = 0.05 // f = exp(-d * b) @@ -30,26 +30,10 @@ namespace model { -LOG_P_005 / hazeRange_m.z); } + // limit range and altitude to no less than 1.0 metres + inline float convertHazeRangeToHazeRangeFactor(const float hazeRange_m) { return -LOG_P_005 / glm::max(hazeRange_m, 1.0f); } - inline float convertHazeRangeToHazeRangeFactor(const float hazeRange_m) { - // limit range to no less than 1.0 metres - if (hazeRange_m < 1.0f) { - return -LOG_P_005; - } - else { - return -LOG_P_005 / hazeRange_m; - } - } - - inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeAltitude_m) { - // limit altitude to no less than 1.0 metres - if (hazeAltitude_m < 1.0) { - return -LOG_P_005; - } - else { - return -LOG_P_005 / hazeAltitude_m; - } - } + inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeAltitude_m) { return -LOG_P_005 / glm::max(hazeAltitude_m, 1.0f); } // Derivation (s is the proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5 // s = dot(lookAngle, sunAngle) = cos(a) @@ -57,7 +41,7 @@ namespace model { // log(m) = p * log(s) // p = log(m) / log(s) inline float convertDirectionalLightAngleToPower(const float directionalLightAngle) { - return LOG_P_05 / (float)log(cos(RADIANS_PER_DEGREE * directionalLightAngle)); + return LOG_P_05 / logf(cosf(RADIANS_PER_DEGREE * directionalLightAngle)); } const glm::vec3 initialHazeColor{ 0.5f, 0.6f, 0.7f }; From ddd25da430a52d87c0e9d4fb2798205668b1dc07 Mon Sep 17 00:00:00 2001 From: beholder Date: Thu, 26 Oct 2017 17:35:28 +0300 Subject: [PATCH 040/183] 8315 Stylus appears in wrong place on hand --- .../controllerModules/tabletStylusInput.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/scripts/system/controllers/controllerModules/tabletStylusInput.js b/scripts/system/controllers/controllerModules/tabletStylusInput.js index beb86d0ef4..46b630d023 100644 --- a/scripts/system/controllers/controllerModules/tabletStylusInput.js +++ b/scripts/system/controllers/controllerModules/tabletStylusInput.js @@ -154,6 +154,25 @@ Script.include("/~/system/libraries/controllers.js"); this.showStylus = function() { if (this.stylus) { + var X_ROT_NEG_90 = { x: -0.70710678, y: 0, z: 0, w: 0.70710678 }; + var modelOrientation = Quat.multiply(this.stylusTip.orientation, X_ROT_NEG_90); + var modelOrientationAngles = Quat.safeEulerAngles(modelOrientation); + + var rotation = Overlays.getProperty(this.stylus, "rotation"); + var rotationAngles = Quat.safeEulerAngles(rotation); + + if(!Vec3.withinEpsilon(modelOrientationAngles, rotationAngles, 1)) { + var modelPositionOffset = Vec3.multiplyQbyV(modelOrientation, { x: 0, y: 0, z: MyAvatar.sensorToWorldScale * -WEB_STYLUS_LENGTH / 2 }); + + var updatedStylusProperties = { + position: Vec3.sum(this.stylusTip.position, modelPositionOffset), + rotation: modelOrientation, + dimensions: Vec3.multiply(MyAvatar.sensorToWorldScale, { x: 0.01, y: 0.01, z: WEB_STYLUS_LENGTH }), + }; + + Overlays.editOverlay(this.stylus, updatedStylusProperties); + } + return; } From 901e14571211dd2a769aa4cdf96996838603ad26 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 26 Oct 2017 22:57:33 -0700 Subject: [PATCH 041/183] remove redundant dimensionsChanged() --- libraries/entities/src/EntityItem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 008ec9769f..059e6bf151 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1754,7 +1754,6 @@ void EntityItem::updateDimensions(const glm::vec3& value) { setDimensions(value); markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS); _queryAACubeSet = false; - dimensionsChanged(); } } From 474609dabf1cab9d65c886281dfa49e56b14f9f6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 26 Oct 2017 22:58:24 -0700 Subject: [PATCH 042/183] enforce dimensions of Circles and Quads --- libraries/entities/src/ShapeEntityItem.cpp | 44 ++++++++++++---------- libraries/entities/src/ShapeEntityItem.h | 2 + 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 9a1a500a54..8c7d1576e1 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -104,6 +104,14 @@ void ShapeEntityItem::setShape(const entity::Shape& shape) { case entity::Shape::Sphere: _type = EntityTypes::Sphere; break; + case entity::Shape::Circle: + // Circle is implicitly flat so we enforce flat dimensions + setDimensions(getDimensions()); + break; + case entity::Shape::Quad: + // Quad is implicitly flat so we enforce flat dimensions + setDimensions(getDimensions()); + break; default: _type = EntityTypes::Shape; break; @@ -196,6 +204,18 @@ void ShapeEntityItem::setColor(const QColor& value) { setAlpha(value.alpha()); } +void ShapeEntityItem::setDimensions(const glm::vec3& value) { + const float MAX_FLAT_DIMENSION = 0.0001f; + if ((_shape == entity::Shape::Circle || _shape == entity::Shape::Quad) && value.y > MAX_FLAT_DIMENSION) { + // enforce flatness in Y + glm::vec3 newDimensions = value; + newDimensions.y = MAX_FLAT_DIMENSION; + EntityItem::setDimensions(newDimensions); + } else { + EntityItem::setDimensions(value); + } +} + bool ShapeEntityItem::supportsDetailedRayIntersection() const { return _shape == entity::Sphere; } @@ -249,13 +269,8 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { const glm::vec3 entityDimensions = getDimensions(); switch (_shape){ - case entity::Shape::Quad: { - // Not in GeometryCache::buildShapes, unsupported. - _collisionShapeType = SHAPE_TYPE_ELLIPSOID; - //TODO WL21389: Add a SHAPE_TYPE_QUAD ShapeType and treat - // as a special box (later if desired support) - } - break; + case entity::Shape::Quad: + // Quads collide like flat Cubes case entity::Shape::Cube: { _collisionShapeType = SHAPE_TYPE_BOX; } @@ -275,19 +290,10 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { } } break; - case entity::Shape::Circle: { - _collisionShapeType = SHAPE_TYPE_CIRCLE; - } - break; + case entity::Shape::Circle: + // Circles collide like flat Cylinders case entity::Shape::Cylinder: { _collisionShapeType = SHAPE_TYPE_CYLINDER_Y; - // TODO WL21389: determine if rotation is axis-aligned - //const Transform::Quat & rot = _transform.getRotation(); - - // TODO WL21389: some way to tell apart SHAPE_TYPE_CYLINDER_Y, _X, _Z based on rotation and - // hull ( or dimensions, need circular cross section) - // Should allow for minor variance along axes? - } break; case entity::Shape::Cone: { @@ -330,7 +336,7 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { case entity::Shape::Torus: { // Not in GeometryCache::buildShapes, unsupported. _collisionShapeType = SHAPE_TYPE_ELLIPSOID; - //TODO WL21389: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later if desired support) + //TODO handle this shape more correctly } break; default: { diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index a88a2098e9..20e36c88e6 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -80,6 +80,8 @@ public: const rgbColor& getColor() const { return _color; } void setColor(const rgbColor& value); + void setDimensions(const glm::vec3& value) override; + xColor getXColor() const; void setColor(const xColor& value); From 2710dca37c70fa331f10ee80ad1232155d113961 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 26 Oct 2017 22:58:50 -0700 Subject: [PATCH 043/183] fix rendering of Circles and Quads --- libraries/render-utils/src/GeometryCache.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index f35fb9f830..fa00737e3c 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -482,8 +482,10 @@ void GeometryCache::buildShapes() { using namespace geometry; auto vertexBuffer = std::make_shared(); auto indexBuffer = std::make_shared(); - // Cube + // Cube setupFlatShape(_shapes[Cube], geometry::cube(), _shapeVertices, _shapeIndices); + //Quad renders as flat Cube + setupFlatShape(_shapes[Quad], geometry::cube(), _shapeVertices, _shapeIndices); // Tetrahedron setupFlatShape(_shapes[Tetrahedron], geometry::tetrahedron(), _shapeVertices, _shapeIndices); // Icosahedron @@ -524,12 +526,10 @@ void GeometryCache::buildShapes() { extrudePolygon<64>(_shapes[Cylinder], _shapeVertices, _shapeIndices); //Cone, extrudePolygon<64>(_shapes[Cone], _shapeVertices, _shapeIndices, true); - //Circle - drawCircle(_shapes[Circle], _shapeVertices, _shapeIndices); + // Circle renders as flat Cylinder + extrudePolygon<64>(_shapes[Circle], _shapeVertices, _shapeIndices); // Not implemented yet: - //Quad, - //Torus, - + //Torus, } const GeometryCache::ShapeData * GeometryCache::getShapeData(const Shape shape) const { From 5ed58d5e5dc6012ed054f72ba3b60f6d0c3a7900 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 26 Oct 2017 22:59:25 -0700 Subject: [PATCH 044/183] enable Quad in ShapeEntityItem properties --- scripts/system/html/entityProperties.html | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 2d5dd35e66..d2c33984ff 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -59,6 +59,7 @@ +
From 45e571dd02cfed91b8a4c7e954b7693fd1b11617 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 26 Oct 2017 08:16:41 -0700 Subject: [PATCH 045/183] cleanup ShapeInfo::getHash() --- libraries/physics/src/ShapeManager.cpp | 8 +- libraries/physics/src/ShapeManager.h | 10 +- libraries/shared/src/HashKey.cpp | 67 +++++++++++++ libraries/shared/src/HashKey.h | 52 ++++++++++ libraries/shared/src/ShapeInfo.cpp | 119 +++++------------------ libraries/shared/src/ShapeInfo.h | 6 +- tests/physics/src/ShapeInfoTests.cpp | 129 +++++++++---------------- tests/physics/src/ShapeInfoTests.h | 4 - 8 files changed, 202 insertions(+), 193 deletions(-) create mode 100644 libraries/shared/src/HashKey.cpp create mode 100644 libraries/shared/src/HashKey.h diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index 77716f671b..97b9e5dab1 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -32,7 +32,7 @@ const btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { if (info.getType() == SHAPE_TYPE_NONE) { return nullptr; } - DoubleHashKey key = info.getHash(); + HashKey key = info.getHash(); ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { shapeRef->refCount++; @@ -50,7 +50,7 @@ const btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { } // private helper method -bool ShapeManager::releaseShapeByKey(const DoubleHashKey& key) { +bool ShapeManager::releaseShapeByKey(const HashKey& key) { ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { if (shapeRef->refCount > 0) { @@ -88,7 +88,7 @@ bool ShapeManager::releaseShape(const btCollisionShape* shape) { void ShapeManager::collectGarbage() { int numShapes = _pendingGarbage.size(); for (int i = 0; i < numShapes; ++i) { - DoubleHashKey& key = _pendingGarbage[i]; + HashKey& key = _pendingGarbage[i]; ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef && shapeRef->refCount == 0) { ShapeFactory::deleteShape(shapeRef->shape); @@ -99,7 +99,7 @@ void ShapeManager::collectGarbage() { } int ShapeManager::getNumReferences(const ShapeInfo& info) const { - DoubleHashKey key = info.getHash(); + HashKey key = info.getHash(); const ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { return shapeRef->refCount; diff --git a/libraries/physics/src/ShapeManager.h b/libraries/physics/src/ShapeManager.h index ed81b5e8f8..6ec3573b53 100644 --- a/libraries/physics/src/ShapeManager.h +++ b/libraries/physics/src/ShapeManager.h @@ -17,7 +17,7 @@ #include -#include "DoubleHashKey.h" +#include "HashKey.h" class ShapeManager { public: @@ -41,18 +41,18 @@ public: bool hasShape(const btCollisionShape* shape) const; private: - bool releaseShapeByKey(const DoubleHashKey& key); + bool releaseShapeByKey(const HashKey& key); class ShapeReference { public: int refCount; const btCollisionShape* shape; - DoubleHashKey key; + HashKey key; ShapeReference() : refCount(0), shape(nullptr) {} }; - btHashMap _shapeMap; - btAlignedObjectArray _pendingGarbage; + btHashMap _shapeMap; + btAlignedObjectArray _pendingGarbage; }; #endif // hifi_ShapeManager_h diff --git a/libraries/shared/src/HashKey.cpp b/libraries/shared/src/HashKey.cpp new file mode 100644 index 0000000000..488eccb1bf --- /dev/null +++ b/libraries/shared/src/HashKey.cpp @@ -0,0 +1,67 @@ +// +// HashKey.cpp +// libraries/shared/src +// +// Created by Andrew Meadows 2017.10.25 +// Copyright 2017 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 "HashKey.h" + +#include "NumericalConstants.h" + + +const uint8_t NUM_PRIMES = 64; +const uint64_t PRIMES[] = { + 4194301UL, 4194287UL, 4194277UL, 4194271UL, 4194247UL, 4194217UL, 4194199UL, 4194191UL, + 4194187UL, 4194181UL, 4194173UL, 4194167UL, 4194143UL, 4194137UL, 4194131UL, 4194107UL, + 4194103UL, 4194023UL, 4194011UL, 4194007UL, 4193977UL, 4193971UL, 4193963UL, 4193957UL, + 4193939UL, 4193929UL, 4193909UL, 4193869UL, 4193807UL, 4193803UL, 4193801UL, 4193789UL, + 4193759UL, 4193753UL, 4193743UL, 4193701UL, 4193663UL, 4193633UL, 4193573UL, 4193569UL, + 4193551UL, 4193549UL, 4193531UL, 4193513UL, 4193507UL, 4193459UL, 4193447UL, 4193443UL, + 4193417UL, 4193411UL, 4193393UL, 4193389UL, 4193381UL, 4193377UL, 4193369UL, 4193359UL, + 4193353UL, 4193327UL, 4193309UL, 4193303UL, 4193297UL, 4193279UL, 4193269UL, 4193263UL +}; + + +// this hash function inspired by Squirrel Eiserloh's GDC2017 talk: "Noise-Based RNG" +uint64_t squirrel3_64(uint64_t data, uint8_t primeIndex) { + constexpr uint64_t BIT_NOISE1 = 2760725261486592643UL; + constexpr uint64_t BIT_NOISE2 = 6774464464027632833UL; + constexpr uint64_t BIT_NOISE3 = 5545331650366059883UL; + + // blend prime numbers into the hash to prevent dupes + // when hashing the same set of numbers in a different order + uint64_t hash = PRIMES[primeIndex % NUM_PRIMES] * data; + hash *= BIT_NOISE1; + hash ^= (hash >> 16); + hash += BIT_NOISE2; + hash ^= (hash << 16); + hash *= BIT_NOISE3; + return hash ^ (hash >> 16); +} + +constexpr float QUANTIZED_VALUES_PER_METER = 250.0f; + +// static +float HashKey::getNumQuantizedValuesPerMeter() { + return QUANTIZED_VALUES_PER_METER; +} + +void HashKey::hashUint64(uint64_t data) { + _hash += squirrel3_64(data, ++_hashCount); +} + +void HashKey::hashFloat(float data) { + _hash += squirrel3_64((uint64_t)((int64_t)(data * QUANTIZED_VALUES_PER_METER)), ++_hashCount); +} + +void HashKey::hashVec3(const glm::vec3& data) { + _hash += squirrel3_64((uint64_t)((int64_t)(data[0] * QUANTIZED_VALUES_PER_METER)), ++_hashCount); + _hash *= squirrel3_64((uint64_t)((int64_t)(data[1] * QUANTIZED_VALUES_PER_METER)), ++_hashCount); + _hash ^= squirrel3_64((uint64_t)((int64_t)(data[2] * QUANTIZED_VALUES_PER_METER)), ++_hashCount); +} + diff --git a/libraries/shared/src/HashKey.h b/libraries/shared/src/HashKey.h new file mode 100644 index 0000000000..5fce182084 --- /dev/null +++ b/libraries/shared/src/HashKey.h @@ -0,0 +1,52 @@ +// +// HashKey.h +// libraries/shared/src +// +// Created by Andrew Meadows 2017.10.25 +// Copyright 2017 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 +// + +#ifndef hifi_HashKey_h +#define hifi_HashKey_h + +#include +#include + +#include + + +// HashKey for use with btHashMap which requires a particular API for its keys. In particular it +// requires its Key to implement these methods: +// +// bool Key::equals() +// int32_t Key::getHash() +// +// The important thing about the HashKey implementation is that while getHash() returns 32-bits, +// internally HashKey stores a 64-bit hash which is used for the equals() comparison. This allows +// btHashMap to insert "dupe" 32-bit keys to different "values". + +class HashKey { +public: + static float getNumQuantizedValuesPerMeter(); + + // These two methods are required by btHashMap. + bool equals(const HashKey& other) const { return _hash == other._hash; } + int32_t getHash() const { return (int32_t)((uint32_t)_hash); } + + void clear() { _hash = _hashCount = 0; } + bool isNull() const { return _hash == 0 && _hashCount == 0; } + void hashUint64(uint64_t data); + void hashFloat(float data); + void hashVec3(const glm::vec3& data); + + uint64_t getHash64() const { return _hash; } // for debug/test purposes + +private: + uint64_t _hash { 0 }; + uint8_t _hashCount { 0 }; +}; + +#endif // hifi_HashKey_h diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 36ce38335a..8cdc4bcf14 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -53,7 +53,7 @@ void ShapeInfo::clear() { _triangleIndices.clear(); _halfExtents = glm::vec3(0.0f); _offset = glm::vec3(0.0f); - _doubleHashKey.clear(); + _hashKey.clear(); _type = SHAPE_TYPE_NONE; } @@ -87,14 +87,14 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString default: break; } - _doubleHashKey.clear(); + _hashKey.clear(); } void ShapeInfo::setBox(const glm::vec3& halfExtents) { _url = ""; _type = SHAPE_TYPE_BOX; setHalfExtents(halfExtents); - _doubleHashKey.clear(); + _hashKey.clear(); } void ShapeInfo::setSphere(float radius) { @@ -102,12 +102,12 @@ void ShapeInfo::setSphere(float radius) { _type = SHAPE_TYPE_SPHERE; radius = glm::max(radius, MIN_HALF_EXTENT); _halfExtents = glm::vec3(radius); - _doubleHashKey.clear(); + _hashKey.clear(); } void ShapeInfo::setPointCollection(const ShapeInfo::PointCollection& pointCollection) { _pointCollection = pointCollection; - _doubleHashKey.clear(); + _hashKey.clear(); } void ShapeInfo::setCapsuleY(float radius, float halfHeight) { @@ -116,12 +116,12 @@ void ShapeInfo::setCapsuleY(float radius, float halfHeight) { radius = glm::max(radius, MIN_HALF_EXTENT); halfHeight = glm::max(halfHeight, 0.0f); _halfExtents = glm::vec3(radius, halfHeight, radius); - _doubleHashKey.clear(); + _hashKey.clear(); } void ShapeInfo::setOffset(const glm::vec3& offset) { _offset = offset; - _doubleHashKey.clear(); + _hashKey.clear(); } uint32_t ShapeInfo::getNumSubShapes() const { @@ -256,119 +256,46 @@ bool ShapeInfo::contains(const glm::vec3& point) const { } } -const DoubleHashKey& ShapeInfo::getHash() const { +const HashKey& ShapeInfo::getHash() const { // NOTE: we cache the key so we only ever need to compute it once for any valid ShapeInfo instance. - if (_doubleHashKey.isNull() && _type != SHAPE_TYPE_NONE) { - bool useOffset = glm::length2(_offset) > MIN_SHAPE_OFFSET * MIN_SHAPE_OFFSET; + if (_hashKey.isNull() && _type != SHAPE_TYPE_NONE) { // The key is not yet cached therefore we must compute it. - // compute hash1 - // TODO?: provide lookup table for hash/hash2 of _type rather than recompute? - uint32_t primeIndex = 0; - _doubleHashKey.computeHash((uint32_t)_type, primeIndex++); - + _hashKey.hashUint64((uint64_t)_type); if (_type != SHAPE_TYPE_SIMPLE_HULL) { - // compute hash1 - uint32_t hash = _doubleHashKey.getHash(); - for (int j = 0; j < 3; ++j) { - // NOTE: 0.49f is used to bump the float up almost half a millimeter - // so the cast to int produces a round() effect rather than a floor() - hash ^= DoubleHashKey::hashFunction( - (uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), - primeIndex++); - if (useOffset) { - hash ^= DoubleHashKey::hashFunction( - (uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f), - primeIndex++); - } - } - _doubleHashKey.setHash(hash); - - // compute hash2 - hash = _doubleHashKey.getHash2(); - for (int j = 0; j < 3; ++j) { - // NOTE: 0.49f is used to bump the float up almost half a millimeter - // so the cast to int produces a round() effect rather than a floor() - uint32_t floatHash = DoubleHashKey::hashFunction2( - (uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f)); - if (useOffset) { - floatHash ^= DoubleHashKey::hashFunction2( - (uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f)); - } - hash += ~(floatHash << 17); - hash ^= (floatHash >> 11); - hash += (floatHash << 4); - hash ^= (floatHash >> 7); - hash += ~(floatHash << 10); - hash = (hash << 16) | (hash >> 16); - } - _doubleHashKey.setHash2(hash); + _hashKey.hashVec3(_halfExtents); + _hashKey.hashVec3(_offset); } else { - + // TODO: we could avoid hashing all of these points if we were to supply the ShapeInfo with a unique + // descriptive string. Shapes that are uniquely described by their type and URL could just put their + // url in the description. assert(_pointCollection.size() == (size_t)1); const PointList & points = _pointCollection.back(); const int numPoints = (int)points.size(); - uint32_t hash = _doubleHashKey.getHash(); - uint32_t hash2 = _doubleHashKey.getHash2(); - for (int pointIndex = 0; pointIndex < numPoints; ++pointIndex) { - // compute hash1 & 2 - const glm::vec3 &curPoint = points[pointIndex]; - for (int vecCompIndex = 0; vecCompIndex < 3; ++vecCompIndex) { - - // NOTE: 0.49f is used to bump the float up almost half a millimeter - // so the cast to int produces a round() effect rather than a floor() - uint32_t valueToHash = (uint32_t)(curPoint[vecCompIndex] * MILLIMETERS_PER_METER + copysignf(1.0f, curPoint[vecCompIndex]) * 0.49f); - - hash ^= DoubleHashKey::hashFunction(valueToHash, primeIndex++); - uint32_t floatHash = DoubleHashKey::hashFunction2(valueToHash); - - if (useOffset) { - - const uint32_t offsetValToHash = (uint32_t)(_offset[vecCompIndex] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[vecCompIndex])* 0.49f); - - hash ^= DoubleHashKey::hashFunction(offsetValToHash, primeIndex++); - floatHash ^= DoubleHashKey::hashFunction2(offsetValToHash); - } - - hash2 += ~(floatHash << 17); - hash2 ^= (floatHash >> 11); - hash2 += (floatHash << 4); - hash2 ^= (floatHash >> 7); - hash2 += ~(floatHash << 10); - hash2 = (hash2 << 16) | (hash2 >> 16); - } + for (int i = 0; i < numPoints; ++i) { + _hashKey.hashVec3(points[i]); } - - _doubleHashKey.setHash(hash); - _doubleHashKey.setHash2(hash2); } QString url = _url.toString(); if (!url.isEmpty()) { - // fold the urlHash into both parts QByteArray baUrl = url.toLocal8Bit(); uint32_t urlHash = qChecksum(baUrl.data(), baUrl.size()); - _doubleHashKey.setHash(_doubleHashKey.getHash() ^ urlHash); - _doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ urlHash); + _hashKey.hashUint64((uint64_t)urlHash); } - uint32_t numHulls = 0; if (_type == SHAPE_TYPE_COMPOUND || _type == SHAPE_TYPE_SIMPLE_COMPOUND) { - numHulls = (uint32_t)_pointCollection.size(); + uint64_t numHulls = (uint64_t)_pointCollection.size(); + _hashKey.hashUint64(numHulls); } else if (_type == SHAPE_TYPE_SIMPLE_HULL) { - numHulls = 1; - } - if (numHulls > 0) { - uint32_t hash = DoubleHashKey::hashFunction(numHulls, primeIndex++); - _doubleHashKey.setHash(_doubleHashKey.getHash() ^ hash); - hash = DoubleHashKey::hashFunction2(numHulls); - _doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ hash); + _hashKey.hashUint64(1); } } - return _doubleHashKey; + return _hashKey; } void ShapeInfo::setHalfExtents(const glm::vec3& halfExtents) { _halfExtents = glm::max(halfExtents, glm::vec3(MIN_HALF_EXTENT)); + _hashKey.clear(); } diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index d658b936a3..069241e29d 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -18,7 +18,7 @@ #include #include -#include "DoubleHashKey.h" +#include "HashKey.h" const float MIN_SHAPE_OFFSET = 0.001f; // offsets less than 1mm will be ignored @@ -89,7 +89,7 @@ public: /// For compound shapes it will only return whether it is inside the bounding box bool contains(const glm::vec3& point) const; - const DoubleHashKey& getHash() const; + const HashKey& getHash() const; protected: void setHalfExtents(const glm::vec3& halfExtents); @@ -99,7 +99,7 @@ protected: TriangleIndices _triangleIndices; glm::vec3 _halfExtents = glm::vec3(0.0f); glm::vec3 _offset = glm::vec3(0.0f); - mutable DoubleHashKey _doubleHashKey; + mutable HashKey _hashKey; ShapeType _type = SHAPE_TYPE_NONE; }; diff --git a/tests/physics/src/ShapeInfoTests.cpp b/tests/physics/src/ShapeInfoTests.cpp index c6a19084a2..79d0092dc3 100644 --- a/tests/physics/src/ShapeInfoTests.cpp +++ b/tests/physics/src/ShapeInfoTests.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -23,108 +23,78 @@ QTEST_MAIN(ShapeInfoTests) +// Enable this to manually run testHashCollisions +// (NOT a regular unit test; takes ~40 secs to run on an i7) +//#define MANUAL_TEST true + void ShapeInfoTests::testHashFunctions() { #if MANUAL_TEST int maxTests = 10000000; ShapeInfo info; - btHashMap hashes; + btHashMap hashes; - uint32_t bits[32]; - uint32_t masks[32]; - for (int i = 0; i < 32; ++i) { + const int32_t NUM_HASH_BITS = 32; + uint32_t bits[NUM_HASH_BITS]; + uint32_t masks[NUM_HASH_BITS]; + for (int i = 0; i < NUM_HASH_BITS; ++i) { bits[i] = 0; - masks[i] = 1U << i; + masks[i] = 1UL << i; } - float deltaLength = 0.002f; - float endLength = 100.0f; + float deltaLength = 1.0f / (HashKey::getNumQuantizedValuesPerMeter() - 3.0f); + float endLength = 2000.0f * deltaLength; int numSteps = (int)(endLength / deltaLength); int testCount = 0; int numCollisions = 0; btClock timer; - for (int x = 1; x < numSteps && testCount < maxTests; ++x) { - float radiusX = (float)x * deltaLength; + for (int i = 1; i < numSteps && testCount < maxTests; ++i) { + float radiusX = (float)i * deltaLength; + int32_t* hashPtr; // test sphere info.setSphere(radiusX); ++testCount; - DoubleHashKey key = info.getHash(); - uint32_t* hashPtr = hashes.find(key.getHash()); - if (hashPtr && *hashPtr == key.getHash2()) { - std::cout << testCount << " hash collision radiusX = " << radiusX - << " h1 = 0x" << std::hex << key.getHash() - << " h2 = 0x" << std::hex << key.getHash2() - << std::endl; + HashKey key = info.getHash(); + hashPtr = hashes.find(key); + if (hashPtr) { + std::cout << testCount << " hash collision sphere radius = " << radiusX + << " h = 0x" << std::hex << key.getHash() << " : 0x" << *hashPtr + << std::dec << std::endl; ++numCollisions; assert(false); } else { - hashes.insert(key.getHash(), key.getHash2()); + hashes.insert(key, key.getHash()); } - for (int k = 0; k < 32; ++k) { - if (masks[k] & key.getHash2()) { - ++bits[k]; + // track bit distribution counts to evaluate hash function randomness + for (int j = 0; j < NUM_HASH_BITS; ++j) { + if (masks[j] & key.getHash()) { + ++bits[j]; } } for (int y = 1; y < numSteps && testCount < maxTests; ++y) { float radiusY = (float)y * deltaLength; - /* TODO: reimplement Cylinder and Capsule shapes - // test cylinder and capsule - int types[] = { CYLINDER_SHAPE_PROXYTYPE, CAPSULE_SHAPE_PROXYTYPE }; - for (int i = 0; i < 2; ++i) { - switch(types[i]) { - case CYLINDER_SHAPE_PROXYTYPE: { - info.setCylinder(radiusX, radiusY); - break; - } - case CAPSULE_SHAPE_PROXYTYPE: { - info.setCapsuleY(radiusX, radiusY); - break; - } - } - - ++testCount; - key = info.getHash(); - hashPtr = hashes.find(key.getHash()); - if (hashPtr && *hashPtr == key.getHash2()) { - std::cout << testCount << " hash collision radiusX = " << radiusX << " radiusY = " << radiusY - << " h1 = 0x" << std::hex << key.getHash() - << " h2 = 0x" << std::hex << key.getHash2() - << std::endl; - ++numCollisions; - assert(false); - } else { - hashes.insert(key.getHash(), key.getHash2()); - } - for (int k = 0; k < 32; ++k) { - if (masks[k] & key.getHash2()) { - ++bits[k]; - } - } - } - */ - for (int z = 1; z < numSteps && testCount < maxTests; ++z) { float radiusZ = (float)z * deltaLength; // test box info.setBox(glm::vec3(radiusX, radiusY, radiusZ)); ++testCount; - DoubleHashKey key = info.getHash(); - hashPtr = hashes.find(key.getHash()); - if (hashPtr && *hashPtr == key.getHash2()) { - std::cout << testCount << " hash collision radiusX = " << radiusX - << " radiusY = " << radiusY << " radiusZ = " << radiusZ - << " h1 = 0x" << std::hex << key.getHash() - << " h2 = 0x" << std::hex << key.getHash2() - << std::endl; + HashKey key = info.getHash(); + hashPtr = hashes.find(key); + if (hashPtr) { + std::cout << testCount << " hash collision box dimensions = < " << radiusX + << ", " << radiusY << ", " << radiusZ << " >" + << " h = 0x" << std::hex << key.getHash() << " : 0x" << *hashPtr << " : 0x" << key.getHash64() + << std::dec << std::endl; ++numCollisions; assert(false); } else { - hashes.insert(key.getHash(), key.getHash2()); + hashes.insert(key, key.getHash()); } - for (int k = 0; k < 32; ++k) { - if (masks[k] & key.getHash2()) { + // track bit distribution counts to evaluate hash function randomness + for (int k = 0; k < NUM_HASH_BITS; ++k) { + if (masks[k] & key.getHash()) { ++bits[k]; } } @@ -135,7 +105,8 @@ void ShapeInfoTests::testHashFunctions() { std::cout << msec << " msec with " << numCollisions << " collisions out of " << testCount << " hashes" << std::endl; // print out distribution of bits - for (int i = 0; i < 32; ++i) { + // ideally the numbers in each bin will be about the same + for (int i = 0; i < NUM_HASH_BITS; ++i) { std::cout << "bit 0x" << std::hex << masks[i] << std::dec << " = " << bits[i] << std::endl; } QCOMPARE(numCollisions, 0); @@ -146,15 +117,14 @@ void ShapeInfoTests::testBoxShape() { ShapeInfo info; glm::vec3 halfExtents(1.23f, 4.56f, 7.89f); info.setBox(halfExtents); - DoubleHashKey key = info.getHash(); + HashKey key = info.getHash(); const btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info); QCOMPARE(shape != nullptr, true); ShapeInfo otherInfo = info; - DoubleHashKey otherKey = otherInfo.getHash(); + HashKey otherKey = otherInfo.getHash(); QCOMPARE(key.getHash(), otherKey.getHash()); - QCOMPARE(key.getHash2(), otherKey.getHash2()); delete shape; } @@ -163,15 +133,14 @@ void ShapeInfoTests::testSphereShape() { ShapeInfo info; float radius = 1.23f; info.setSphere(radius); - DoubleHashKey key = info.getHash(); + HashKey key = info.getHash(); const btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info); QCOMPARE(shape != nullptr, true); ShapeInfo otherInfo = info; - DoubleHashKey otherKey = otherInfo.getHash(); + HashKey otherKey = otherInfo.getHash(); QCOMPARE(key.getHash(), otherKey.getHash()); - QCOMPARE(key.getHash2(), otherKey.getHash2()); delete shape; } @@ -182,15 +151,14 @@ void ShapeInfoTests::testCylinderShape() { float radius = 1.23f; float height = 4.56f; info.setCylinder(radius, height); - DoubleHashKey key = info.getHash(); + HashKey key = info.getHash(); btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info); QCOMPARE(shape != nullptr, true); ShapeInfo otherInfo = info; - DoubleHashKey otherKey = otherInfo.getHash(); + HashKey otherKey = otherInfo.getHash(); QCOMPARE(key.getHash(), otherKey.getHash()); - QCOMPARE(key.getHash2(), otherKey.getHash2()); delete shape; */ @@ -202,15 +170,14 @@ void ShapeInfoTests::testCapsuleShape() { float radius = 1.23f; float height = 4.56f; info.setCapsule(radius, height); - DoubleHashKey key = info.getHash(); + HashKey key = info.getHash(); btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info); QCOMPARE(shape != nullptr, true); ShapeInfo otherInfo = info; - DoubleHashKey otherKey = otherInfo.getHash(); + HashKey otherKey = otherInfo.getHash(); QCOMPARE(key.getHash(), otherKey.getHash()); - QCOMPARE(key.getHash2(), otherKey.getHash2()); delete shape; */ diff --git a/tests/physics/src/ShapeInfoTests.h b/tests/physics/src/ShapeInfoTests.h index fbd89a13a8..1f6054dd1a 100644 --- a/tests/physics/src/ShapeInfoTests.h +++ b/tests/physics/src/ShapeInfoTests.h @@ -18,10 +18,6 @@ //#include "BulletTestUtils.h" //#include "../QTestExtensions.h" -// Enable this to manually run testHashCollisions -// (NOT a regular unit test; takes ~17 secs to run on an i7) -#define MANUAL_TEST false - class ShapeInfoTests : public QObject { Q_OBJECT private slots: From b00d15834255f9ad1f8d1e6359e104efbfb72698 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 26 Oct 2017 09:00:42 -0700 Subject: [PATCH 046/183] remove DoubleHashKey: it is no longer used --- libraries/shared/src/DoubleHashKey.cpp | 48 ------------------------- libraries/shared/src/DoubleHashKey.h | 49 -------------------------- 2 files changed, 97 deletions(-) delete mode 100644 libraries/shared/src/DoubleHashKey.cpp delete mode 100644 libraries/shared/src/DoubleHashKey.h diff --git a/libraries/shared/src/DoubleHashKey.cpp b/libraries/shared/src/DoubleHashKey.cpp deleted file mode 100644 index ded2f073eb..0000000000 --- a/libraries/shared/src/DoubleHashKey.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// DoubleHashKey.cpp -// libraries/shared/src -// -// Created by Andrew Meadows 2014.11.02 -// 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 "DoubleHashKey.h" - -const uint32_t NUM_PRIMES = 64; -const uint32_t PRIMES[] = { - 4194301U, 4194287U, 4194277U, 4194271U, 4194247U, 4194217U, 4194199U, 4194191U, - 4194187U, 4194181U, 4194173U, 4194167U, 4194143U, 4194137U, 4194131U, 4194107U, - 4194103U, 4194023U, 4194011U, 4194007U, 4193977U, 4193971U, 4193963U, 4193957U, - 4193939U, 4193929U, 4193909U, 4193869U, 4193807U, 4193803U, 4193801U, 4193789U, - 4193759U, 4193753U, 4193743U, 4193701U, 4193663U, 4193633U, 4193573U, 4193569U, - 4193551U, 4193549U, 4193531U, 4193513U, 4193507U, 4193459U, 4193447U, 4193443U, - 4193417U, 4193411U, 4193393U, 4193389U, 4193381U, 4193377U, 4193369U, 4193359U, - 4193353U, 4193327U, 4193309U, 4193303U, 4193297U, 4193279U, 4193269U, 4193263U -}; - -uint32_t DoubleHashKey::hashFunction(uint32_t value, uint32_t primeIndex) { - uint32_t hash = PRIMES[primeIndex % NUM_PRIMES] * (value + 1U); - hash += ~(hash << 15); - hash ^= (hash >> 10); - hash += (hash << 3); - hash ^= (hash >> 6); - hash += ~(hash << 11); - return hash ^ (hash >> 16); -} - -uint32_t DoubleHashKey::hashFunction2(uint32_t value) { - uint32_t hash = 0x811c9dc5U; - for (uint32_t i = 0; i < 4; i++ ) { - uint32_t byte = (value << (i * 8)) >> (24 - i * 8); - hash = ( hash ^ byte ) * 0x01000193U; - } - return hash; -} - -void DoubleHashKey::computeHash(uint32_t value, uint32_t primeIndex) { - _hash = DoubleHashKey::hashFunction(value, primeIndex); - _hash2 = DoubleHashKey::hashFunction2(value); -} diff --git a/libraries/shared/src/DoubleHashKey.h b/libraries/shared/src/DoubleHashKey.h deleted file mode 100644 index ca92a7197f..0000000000 --- a/libraries/shared/src/DoubleHashKey.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// DoubleHashKey.h -// libraries/shared/src -// -// Created by Andrew Meadows 2014.11.02 -// 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 -// - -#ifndef hifi_DoubleHashKey_h -#define hifi_DoubleHashKey_h - -#include - -// DoubleHashKey for use with btHashMap -class DoubleHashKey { -public: - static uint32_t hashFunction(uint32_t value, uint32_t primeIndex); - static uint32_t hashFunction2(uint32_t value); - - DoubleHashKey() : _hash(0), _hash2(0) { } - - DoubleHashKey(uint32_t value, uint32_t primeIndex = 0) : - _hash(hashFunction(value, primeIndex)), - _hash2(hashFunction2(value)) { - } - - void clear() { _hash = 0; _hash2 = 0; } - bool isNull() const { return _hash == 0 && _hash2 == 0; } - - bool equals(const DoubleHashKey& other) const { - return _hash == other._hash && _hash2 == other._hash2; - } - - void computeHash(uint32_t value, uint32_t primeIndex = 0); - uint32_t getHash() const { return _hash; } - uint32_t getHash2() const { return _hash2; } - - void setHash(uint32_t hash) { _hash = hash; } - void setHash2(uint32_t hash2) { _hash2 = hash2; } - -private: - uint32_t _hash; - uint32_t _hash2; -}; - -#endif // hifi_DoubleHashKey_h From 4cadcd79bfb522e453a75fa46f859ccbcdcd6d27 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 27 Oct 2017 17:07:19 +0200 Subject: [PATCH 047/183] Return full viewport when scissor is disabled and items in outline group --- libraries/render-utils/src/OutlineEffect.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index e3f4ff2b7f..fb2aab95f2 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -113,8 +113,9 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con RenderArgs* args = renderContext->args; ShapeKey::Builder defaultKeyBuilder; - auto framebufferSize = ressources->getSourceFrameSize(); +#if OUTLINE_USE_SCISSOR + auto framebufferSize = ressources->getSourceFrameSize(); // First thing we do is determine the projected bounding rect of all the outlined items auto outlinedRect = computeOutlineRect(inShapes, args->getViewFrustum(), framebufferSize); auto blurPixelWidth = _sharedParameters->_blurPixelWidths[_outlineIndex]; @@ -123,6 +124,10 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con // Add 1 pixel of extra margin to be on the safe side outputs = expandRect(outlinedRect, blurPixelWidth+1, framebufferSize); outlinedRect = expandRect(outputs, blurPixelWidth+1, framebufferSize); +#else + // Render full screen + outputs = args->_viewport; +#endif // Clear the framebuffer without stereo // Needs to be distinct from the other batch because using the clear call From 4cbee72eae60305cc616b53aee5fba092f2090ae Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 27 Oct 2017 17:50:22 +0200 Subject: [PATCH 048/183] Fixed warning on Mac and Ubuntu --- libraries/render-utils/src/OutlineEffect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index fb2aab95f2..f459ddc42c 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -367,7 +367,7 @@ void DebugOutline::run(const render::RenderContextPointer& renderContext, const const auto outlineRessources = input.get0(); const auto outlineRect = input.get1(); - if (_isDisplayEnabled && outlineRessources) { + if (_isDisplayEnabled && outlineRessources && outlineRect.z>0 && outlineRect.w>0) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; From d45febf1db706a7f8855004818816d9220a9f823 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 27 Oct 2017 08:55:41 -0700 Subject: [PATCH 049/183] add description of ShapeManager in comments --- libraries/physics/src/ShapeManager.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/libraries/physics/src/ShapeManager.h b/libraries/physics/src/ShapeManager.h index 6ec3573b53..d75bb1dc4a 100644 --- a/libraries/physics/src/ShapeManager.h +++ b/libraries/physics/src/ShapeManager.h @@ -19,6 +19,28 @@ #include "HashKey.h" +// The ShapeManager handles the ref-counting on shared shapes: +// +// Each object added to the physics simulation gets a corresponding btRigidBody. +// The body has a btCollisionShape that represents the contours of its collision +// surface. Multiple bodies may have the same shape. Rather than create a unique +// btCollisionShape instance for every body with a particular shape we can instead +// use a single shape instance for all of the bodies. This is called "shape +// sharing". +// +// When body needs a new shape a description of ths shape (ShapeInfo) is assembled +// and a request is sent to the ShapeManager for a corresponding btCollisionShape +// pointer. The ShapeManager will compute a hash of the ShapeInfo's data and use +// that to find the shape in its map. If it finds one it increments the ref-count +// and returns the pointer. If not it asks the ShapeFactory to create it, adds an +// entry in the map with a ref-count of 1, and returns the pointer. +// +// When a body stops using a shape the ShapeManager must be informed so it can +// decrement its ref-count. When a ref-count drops to zero the ShapeManager +// doesn't delete it right away. Instead it puts the shape's key on a list delete +// later. When that list grows big enough the ShapeManager will remove any matching +// entries that still have zero ref-count. + class ShapeManager { public: @@ -51,6 +73,7 @@ private: ShapeReference() : refCount(0), shape(nullptr) {} }; + // btHashMap is required because it supports memory alignment of the btCollisionShapes btHashMap _shapeMap; btAlignedObjectArray _pendingGarbage; }; From 137fccbd91b46c20fddc891e52915824bd440f72 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 27 Oct 2017 08:56:26 -0700 Subject: [PATCH 050/183] cleanup ShapeFactory implementation --- libraries/physics/src/ShapeFactory.cpp | 63 ++++++++++++++------------ libraries/physics/src/ShapeFactory.h | 16 +------ 2 files changed, 35 insertions(+), 44 deletions(-) diff --git a/libraries/physics/src/ShapeFactory.cpp b/libraries/physics/src/ShapeFactory.cpp index cd0fba848a..f484f32fdf 100644 --- a/libraries/physics/src/ShapeFactory.cpp +++ b/libraries/physics/src/ShapeFactory.cpp @@ -16,6 +16,40 @@ #include "ShapeFactory.h" #include "BulletUtil.h" + +class StaticMeshShape : public btBvhTriangleMeshShape { +public: + StaticMeshShape() = delete; + + StaticMeshShape(btTriangleIndexVertexArray* dataArray) + : btBvhTriangleMeshShape(dataArray, true), _dataArray(dataArray) { + assert(_dataArray); + } + + ~StaticMeshShape() { + assert(_dataArray); + IndexedMeshArray& meshes = _dataArray->getIndexedMeshArray(); + for (int32_t i = 0; i < meshes.size(); ++i) { + btIndexedMesh mesh = meshes[i]; + mesh.m_numTriangles = 0; + delete [] mesh.m_triangleIndexBase; + mesh.m_triangleIndexBase = nullptr; + mesh.m_numVertices = 0; + delete [] mesh.m_vertexBase; + mesh.m_vertexBase = nullptr; + } + meshes.clear(); + delete _dataArray; + _dataArray = nullptr; + } + +private: + // the StaticMeshShape owns its vertex/index data + btTriangleIndexVertexArray* _dataArray; +}; + +// the dataArray must be created before we create the StaticMeshShape + // These are the same normalized directions used by the btShapeHull class. // 12 points for the face centers of a dodecahedron plus another 30 points // for the midpoints the edges, for a total of 42. @@ -230,23 +264,6 @@ btTriangleIndexVertexArray* createStaticMeshArray(const ShapeInfo& info) { return dataArray; } -// util method -void deleteStaticMeshArray(btTriangleIndexVertexArray* dataArray) { - assert(dataArray); - IndexedMeshArray& meshes = dataArray->getIndexedMeshArray(); - for (int32_t i = 0; i < meshes.size(); ++i) { - btIndexedMesh mesh = meshes[i]; - mesh.m_numTriangles = 0; - delete [] mesh.m_triangleIndexBase; - mesh.m_triangleIndexBase = nullptr; - mesh.m_numVertices = 0; - delete [] mesh.m_vertexBase; - mesh.m_vertexBase = nullptr; - } - meshes.clear(); - delete dataArray; -} - const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) { btCollisionShape* shape = NULL; int type = info.getType(); @@ -431,7 +448,6 @@ void ShapeFactory::deleteShape(const btCollisionShape* shape) { assert(shape); // ShapeFactory is responsible for deleting all shapes, even the const ones that are stored // in the ShapeManager, so we must cast to non-const here when deleting. - // so we cast to non-const here when deleting memory. btCollisionShape* nonConstShape = const_cast(shape); if (nonConstShape->getShapeType() == (int)COMPOUND_SHAPE_PROXYTYPE) { btCompoundShape* compoundShape = static_cast(nonConstShape); @@ -448,14 +464,3 @@ void ShapeFactory::deleteShape(const btCollisionShape* shape) { } delete nonConstShape; } - -// the dataArray must be created before we create the StaticMeshShape -ShapeFactory::StaticMeshShape::StaticMeshShape(btTriangleIndexVertexArray* dataArray) -: btBvhTriangleMeshShape(dataArray, true), _dataArray(dataArray) { - assert(dataArray); -} - -ShapeFactory::StaticMeshShape::~StaticMeshShape() { - deleteStaticMeshArray(_dataArray); - _dataArray = nullptr; -} diff --git a/libraries/physics/src/ShapeFactory.h b/libraries/physics/src/ShapeFactory.h index 2bf79f390c..704a7804b3 100644 --- a/libraries/physics/src/ShapeFactory.h +++ b/libraries/physics/src/ShapeFactory.h @@ -17,25 +17,11 @@ #include -// translates between ShapeInfo and btShape +// The ShapeFactory assembles and correctly disassembles btCollisionShapes. namespace ShapeFactory { const btCollisionShape* createShapeFromInfo(const ShapeInfo& info); void deleteShape(const btCollisionShape* shape); - - //btTriangleIndexVertexArray* createStaticMeshArray(const ShapeInfo& info); - //void deleteStaticMeshArray(btTriangleIndexVertexArray* dataArray); - - class StaticMeshShape : public btBvhTriangleMeshShape { - public: - StaticMeshShape() = delete; - StaticMeshShape(btTriangleIndexVertexArray* dataArray); - ~StaticMeshShape(); - - private: - // the StaticMeshShape owns its vertex/index data - btTriangleIndexVertexArray* _dataArray; - }; }; #endif // hifi_ShapeFactory_h From 66c31caf4b17a970a6b47419a4d7abf1318126bb Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Fri, 27 Oct 2017 09:08:58 -0700 Subject: [PATCH 051/183] Refactoring of the haze --- .../src/RenderableZoneEntityItem.cpp | 6 +- libraries/entities/CMakeLists.txt | 2 +- libraries/entities/src/HazePropertyGroup.cpp | 13 ---- libraries/entities/src/HazePropertyGroup.h | 33 +++------ libraries/entities/src/ZoneEntityItem.h | 19 ++--- libraries/model/src/model/Haze.cpp | 42 +++++------ libraries/model/src/model/Haze.h | 65 +++-------------- libraries/model/src/model/HazeInit.h | 69 +++++++++++++++++++ .../render-utils/src/DeferredGlobalLight.slh | 10 +-- .../src/DeferredLightingEffect.cpp | 4 +- libraries/render-utils/src/DrawHaze.cpp | 34 ++++----- libraries/render-utils/src/DrawHaze.h | 68 +++++++++--------- libraries/render-utils/src/Haze.slf | 20 +++--- libraries/render-utils/src/Haze.slh | 14 ++-- libraries/render-utils/src/HazeStage.cpp | 10 +-- libraries/render-utils/src/HazeStage.h | 44 ++++++------ scripts/system/html/entityProperties.html | 16 ++--- scripts/system/html/js/entityProperties.js | 28 ++++---- 18 files changed, 249 insertions(+), 248 deletions(-) create mode 100644 libraries/model/src/model/HazeInit.h diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 0235f1b7a3..877e245006 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -346,15 +346,15 @@ void ZoneEntityRenderer::updateHazeFromEntity(const TypedEntityPointer& entity) xColor hazeColor = _hazeProperties.getHazeColor(); haze->setHazeColor(glm::vec3(hazeColor.red / 255.0, hazeColor.green / 255.0, hazeColor.blue / 255.0)); xColor hazeGlareColor = _hazeProperties.getHazeGlareColor(); - haze->setDirectionalLightColor(glm::vec3(hazeGlareColor.red / 255.0, hazeGlareColor.green / 255.0, hazeGlareColor.blue / 255.0)); + haze->setHazeGlareColor(glm::vec3(hazeGlareColor.red / 255.0, hazeGlareColor.green / 255.0, hazeGlareColor.blue / 255.0)); haze->setHazeEnableGlare(_hazeProperties.getHazeEnableGlare()); - haze->setDirectionalLightBlend(model::convertDirectionalLightAngleToPower(_hazeProperties.getHazeGlareAngle())); + haze->setHazeGlareBlend(model::convertGlareAngleToPower(_hazeProperties.getHazeGlareAngle())); float hazeAltitude = _hazeProperties.getHazeCeiling() - _hazeProperties.getHazeBaseRef(); haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(hazeAltitude)); haze->setHazeBaseReference(_hazeProperties.getHazeBaseRef()); - haze->setHazeBackgroundBlendValue(_hazeProperties.getHazeBackgroundBlend()); + haze->setHazeBackgroundBlend(_hazeProperties.getHazeBackgroundBlend()); haze->setHazeAttenuateKeyLight(_hazeProperties.getHazeAttenuateKeyLight()); haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(_hazeProperties.getHazeKeyLightRange())); diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 322d69da16..c23740654e 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") -link_hifi_libraries(shared networking octree avatars) +link_hifi_libraries(shared networking octree avatars model) diff --git a/libraries/entities/src/HazePropertyGroup.cpp b/libraries/entities/src/HazePropertyGroup.cpp index 996d2e0cd3..3cc3e69960 100644 --- a/libraries/entities/src/HazePropertyGroup.cpp +++ b/libraries/entities/src/HazePropertyGroup.cpp @@ -15,19 +15,6 @@ #include "EntityItemProperties.h" #include "EntityItemPropertiesMacros.h" -const float HazePropertyGroup::DEFAULT_HAZE_RANGE{ 1000.0f }; -const xColor HazePropertyGroup::DEFAULT_HAZE_COLOR{ 128, 154, 179 }; // Bluish -const xColor HazePropertyGroup::DEFAULT_HAZE_GLARE_COLOR{ 255, 229, 179 }; // Yellowish -const float HazePropertyGroup::DEFAULT_HAZE_GLARE_ANGLE{ 20.0 }; - -const float HazePropertyGroup::DEFAULT_HAZE_CEILING{ 200.0f }; -const float HazePropertyGroup::DEFAULT_HAZE_BASE_REF{ 0.0f }; - -const float HazePropertyGroup::DEFAULT_HAZE_BACKGROUND_BLEND{ 0.0f }; - -const float HazePropertyGroup::DEFAULT_HAZE_KEYLIGHT_RANGE{ 1000.0 }; -const float HazePropertyGroup::DEFAULT_HAZE_KEYLIGHT_ALTITUDE{ 200.0f }; - void HazePropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const { COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_RANGE, Haze, haze, HazeRange, hazeRange); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_COLOR, Haze, haze, HazeColor, hazeColor); diff --git a/libraries/entities/src/HazePropertyGroup.h b/libraries/entities/src/HazePropertyGroup.h index cdd36ff7ef..1cbaa24f2a 100644 --- a/libraries/entities/src/HazePropertyGroup.h +++ b/libraries/entities/src/HazePropertyGroup.h @@ -21,6 +21,8 @@ #include "PropertyGroup.h" #include "EntityItemPropertiesMacros.h" +#include + class EntityItemProperties; class EncodeBitstreamParams; class OctreePacketData; @@ -74,38 +76,25 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - static const float DEFAULT_HAZE_RANGE; - static const xColor DEFAULT_HAZE_COLOR; - static const xColor DEFAULT_HAZE_GLARE_COLOR; - static const float DEFAULT_HAZE_GLARE_ANGLE; - - static const float DEFAULT_HAZE_CEILING; - static const float DEFAULT_HAZE_BASE_REF; - - static const float DEFAULT_HAZE_BACKGROUND_BLEND; - - static const float DEFAULT_HAZE_KEYLIGHT_RANGE; - static const float DEFAULT_HAZE_KEYLIGHT_ALTITUDE; - // Range only parameters - DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, DEFAULT_HAZE_RANGE); - DEFINE_PROPERTY_REF(PROP_HAZE_COLOR, HazeColor, hazeColor, xColor, DEFAULT_HAZE_COLOR); - DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_COLOR, HazeGlareColor, hazeGlareColor, xColor, DEFAULT_HAZE_GLARE_COLOR); + DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, model::initialHazeRange_m); + DEFINE_PROPERTY_REF(PROP_HAZE_COLOR, HazeColor, hazeColor, xColor, model::initialHazeColorXcolor); + DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_COLOR, HazeGlareColor, hazeGlareColor, xColor, model::initialHazeGlareColorXcolor); DEFINE_PROPERTY(PROP_HAZE_ENABLE_GLARE, HazeEnableGlare, hazeEnableGlare, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_ANGLE, HazeGlareAngle, hazeGlareAngle, float, DEFAULT_HAZE_GLARE_ANGLE); + DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_ANGLE, HazeGlareAngle, hazeGlareAngle, float, model::initialGlareAngle_degs); // Altitude parameters DEFINE_PROPERTY(PROP_HAZE_ALTITUDE_EFFECT, HazeAltitudeEffect, hazeAltitudeEffect, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_CEILING, HazeCeiling, hazeCeiling, float, DEFAULT_HAZE_CEILING); - DEFINE_PROPERTY_REF(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, DEFAULT_HAZE_BASE_REF); + DEFINE_PROPERTY_REF(PROP_HAZE_CEILING, HazeCeiling, hazeCeiling, float, model::initialHazeBaseReference_m + model::initialHazeHeight_m); + DEFINE_PROPERTY_REF(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, model::initialHazeBaseReference_m); // Background (skybox) blend value - DEFINE_PROPERTY_REF(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend, hazeBackgroundBlend, float, DEFAULT_HAZE_BACKGROUND_BLEND); + DEFINE_PROPERTY_REF(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend, hazeBackgroundBlend, float, model::initialHazeBackgroundBlend); // hazeDirectional light attenuation DEFINE_PROPERTY(PROP_HAZE_ATTENUATE_KEYLIGHT, HazeAttenuateKeyLight, hazeAttenuateKeyLight, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, DEFAULT_HAZE_KEYLIGHT_RANGE); - DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, DEFAULT_HAZE_KEYLIGHT_ALTITUDE); + DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, model::initialHazeKeyLightRange_m); + DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, model::initialHazeKeyLightAltitude_m); }; #endif // hifi_HazePropertyGroup_h diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index ddbb2ed914..628c228af6 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -19,6 +19,7 @@ #include "HazePropertyGroup.h" #include "StagePropertyGroup.h" #include +#include class ZoneEntityItem : public EntityItem { public: @@ -150,20 +151,20 @@ protected: uint32_t _hazeMode{ DEFAULT_HAZE_MODE }; - float _hazeRange{ HazePropertyGroup::DEFAULT_HAZE_RANGE }; - xColor _hazeColor{ HazePropertyGroup::DEFAULT_HAZE_COLOR }; - xColor _hazeGlareColor{ HazePropertyGroup::DEFAULT_HAZE_GLARE_COLOR }; + float _hazeRange{ model::initialHazeRange_m }; + xColor _hazeColor{ model::initialHazeColorXcolor }; + xColor _hazeGlareColor{ model::initialHazeGlareColorXcolor }; bool _hazeEnableGlare{ false }; - float _hazeGlareAngle{ HazePropertyGroup::DEFAULT_HAZE_GLARE_ANGLE }; + float _hazeGlareAngle{ model::initialGlareAngle_degs }; - float _hazeCeiling{ HazePropertyGroup::DEFAULT_HAZE_CEILING }; - float _hazeBaseRef{ HazePropertyGroup::DEFAULT_HAZE_BASE_REF }; + float _hazeCeiling{ model::initialHazeBaseReference_m + model::initialHazeHeight_m }; + float _hazeBaseRef{ model::initialHazeBaseReference_m }; - float _hazeBackgroundBlend{ HazePropertyGroup::DEFAULT_HAZE_BACKGROUND_BLEND }; + float _hazeBackgroundBlend{ model::initialHazeBackgroundBlend }; bool _hazeAttenuateKeyLight{ false }; - float _hazeKeyLightRange{ HazePropertyGroup::DEFAULT_HAZE_KEYLIGHT_RANGE }; - float _hazeKeyLightAltitude{ HazePropertyGroup::DEFAULT_HAZE_KEYLIGHT_ALTITUDE }; + float _hazeKeyLightRange{ model::initialHazeKeyLightRange_m }; + float _hazeKeyLightAltitude{ model::initialHazeKeyLightAltitude_m }; SkyboxPropertyGroup _skyboxProperties; HazePropertyGroup _hazeProperties; diff --git a/libraries/model/src/model/Haze.cpp b/libraries/model/src/model/Haze.cpp index 679d4ad3d1..1c9b989fd1 100644 --- a/libraries/model/src/model/Haze.cpp +++ b/libraries/model/src/model/Haze.cpp @@ -23,7 +23,7 @@ Haze::Haze() { enum HazeModes { HAZE_MODE_IS_ACTIVE = 1 << 0, HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1, - HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED = 1 << 2, + HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2, HAZE_MODE_IS_MODULATE_COLOR = 1 << 3, HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4 }; @@ -55,25 +55,25 @@ void Haze::setHazeEnableGlare(const bool isHazeEnableGlare) { } } -void Haze::setDirectionalLightBlend(const float hazeDirectionalLightBlend) { +void Haze::setHazeGlareBlend(const float hazeGlareBlend) { auto& params = _hazeParametersBuffer.get(); - if (params.directionalLightBlend != hazeDirectionalLightBlend) { - _hazeParametersBuffer.edit().directionalLightBlend = hazeDirectionalLightBlend; + if (params.hazeGlareBlend != hazeGlareBlend) { + _hazeParametersBuffer.edit().hazeGlareBlend = hazeGlareBlend; } } -void Haze::setDirectionalLightColor(const glm::vec3 hazeDirectionalLightColor) { +void Haze::setHazeGlareColor(const glm::vec3 hazeGlareColor) { auto& params = _hazeParametersBuffer.get(); - if (params.directionalLightColor.r != hazeDirectionalLightColor.r) { - _hazeParametersBuffer.edit().directionalLightColor.r = hazeDirectionalLightColor.r; + if (params.hazeGlareColor.r != hazeGlareColor.r) { + _hazeParametersBuffer.edit().hazeGlareColor.r = hazeGlareColor.r; } - if (params.directionalLightColor.g != hazeDirectionalLightColor.g) { - _hazeParametersBuffer.edit().directionalLightColor.g = hazeDirectionalLightColor.g; + if (params.hazeGlareColor.g != hazeGlareColor.g) { + _hazeParametersBuffer.edit().hazeGlareColor.g = hazeGlareColor.g; } - if (params.directionalLightColor.b != hazeDirectionalLightColor.b) { - _hazeParametersBuffer.edit().directionalLightColor.b = hazeDirectionalLightColor.b; + if (params.hazeGlareColor.b != hazeGlareColor.b) { + _hazeParametersBuffer.edit().hazeGlareColor.b = hazeGlareColor.b; } } void Haze::setHazeActive(const bool isHazeActive) { @@ -99,10 +99,10 @@ void Haze::setAltitudeBased(const bool isAltitudeBased) { void Haze::setHazeAttenuateKeyLight(const bool isHazeAttenuateKeyLight) { auto& params = _hazeParametersBuffer.get(); - if (((params.hazeMode & HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED) == HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED ) && !isHazeAttenuateKeyLight) { - _hazeParametersBuffer.edit().hazeMode &= ~HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED; - } else if (((params.hazeMode & HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED) != HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED) && isHazeAttenuateKeyLight) { - _hazeParametersBuffer.edit().hazeMode |= HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED; + if (((params.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) && !isHazeAttenuateKeyLight) { + _hazeParametersBuffer.edit().hazeMode &= ~HAZE_MODE_IS_KEYLIGHT_ATTENUATED; + } else if (((params.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) != HAZE_MODE_IS_KEYLIGHT_ATTENUATED) && isHazeAttenuateKeyLight) { + _hazeParametersBuffer.edit().hazeMode |= HAZE_MODE_IS_KEYLIGHT_ATTENUATED; } } @@ -124,11 +124,11 @@ void Haze::setHazeRangeFactor(const float hazeRangeFactor) { } } -void Haze::setHazeAltitudeFactor(const float hazeAltitudeFactor) { +void Haze::setHazeAltitudeFactor(const float hazeHeightFactor) { auto& params = _hazeParametersBuffer.get(); - if (params.hazeAltitudeFactor != hazeAltitudeFactor) { - _hazeParametersBuffer.edit().hazeAltitudeFactor = hazeAltitudeFactor; + if (params.hazeHeightFactor != hazeHeightFactor) { + _hazeParametersBuffer.edit().hazeHeightFactor = hazeHeightFactor; } } @@ -156,11 +156,11 @@ void Haze::setHazeBaseReference(const float hazeBaseReference) { } } -void Haze::setHazeBackgroundBlendValue(const float hazeBackgroundBlendValue) { +void Haze::setHazeBackgroundBlend(const float hazeBackgroundBlend) { auto& params = _hazeParametersBuffer.get(); - if (params.hazeBackgroundBlendValue != hazeBackgroundBlendValue) { - _hazeParametersBuffer.edit().hazeBackgroundBlendValue = hazeBackgroundBlendValue; + if (params.hazeBackgroundBlend != hazeBackgroundBlend) { + _hazeParametersBuffer.edit().hazeBackgroundBlend = hazeBackgroundBlend; } } diff --git a/libraries/model/src/model/Haze.h b/libraries/model/src/model/Haze.h index 2ffdd2333b..bed82c80f9 100644 --- a/libraries/model/src/model/Haze.h +++ b/libraries/model/src/model/Haze.h @@ -15,56 +15,11 @@ #include "Transform.h" #include "NumericalConstants.h" +#include "HazeInit.h" + namespace model { - const float LOG_P_005 = logf(0.05f); - const float LOG_P_05 = logf(0.5f); - - // Derivation (d is distance, b is haze coefficient, f is attenuation, solve for f = 0.05 - // f = exp(-d * b) - // ln(f) = -d * b - // b = -ln(f)/d - inline glm::vec3 convertHazeRangeToHazeRangeFactor(const glm::vec3 hazeRange_m) { - return glm::vec3( - -LOG_P_005 / hazeRange_m.x, - -LOG_P_005 / hazeRange_m.y, - -LOG_P_005 / hazeRange_m.z); - } - - // limit range and altitude to no less than 1.0 metres - inline float convertHazeRangeToHazeRangeFactor(const float hazeRange_m) { return -LOG_P_005 / glm::max(hazeRange_m, 1.0f); } - - inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeAltitude_m) { return -LOG_P_005 / glm::max(hazeAltitude_m, 1.0f); } - - // Derivation (s is the proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5 - // s = dot(lookAngle, sunAngle) = cos(a) - // m = pow(s, p) - // log(m) = p * log(s) - // p = log(m) / log(s) - inline float convertDirectionalLightAngleToPower(const float directionalLightAngle) { - return LOG_P_05 / logf(cosf(RADIANS_PER_DEGREE * directionalLightAngle)); - } - - const glm::vec3 initialHazeColor{ 0.5f, 0.6f, 0.7f }; - const float initialDirectionalLightAngle_degs{ 30.0f }; - - const glm::vec3 initialDirectionalLightColor{ 1.0f, 0.9f, 0.7f }; - const float initialHazeBaseReference{ 0.0f }; - // Haze range is defined here as the range the visibility is reduced by 95% // Haze altitude is defined here as the altitude (above 0) that the haze is reduced by 95% - const float initialHazeRange_m{ 150.0f }; - const float initialHazeAltitude_m{ 150.0f }; - - const float initialHazeKeyLightRange_m{ 150.0f }; - const float initialHazeKeyLightAltitude_m{ 150.0f }; - - const float initialHazeBackgroundBlendValue{ 0.0f }; - - const glm::vec3 initialColorModulationFactor{ - convertHazeRangeToHazeRangeFactor(initialHazeRange_m), - convertHazeRangeToHazeRangeFactor(initialHazeRange_m), - convertHazeRangeToHazeRangeFactor(initialHazeRange_m) - }; class Haze { public: @@ -73,9 +28,9 @@ namespace model { Haze(); void setHazeColor(const glm::vec3 hazeColor); - void setDirectionalLightBlend(const float directionalLightBlend); + void setHazeGlareBlend(const float hazeGlareBlend); - void setDirectionalLightColor(const glm::vec3 directionalLightColor); + void setHazeGlareColor(const glm::vec3 hazeGlareColor); void setHazeBaseReference(const float hazeBaseReference); void setHazeActive(const bool isHazeActive); @@ -90,7 +45,7 @@ namespace model { void setHazeKeyLightRangeFactor(const float hazeKeyLightRange); void setHazeKeyLightAltitudeFactor(const float hazeKeyLightAltitude); - void setHazeBackgroundBlendValue(const float hazeBackgroundBlendValue); + void setHazeBackgroundBlend(const float hazeBackgroundBlend); void setZoneTransform(const glm::mat4& zoneTransform); @@ -101,10 +56,10 @@ namespace model { public: // DO NOT CHANGE ORDER HERE WITHOUT UNDERSTANDING THE std140 LAYOUT glm::vec3 hazeColor{ initialHazeColor }; - float directionalLightBlend{ convertDirectionalLightAngleToPower(initialDirectionalLightAngle_degs) }; + float hazeGlareBlend{ convertGlareAngleToPower(initialGlareAngle_degs) }; - glm::vec3 directionalLightColor{ initialDirectionalLightColor }; - float hazeBaseReference{ initialHazeBaseReference }; + glm::vec3 hazeGlareColor{ initialHazeGlareColor }; + float hazeBaseReference{ initialHazeBaseReference_m }; glm::vec3 colorModulationFactor{ initialColorModulationFactor }; int hazeMode{ 0 }; // bit 0 - set to activate haze attenuation of fragment color @@ -115,11 +70,11 @@ namespace model { glm::mat4 zoneTransform; // Amount of background (skybox) to display, overriding the haze effect for the background - float hazeBackgroundBlendValue{ initialHazeBackgroundBlendValue }; + float hazeBackgroundBlend{ initialHazeBackgroundBlend }; // The haze attenuation exponents used by both fragment and directional light attenuation float hazeRangeFactor{ convertHazeRangeToHazeRangeFactor(initialHazeRange_m) }; - float hazeAltitudeFactor{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeAltitude_m) }; + float hazeHeightFactor{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeHeight_m) }; float hazeKeyLightRangeFactor{ convertHazeRangeToHazeRangeFactor(initialHazeKeyLightRange_m) }; float hazeKeyLightAltitudeFactor{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeKeyLightAltitude_m) }; diff --git a/libraries/model/src/model/HazeInit.h b/libraries/model/src/model/HazeInit.h new file mode 100644 index 0000000000..218a79fc1d --- /dev/null +++ b/libraries/model/src/model/HazeInit.h @@ -0,0 +1,69 @@ +// +// MakeHaze.h +// libraries/model/src/model +// +// Created by Nissim Hadar on 10/26/2017. +// 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 +// +#ifndef hifi_model_HazeInit_h +#define hifi_model_HazeInit_h + +namespace model { + const float LOG_P_005 = logf(0.05f); + const float LOG_P_05 = logf(0.5f); + + // Derivation (d is distance, b is haze coefficient, f is attenuation, solve for f = 0.05 + // f = exp(-d * b) + // ln(f) = -d * b + // b = -ln(f)/d + inline glm::vec3 convertHazeRangeToHazeRangeFactor(const glm::vec3 hazeRange_m) { + return glm::vec3( + -LOG_P_005 / hazeRange_m.x, + -LOG_P_005 / hazeRange_m.y, + -LOG_P_005 / hazeRange_m.z); + } + + // limit range and altitude to no less than 1.0 metres + inline float convertHazeRangeToHazeRangeFactor(const float hazeRange_m) { return -LOG_P_005 / glm::max(hazeRange_m, 1.0f); } + + inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeHeight_m) { return -LOG_P_005 / glm::max(hazeHeight_m, 1.0f); } + + // Derivation (s is the proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5 + // s = dot(lookAngle, sunAngle) = cos(a) + // m = pow(s, p) + // log(m) = p * log(s) + // p = log(m) / log(s) + // limit to 0.1 degrees + inline float convertGlareAngleToPower(const float hazeGlareAngle) { + const float GLARE_ANGLE_LIMIT = 0.1f; + return LOG_P_05 / logf(cosf(RADIANS_PER_DEGREE * glm::max(GLARE_ANGLE_LIMIT, hazeGlareAngle))); + } + + const float initialHazeRange_m{ 1000.0f }; + const float initialHazeHeight_m{ 200.0f }; + + const float initialHazeKeyLightRange_m{ 1000.0f }; + const float initialHazeKeyLightAltitude_m{ 200.0f }; + + const float initialHazeBackgroundBlend{ 0.0f }; + + const glm::vec3 initialColorModulationFactor{ + convertHazeRangeToHazeRangeFactor(initialHazeRange_m), + convertHazeRangeToHazeRangeFactor(initialHazeRange_m), + convertHazeRangeToHazeRangeFactor(initialHazeRange_m) + }; + + const glm::vec3 initialHazeColor{ 0.5f, 0.6f, 0.7f }; // Bluish + const xColor initialHazeColorXcolor{ 128, 154, 179 }; + + const float initialGlareAngle_degs{ 20.0f }; + + const glm::vec3 initialHazeGlareColor{ 1.0f, 0.9f, 0.7f }; + const xColor initialHazeGlareColorXcolor{ 255, 229, 179 }; + + const float initialHazeBaseReference_m{ 0.0f }; +} +#endif // hifi_model_HazeInit_h diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index cc20f6335e..f70daf1e77 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -134,7 +134,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu color += directionalSpecular; // Attenuate the light if haze effect selected - if ((hazeParams.hazeMode & HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED) == HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED) { + if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { // Directional light attenuation is simulated by assuming the light source is at a fixed height above the // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height // @@ -147,8 +147,8 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen) float height_95p = 2000.0; - if (hazeParams.hazeAltitudeFactorKeyLight > 0.0f) { - height_95p = -log(0.05) / hazeParams.hazeAltitudeFactorKeyLight; + if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) { + height_95p = -log(0.05) / hazeParams.hazeKeyLightAltitudeFactor; } // Note that the sine will always be positive @@ -168,8 +168,8 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu // Integration is from the fragment towards the light source // Note that the haze base reference affects only the haze density as function of altitude float hazeDensityDistribution = - hazeParams.hazeRangeFactorKeyLight * - exp(-hazeParams.hazeAltitudeFactorKeyLight * (worldFragPos.y - hazeParams.hazeBaseReference)); + hazeParams.hazeKeyLightRangeFactor * + exp(-hazeParams.hazeKeyLightAltitudeFactor * (worldFragPos.y - hazeParams.hazeBaseReference)); float hazeIntegral = hazeDensityDistribution * distance; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index b6a91888a1..e6a33a9911 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -498,7 +498,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, auto lightStage = renderContext->_scene->getStage(); assert(lightStage); assert(lightStage->getNumLights() > 0); - auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow(); + auto lightAndShadow = lightStage->getLightAndShadow(0); const auto& globalShadow = lightAndShadow.second; // Bind the shadow buffer @@ -509,7 +509,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, auto& program = deferredLightingEffect->_directionalSkyboxLight; LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations; - auto keyLight = lightAndShadow.first; + auto keyLight = lightStage->getLight(0); // Setup the global directional pass pipeline { diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index bf254ce80e..071db8cf25 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -33,24 +33,24 @@ void HazeConfig::setHazeColorB(const float value) { hazeColorB = value; } -void HazeConfig::setDirectionalLightAngle_degs(const float value) { - hazeDirectionalLightAngle_degs = value; +void HazeConfig::setHazeGlareAngle_degs(const float value) { + hazeGlareAngle_degs = value; } -void HazeConfig::setDirectionalLightColorR(const float value) { - hazeDirectionalLightColorR = value; +void HazeConfig::setHazeGlareColorR(const float value) { + hazeGlareColorR = value; } -void HazeConfig::setDirectionalLightColorG(const float value) { - hazeDirectionalLightColorG = value; +void HazeConfig::setHazeGlareColorG(const float value) { + hazeGlareColorG = value; } -void HazeConfig::setDirectionalLightColorB(const float value) { - hazeDirectionalLightColorB = value; +void HazeConfig::setHazeGlareColorB(const float value) { + hazeGlareColorB = value; } void HazeConfig::setHazeBaseReference(const float value) { - hazeBaseReference = value; + hazeBaseReference_m = value; } void HazeConfig::setHazeActive(const bool active) { @@ -78,7 +78,7 @@ void HazeConfig::setHazeRange_m(const float value) { } void HazeConfig::setHazeAltitude_m(const float value) { - hazeAltitude_m = value; + hazeHeight_m = value; } void HazeConfig::setHazeKeyLightRange_m(const float value) { @@ -89,8 +89,8 @@ void HazeConfig::setHazeKeyLightAltitude_m(const float value) { hazeKeyLightAltitude_m = value; } -void HazeConfig::setHazeBackgroundBlendValue(const float value) { - hazeBackgroundBlendValue = value; +void HazeConfig::setHazeBackgroundBlend(const float value) { + hazeBackgroundBlend = value; } MakeHaze::MakeHaze() { @@ -99,10 +99,10 @@ MakeHaze::MakeHaze() { void MakeHaze::configure(const Config& config) { _haze->setHazeColor(glm::vec3(config.hazeColorR, config.hazeColorG, config.hazeColorB)); - _haze->setDirectionalLightBlend(model::convertDirectionalLightAngleToPower(config.hazeDirectionalLightAngle_degs)); + _haze->setHazeGlareBlend(model::convertGlareAngleToPower(config.hazeGlareAngle_degs)); - _haze->setDirectionalLightColor(glm::vec3(config.hazeDirectionalLightColorR, config.hazeDirectionalLightColorG, config.hazeDirectionalLightColorB)); - _haze->setHazeBaseReference(config.hazeBaseReference); + _haze->setHazeGlareColor(glm::vec3(config.hazeGlareColorR, config.hazeGlareColorG, config.hazeGlareColorB)); + _haze->setHazeBaseReference(config.hazeBaseReference_m); _haze->setHazeActive(config.isHazeActive); _haze->setAltitudeBased(config.isAltitudeBased); @@ -111,12 +111,12 @@ void MakeHaze::configure(const Config& config) { _haze->setHazeEnableGlare(config.isHazeEnableGlare); _haze->setHazeRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeRange_m)); - _haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeAltitude_m)); + _haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight_m)); _haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange_m)); _haze->setHazeKeyLightAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude_m)); - _haze->setHazeBackgroundBlendValue(config.hazeBackgroundBlendValue); + _haze->setHazeBackgroundBlend(config.hazeBackgroundBlend); } void MakeHaze::run(const render::RenderContextPointer& renderContext, model::HazePointer& haze) { diff --git a/libraries/render-utils/src/DrawHaze.h b/libraries/render-utils/src/DrawHaze.h index 4a7b2135bd..e7a3f2c636 100644 --- a/libraries/render-utils/src/DrawHaze.h +++ b/libraries/render-utils/src/DrawHaze.h @@ -22,7 +22,7 @@ #include "SurfaceGeometryPass.h" -#include "model/Haze.h" +#include using LinearDepthFramebufferPointer = std::shared_ptr; @@ -32,12 +32,12 @@ class MakeHazeConfig : public render::Job::Config { Q_PROPERTY(float hazeColorR MEMBER hazeColorR WRITE setHazeColorR NOTIFY dirty); Q_PROPERTY(float hazeColorG MEMBER hazeColorG WRITE setHazeColorG NOTIFY dirty); Q_PROPERTY(float hazeColorB MEMBER hazeColorB WRITE setHazeColorB NOTIFY dirty); - Q_PROPERTY(float hazeDirectionalLightAngle_degs MEMBER hazeDirectionalLightAngle_degs WRITE setDirectionalLightAngle_degs NOTIFY dirty); + Q_PROPERTY(float hazeGlareAngle_degs MEMBER hazeGlareAngle_degs WRITE setHazeGlareAngle_degs NOTIFY dirty); - Q_PROPERTY(float hazeDirectionalLightColorR MEMBER hazeDirectionalLightColorR WRITE setDirectionalLightColorR NOTIFY dirty); - Q_PROPERTY(float hazeDirectionalLightColorG MEMBER hazeDirectionalLightColorG WRITE setDirectionalLightColorG NOTIFY dirty); - Q_PROPERTY(float hazeDirectionalLightColorB MEMBER hazeDirectionalLightColorB WRITE setDirectionalLightColorB NOTIFY dirty); - Q_PROPERTY(float hazeBaseReference MEMBER hazeBaseReference WRITE setHazeBaseReference NOTIFY dirty); + Q_PROPERTY(float hazeGlareColorR MEMBER hazeGlareColorR WRITE setHazeGlareColorR NOTIFY dirty); + Q_PROPERTY(float hazeGlareColorG MEMBER hazeGlareColorG WRITE setHazeGlareColorG NOTIFY dirty); + Q_PROPERTY(float hazeGlareColorB MEMBER hazeGlareColorB WRITE setHazeGlareColorB NOTIFY dirty); + Q_PROPERTY(float hazeBaseReference_m MEMBER hazeBaseReference_m WRITE setHazeBaseReference NOTIFY dirty); Q_PROPERTY(bool isHazeActive MEMBER isHazeActive WRITE setHazeActive NOTIFY dirty); Q_PROPERTY(bool isAltitudeBased MEMBER isAltitudeBased WRITE setAltitudeBased NOTIFY dirty); @@ -46,12 +46,12 @@ class MakeHazeConfig : public render::Job::Config { Q_PROPERTY(bool isHazeEnableGlare MEMBER isHazeEnableGlare WRITE setHazeEnableGlare NOTIFY dirty); Q_PROPERTY(float hazeRange_m MEMBER hazeRange_m WRITE setHazeRange_m NOTIFY dirty); - Q_PROPERTY(float hazeAltitude_m MEMBER hazeAltitude_m WRITE setHazeAltitude_m NOTIFY dirty); + Q_PROPERTY(float hazeHeight_m MEMBER hazeHeight_m WRITE setHazeAltitude_m NOTIFY dirty); Q_PROPERTY(float hazeKeyLightRange_m MEMBER hazeKeyLightRange_m WRITE setHazeKeyLightRange_m NOTIFY dirty); Q_PROPERTY(float hazeKeyLightAltitude_m MEMBER hazeKeyLightAltitude_m WRITE setHazeKeyLightAltitude_m NOTIFY dirty); - Q_PROPERTY(float hazeBackgroundBlendValue MEMBER hazeBackgroundBlendValue WRITE setHazeBackgroundBlendValue NOTIFY dirty); + Q_PROPERTY(float hazeBackgroundBlend MEMBER hazeBackgroundBlend WRITE setHazeBackgroundBlend NOTIFY dirty); public: MakeHazeConfig() : render::Job::Config() {} @@ -59,12 +59,12 @@ public: float hazeColorR{ model::initialHazeColor.r }; float hazeColorG{ model::initialHazeColor.g }; float hazeColorB{ model::initialHazeColor.b }; - float hazeDirectionalLightAngle_degs{ model::initialDirectionalLightAngle_degs }; + float hazeGlareAngle_degs{ model::initialGlareAngle_degs }; - float hazeDirectionalLightColorR{ model::initialDirectionalLightColor.r }; - float hazeDirectionalLightColorG{ model::initialDirectionalLightColor.g }; - float hazeDirectionalLightColorB{ model::initialDirectionalLightColor.b }; - float hazeBaseReference{ model::initialHazeBaseReference }; + float hazeGlareColorR{ model::initialHazeGlareColor.r }; + float hazeGlareColorG{ model::initialHazeGlareColor.g }; + float hazeGlareColorB{ model::initialHazeGlareColor.b }; + float hazeBaseReference_m{ model::initialHazeBaseReference_m }; bool isHazeActive{ false }; bool isAltitudeBased{ false }; @@ -73,23 +73,23 @@ public: bool isHazeEnableGlare{ false }; float hazeRange_m{ model::initialHazeRange_m }; - float hazeAltitude_m{ model::initialHazeAltitude_m }; + float hazeHeight_m{ model::initialHazeHeight_m }; float hazeKeyLightRange_m{ model::initialHazeKeyLightRange_m }; float hazeKeyLightAltitude_m{ model::initialHazeKeyLightAltitude_m }; - float hazeBackgroundBlendValue{ model::initialHazeBackgroundBlendValue }; + float hazeBackgroundBlend{ model::initialHazeBackgroundBlend }; public slots: void setHazeColorR(const float value) { hazeColorR = value; emit dirty(); } void setHazeColorG(const float value) { hazeColorG = value; emit dirty(); } void setHazeColorB(const float value) { hazeColorB = value; emit dirty(); } - void setDirectionalLightAngle_degs(const float value) { hazeDirectionalLightAngle_degs = value; emit dirty(); } + void setHazeGlareAngle_degs(const float value) { hazeGlareAngle_degs = value; emit dirty(); } - void setDirectionalLightColorR(const float value) { hazeDirectionalLightColorR = value; emit dirty(); } - void setDirectionalLightColorG(const float value) { hazeDirectionalLightColorG = value; emit dirty(); } - void setDirectionalLightColorB(const float value) { hazeDirectionalLightColorB = value; emit dirty(); } - void setHazeBaseReference(const float value) { hazeBaseReference = value; ; emit dirty(); } + void setHazeGlareColorR(const float value) { hazeGlareColorR = value; emit dirty(); } + void setHazeGlareColorG(const float value) { hazeGlareColorG = value; emit dirty(); } + void setHazeGlareColorB(const float value) { hazeGlareColorB = value; emit dirty(); } + void setHazeBaseReference(const float value) { hazeBaseReference_m = value; ; emit dirty(); } void setHazeActive(const bool active) { isHazeActive = active; emit dirty(); } void setAltitudeBased(const bool active) { isAltitudeBased = active; emit dirty(); } @@ -98,12 +98,12 @@ public slots: void setHazeEnableGlare(const bool active) { isHazeEnableGlare = active; emit dirty(); } void setHazeRange_m(const float value) { hazeRange_m = value; emit dirty(); } - void setHazeAltitude_m(const float value) { hazeAltitude_m = value; emit dirty(); } + void setHazeAltitude_m(const float value) { hazeHeight_m = value; emit dirty(); } void setHazeKeyLightRange_m(const float value) { hazeKeyLightRange_m = value; emit dirty(); } void setHazeKeyLightAltitude_m(const float value) { hazeKeyLightAltitude_m = value; emit dirty(); } - void setHazeBackgroundBlendValue(const float value) { hazeBackgroundBlendValue = value; ; emit dirty(); } + void setHazeBackgroundBlend(const float value) { hazeBackgroundBlend = value; ; emit dirty(); } signals: void dirty(); @@ -131,12 +131,12 @@ public: float hazeColorR{ model::initialHazeColor.r }; float hazeColorG{ model::initialHazeColor.g }; float hazeColorB{ model::initialHazeColor.b }; - float hazeDirectionalLightAngle_degs{ model::initialDirectionalLightAngle_degs }; + float hazeGlareAngle_degs{ model::initialGlareAngle_degs }; - float hazeDirectionalLightColorR{ model::initialDirectionalLightColor.r }; - float hazeDirectionalLightColorG{ model::initialDirectionalLightColor.g }; - float hazeDirectionalLightColorB{ model::initialDirectionalLightColor.b }; - float hazeBaseReference{ model::initialHazeBaseReference }; + float hazeGlareColorR{ model::initialHazeGlareColor.r }; + float hazeGlareColorG{ model::initialHazeGlareColor.g }; + float hazeGlareColorB{ model::initialHazeGlareColor.b }; + float hazeBaseReference_m{ model::initialHazeBaseReference_m }; bool isHazeActive{ false }; // Setting this to true will set haze to on bool isAltitudeBased{ false }; @@ -145,22 +145,22 @@ public: bool isHazeEnableGlare{ false }; float hazeRange_m{ model::initialHazeRange_m }; - float hazeAltitude_m{ model::initialHazeAltitude_m }; + float hazeHeight_m{ model::initialHazeHeight_m }; float hazeKeyLightRange_m{ model::initialHazeKeyLightRange_m }; float hazeKeyLightAltitude_m{ model::initialHazeKeyLightAltitude_m }; - float hazeBackgroundBlendValue{ model::initialHazeBackgroundBlendValue }; + float hazeBackgroundBlend{ model::initialHazeBackgroundBlend }; // methods void setHazeColorR(const float value); void setHazeColorG(const float value); void setHazeColorB(const float value); - void setDirectionalLightAngle_degs(const float value); + void setHazeGlareAngle_degs(const float value); - void setDirectionalLightColorR(const float value); - void setDirectionalLightColorG(const float value); - void setDirectionalLightColorB(const float value); + void setHazeGlareColorR(const float value); + void setHazeGlareColorG(const float value); + void setHazeGlareColorB(const float value); void setHazeBaseReference(const float value); void setHazeActive(const bool active); @@ -175,7 +175,7 @@ public: void setHazeKeyLightRange_m(const float value); void setHazeKeyLightAltitude_m(const float value); - void setHazeBackgroundBlendValue(const float value); + void setHazeBackgroundBlend(const float value); }; class DrawHaze { diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index 77c820e093..b366e6d639 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -60,15 +60,15 @@ void main(void) { Light light = getLight(); vec3 lightDirection = getLightDirection(light); - float directionalLightComponent = max(0.0, dot(eyeFragDir, -lightDirection)); - float power = min(1.0, pow(directionalLightComponent, hazeParams.directionalLightBlend)); + float glareComponent = max(0.0, dot(eyeFragDir, -lightDirection)); + float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend)); - vec4 directionalLightColor = vec4(hazeParams.directionalLightColor, 1.0); + vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0); - // Use the haze colour for the belnd-out colour, if blend is not enabled + // Use the haze colour for the glare colour, if blend is not enabled vec4 blendedHazeColor; if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) { - blendedHazeColor = mix(hazeColor, directionalLightColor, power); + blendedHazeColor = mix(hazeColor, glareColor, power); } else { blendedHazeColor = hazeColor; } @@ -86,14 +86,14 @@ void main(void) { // Note that the haze base reference affects only the haze density as function of altitude vec3 hazeDensityDistribution = hazeParams.colorModulationFactor * - exp(-hazeParams.hazeAltitudeFactor * (worldEyePos.y - hazeParams.hazeBaseReference)); + exp(-hazeParams.hazeHeightFactor * (worldEyePos.y - hazeParams.hazeBaseReference)); vec3 hazeIntegral = hazeDensityDistribution * distance; const float slopeThreshold = 0.01; float deltaHeight = worldFragPos.y - worldEyePos.y; if (abs(deltaHeight) > slopeThreshold) { - float t = hazeParams.hazeAltitudeFactor * deltaHeight; + float t = hazeParams.hazeHeightFactor * deltaHeight; hazeIntegral *= (1.0 - exp (-t)) / t; } @@ -117,14 +117,14 @@ void main(void) { // Note that the haze base reference affects only the haze density as function of altitude float hazeDensityDistribution = hazeParams.hazeRangeFactor * - exp(-hazeParams.hazeAltitudeFactor * (worldEyePos.y - hazeParams.hazeBaseReference)); + exp(-hazeParams.hazeHeightFactor * (worldEyePos.y - hazeParams.hazeBaseReference)); float hazeIntegral = hazeDensityDistribution * distance; const float slopeThreshold = 0.01; float deltaHeight = worldFragPos.y - worldEyePos.y; if (abs(deltaHeight) > slopeThreshold) { - float t = hazeParams.hazeAltitudeFactor * deltaHeight; + float t = hazeParams.hazeHeightFactor * deltaHeight; // Protect from wild values if (abs(t) > 0.0000001) { hazeIntegral *= (1.0 - exp (-t)) / t; @@ -140,7 +140,7 @@ void main(void) { // Mix with background at far range const float BLEND_DISTANCE = 27000.0; if (distance > BLEND_DISTANCE) { - outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlendValue); + outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend); } else { outFragColor = potentialFragColor; } diff --git a/libraries/render-utils/src/Haze.slh b/libraries/render-utils/src/Haze.slh index 614431dce7..de7f0ac246 100644 --- a/libraries/render-utils/src/Haze.slh +++ b/libraries/render-utils/src/Haze.slh @@ -12,28 +12,28 @@ const int HAZE_MODE_IS_ACTIVE = 1 << 0; const int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1; -const int HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED = 1 << 2; +const int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2; const int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3; const int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4; struct HazeParams { vec3 hazeColor; - float directionalLightBlend; + float hazeGlareBlend; - vec3 directionalLightColor; + vec3 hazeGlareColor; float hazeBaseReference; vec3 colorModulationFactor; int hazeMode; mat4 zoneTransform; - float backgroundBlendValue; + float backgroundBlend; float hazeRangeFactor; - float hazeAltitudeFactor; + float hazeHeightFactor; - float hazeRangeFactorKeyLight; - float hazeAltitudeFactorKeyLight; + float hazeKeyLightRangeFactor; + float hazeKeyLightAltitudeFactor; }; layout(std140) uniform hazeBuffer { diff --git a/libraries/render-utils/src/HazeStage.cpp b/libraries/render-utils/src/HazeStage.cpp index aa7a7f554c..6a6104a1df 100644 --- a/libraries/render-utils/src/HazeStage.cpp +++ b/libraries/render-utils/src/HazeStage.cpp @@ -21,10 +21,10 @@ FetchHazeStage::FetchHazeStage() { void FetchHazeStage::configure(const Config& config) { _haze->setHazeColor(glm::vec3(config.hazeColorR, config.hazeColorG, config.hazeColorB)); - _haze->setDirectionalLightBlend(model::convertDirectionalLightAngleToPower(config.hazeDirectionalLightAngle_degs)); + _haze->setHazeGlareBlend(model::convertGlareAngleToPower(config.hazeGlareAngle_degs)); - _haze->setDirectionalLightColor(glm::vec3(config.hazeDirectionalLightColorR, config.hazeDirectionalLightColorG, config.hazeDirectionalLightColorB)); - _haze->setHazeBaseReference(config.hazeBaseReference); + _haze->setHazeGlareColor(glm::vec3(config.hazeGlareColorR, config.hazeGlareColorG, config.hazeGlareColorB)); + _haze->setHazeBaseReference(config.hazeBaseReference_m); _haze->setHazeActive(config.isHazeActive); _haze->setAltitudeBased(config.isAltitudeBased); @@ -33,12 +33,12 @@ void FetchHazeStage::configure(const Config& config) { _haze->setHazeEnableGlare(config.isHazeEnableGlare); _haze->setHazeRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeRange_m)); - _haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeAltitude_m)); + _haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight_m)); _haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange_m)); _haze->setHazeKeyLightAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude_m)); - _haze->setHazeBackgroundBlendValue(config.hazeBackgroundBlendValue); + _haze->setHazeBackgroundBlend(config.hazeBackgroundBlend); } HazeStage::Index HazeStage::findHaze(const HazePointer& haze) const { diff --git a/libraries/render-utils/src/HazeStage.h b/libraries/render-utils/src/HazeStage.h index 7cc0c659b0..e2d09f3011 100644 --- a/libraries/render-utils/src/HazeStage.h +++ b/libraries/render-utils/src/HazeStage.h @@ -19,7 +19,7 @@ #include #include -#include "model/Haze.h" +#include // Haze stage to set up haze-related rendering tasks class HazeStage : public render::Stage { @@ -86,12 +86,12 @@ class FetchHazeConfig : public render::Job::Config { Q_PROPERTY(float hazeColorR MEMBER hazeColorR WRITE setHazeColorR NOTIFY dirty); Q_PROPERTY(float hazeColorG MEMBER hazeColorG WRITE setHazeColorG NOTIFY dirty); Q_PROPERTY(float hazeColorB MEMBER hazeColorB WRITE setHazeColorB NOTIFY dirty); - Q_PROPERTY(float hazeDirectionalLightAngle_degs MEMBER hazeDirectionalLightAngle_degs WRITE setDirectionalLightAngle_degs NOTIFY dirty); + Q_PROPERTY(float hazeGlareAngle_degs MEMBER hazeGlareAngle_degs WRITE setHazeGlareAngle_degs NOTIFY dirty); - Q_PROPERTY(float hazeDirectionalLightColorR MEMBER hazeDirectionalLightColorR WRITE setDirectionalLightColorR NOTIFY dirty); - Q_PROPERTY(float hazeDirectionalLightColorG MEMBER hazeDirectionalLightColorG WRITE setDirectionalLightColorG NOTIFY dirty); - Q_PROPERTY(float hazeDirectionalLightColorB MEMBER hazeDirectionalLightColorB WRITE setDirectionalLightColorB NOTIFY dirty); - Q_PROPERTY(float hazeBaseReference MEMBER hazeBaseReference WRITE setHazeBaseReference NOTIFY dirty); + Q_PROPERTY(float hazeGlareColorR MEMBER hazeGlareColorR WRITE setHazeGlareColorR NOTIFY dirty); + Q_PROPERTY(float hazeGlareColorG MEMBER hazeGlareColorG WRITE setHazeGlareColorG NOTIFY dirty); + Q_PROPERTY(float hazeGlareColorB MEMBER hazeGlareColorB WRITE setHazeGlareColorB NOTIFY dirty); + Q_PROPERTY(float hazeBaseReference_m MEMBER hazeBaseReference_m WRITE setHazeBaseReference NOTIFY dirty); Q_PROPERTY(bool isHazeActive MEMBER isHazeActive WRITE setHazeActive NOTIFY dirty); Q_PROPERTY(bool isAltitudeBased MEMBER isAltitudeBased WRITE setAltitudeBased NOTIFY dirty); @@ -100,12 +100,12 @@ class FetchHazeConfig : public render::Job::Config { Q_PROPERTY(bool isHazeEnableGlare MEMBER isHazeEnableGlare WRITE setHazeEnableGlare NOTIFY dirty); Q_PROPERTY(float hazeRange_m MEMBER hazeRange_m WRITE setHazeRange_m NOTIFY dirty); - Q_PROPERTY(float hazeAltitude_m MEMBER hazeAltitude_m WRITE setHazeAltitude_m NOTIFY dirty); + Q_PROPERTY(float hazeHeight_m MEMBER hazeHeight_m WRITE setHazeAltitude_m NOTIFY dirty); Q_PROPERTY(float hazeKeyLightRange_m MEMBER hazeKeyLightRange_m WRITE setHazeKeyLightRange_m NOTIFY dirty); Q_PROPERTY(float hazeKeyLightAltitude_m MEMBER hazeKeyLightAltitude_m WRITE setHazeKeyLightAltitude_m NOTIFY dirty); - Q_PROPERTY(float hazeBackgroundBlendValue MEMBER hazeBackgroundBlendValue WRITE setHazeBackgroundBlendValue NOTIFY dirty); + Q_PROPERTY(float hazeBackgroundBlend MEMBER hazeBackgroundBlend WRITE setHazeBackgroundBlend NOTIFY dirty); public: FetchHazeConfig() : render::Job::Config() {} @@ -113,12 +113,12 @@ public: float hazeColorR{ model::initialHazeColor.r }; float hazeColorG{ model::initialHazeColor.g }; float hazeColorB{ model::initialHazeColor.b }; - float hazeDirectionalLightAngle_degs{ model::initialDirectionalLightAngle_degs }; + float hazeGlareAngle_degs{ model::initialGlareAngle_degs }; - float hazeDirectionalLightColorR{ model::initialDirectionalLightColor.r }; - float hazeDirectionalLightColorG{ model::initialDirectionalLightColor.g }; - float hazeDirectionalLightColorB{ model::initialDirectionalLightColor.b }; - float hazeBaseReference{ model::initialHazeBaseReference }; + float hazeGlareColorR{ model::initialHazeGlareColor.r }; + float hazeGlareColorG{ model::initialHazeGlareColor.g }; + float hazeGlareColorB{ model::initialHazeGlareColor.b }; + float hazeBaseReference_m{ model::initialHazeBaseReference_m }; bool isHazeActive{ false }; bool isAltitudeBased{ false }; @@ -127,23 +127,23 @@ public: bool isHazeEnableGlare{ false }; float hazeRange_m{ model::initialHazeRange_m }; - float hazeAltitude_m{ model::initialHazeAltitude_m }; + float hazeHeight_m{ model::initialHazeHeight_m }; float hazeKeyLightRange_m{ model::initialHazeKeyLightRange_m }; float hazeKeyLightAltitude_m{ model::initialHazeKeyLightAltitude_m }; - float hazeBackgroundBlendValue{ model::initialHazeBackgroundBlendValue }; + float hazeBackgroundBlend{ model::initialHazeBackgroundBlend }; public slots: void setHazeColorR(const float value) { hazeColorR = value; emit dirty(); } void setHazeColorG(const float value) { hazeColorG = value; emit dirty(); } void setHazeColorB(const float value) { hazeColorB = value; emit dirty(); } - void setDirectionalLightAngle_degs(const float value) { hazeDirectionalLightAngle_degs = value; emit dirty(); } + void setHazeGlareAngle_degs(const float value) { hazeGlareAngle_degs = value; emit dirty(); } - void setDirectionalLightColorR(const float value) { hazeDirectionalLightColorR = value; emit dirty(); } - void setDirectionalLightColorG(const float value) { hazeDirectionalLightColorG = value; emit dirty(); } - void setDirectionalLightColorB(const float value) { hazeDirectionalLightColorB = value; emit dirty(); } - void setHazeBaseReference(const float value) { hazeBaseReference = value; ; emit dirty(); } + void setHazeGlareColorR(const float value) { hazeGlareColorR = value; emit dirty(); } + void setHazeGlareColorG(const float value) { hazeGlareColorG = value; emit dirty(); } + void setHazeGlareColorB(const float value) { hazeGlareColorB = value; emit dirty(); } + void setHazeBaseReference(const float value) { hazeBaseReference_m = value; ; emit dirty(); } void setHazeActive(const bool active) { isHazeActive = active; emit dirty(); } void setAltitudeBased(const bool active) { isAltitudeBased = active; emit dirty(); } @@ -152,12 +152,12 @@ public slots: void setHazeEnableGlare(const bool active) { isHazeEnableGlare = active; emit dirty(); } void setHazeRange_m(const float value) { hazeRange_m = value; emit dirty(); } - void setHazeAltitude_m(const float value) { hazeAltitude_m = value; emit dirty(); } + void setHazeAltitude_m(const float value) { hazeHeight_m = value; emit dirty(); } void setHazeKeyLightRange_m(const float value) { hazeKeyLightRange_m = value; emit dirty(); } void setHazeKeyLightAltitude_m(const float value) { hazeKeyLightAltitude_m = value; emit dirty(); } - void setHazeBackgroundBlendValue(const float value) { hazeBackgroundBlendValue = value; ; emit dirty(); } + void setHazeBackgroundBlend(const float value) { hazeBackgroundBlend = value; ; emit dirty(); } signals: void dirty(); diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 2d5dd35e66..f898eb3b9a 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -570,14 +570,14 @@
-
+
Haze Color
-
+
-
+
-
+
@@ -586,14 +586,14 @@
-
+
Glare Color
-
+
-
+
-
+
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index a015eed714..0463ac4172 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -678,14 +678,14 @@ function loaded() { var elZoneHazeModeEnabled = document.getElementById("property-zone-haze-mode-enabled"); var elZoneHazeRange = document.getElementById("property-zone-haze-range"); - var elZoneHazeColor = document.getElementById("property-zone-haze-blend-in-color"); - var elZoneHazeColorRed = document.getElementById("property-zone-haze-blend-in-color-red"); - var elZoneHazeColorGreen = document.getElementById("property-zone-haze-blend-in-color-green"); - var elZoneHazeColorBlue = document.getElementById("property-zone-haze-blend-in-color-blue"); - var elZoneHazeGlareColor = document.getElementById("property-zone-haze-blend-out-color"); - var elZoneHazeGlareColorRed = document.getElementById("property-zone-haze-blend-out-color-red"); - var elZoneHazeGlareColorGreen = document.getElementById("property-zone-haze-blend-out-color-green"); - var elZoneHazeGlareColorBlue = document.getElementById("property-zone-haze-blend-out-color-blue"); + var elZoneHazeColor = document.getElementById("property-zone-haze-color"); + var elZoneHazeColorRed = document.getElementById("property-zone-haze-color-red"); + var elZoneHazeColorGreen = document.getElementById("property-zone-haze-color-green"); + var elZoneHazeColorBlue = document.getElementById("property-zone-haze-color-blue"); + var elZoneHazeGlareColor = document.getElementById("property-zone-haze-glare-color"); + var elZoneHazeGlareColorRed = document.getElementById("property-zone-haze-glare-color-red"); + var elZoneHazeGlareColorGreen = document.getElementById("property-zone-haze-glare-color-green"); + var elZoneHazeGlareColorBlue = document.getElementById("property-zone-haze-glare-color-blue"); var elZoneHazeEnableGlare = document.getElementById("property-zone-haze-enable-light-blend"); var elZonehazeGlareAngle = document.getElementById("property-zone-haze-blend-angle"); @@ -1474,15 +1474,15 @@ function loaded() { elZoneHazeRange.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeRange')); - colorPickers.push($('#property-zone-haze-blend-in-color').colpick({ + colorPickers.push($('#property-zone-haze-color').colpick({ colorScheme: 'dark', layout: 'hex', color: '000000', onShow: function(colpick) { - $('#property-zone-haze-blend-in-color').attr('active', 'true'); + $('#property-zone-haze-color').attr('active', 'true'); }, onHide: function(colpick) { - $('#property-zone-haze-blend-in-color').attr('active', 'false'); + $('#property-zone-haze-color').attr('active', 'false'); }, onSubmit: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); @@ -1499,15 +1499,15 @@ function loaded() { elZoneHazeColorGreen.addEventListener('change', zoneHazeColorChangeFunction); elZoneHazeColorBlue.addEventListener('change', zoneHazeColorChangeFunction); - colorPickers.push($('#property-zone-haze-blend-out-color').colpick({ + colorPickers.push($('#property-zone-haze-glare-color').colpick({ colorScheme: 'dark', layout: 'hex', color: '000000', onShow: function(colpick) { - $('#property-zone-haze-blend-out-color').attr('active', 'true'); + $('#property-zone-haze-glare-color').attr('active', 'true'); }, onHide: function(colpick) { - $('#property-zone-haze-blend-out-color').attr('active', 'false'); + $('#property-zone-haze-glare-color').attr('active', 'false'); }, onSubmit: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); From 2c4d4373dc87d4a76030c3690180c712d266936d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 27 Oct 2017 10:41:16 -0700 Subject: [PATCH 052/183] support asymmetrical cross section Cylinder --- libraries/entities/src/ShapeEntityItem.cpp | 37 ++++++++++++++-------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 8c7d1576e1..4115a606df 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -51,12 +51,12 @@ namespace entity { } } -// shapeCalculator is a hook for external code that knows how to configure a ShapeInfo +// hullShapeCalculator is a hook for external code that knows how to configure a ShapeInfo // for given entity::Shape and dimensions -ShapeEntityItem::ShapeInfoCalculator shapeCalculator = nullptr; +ShapeEntityItem::ShapeInfoCalculator hullShapeCalculator = nullptr; void ShapeEntityItem::setShapeInfoCalulator(ShapeEntityItem::ShapeInfoCalculator callback) { - shapeCalculator = callback; + hullShapeCalculator = callback; } ShapeEntityItem::Pointer ShapeEntityItem::baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -276,7 +276,6 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { } break; case entity::Shape::Sphere: { - float diameter = entityDimensions.x; const float MIN_DIAMETER = 0.001f; const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; @@ -293,13 +292,25 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { case entity::Shape::Circle: // Circles collide like flat Cylinders case entity::Shape::Cylinder: { - _collisionShapeType = SHAPE_TYPE_CYLINDER_Y; + float diameter = entityDimensions.x; + const float MIN_DIAMETER = 0.001f; + const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; + if (diameter > MIN_DIAMETER + && fabsf(diameter - entityDimensions.z) / diameter < MIN_RELATIVE_SPHERICAL_ERROR) { + _collisionShapeType = SHAPE_TYPE_SPHERE; + } else if (hullShapeCalculator) { + hullShapeCalculator(this, info); + _collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; + } else { + // woops, someone forgot to hook up the hullShapeCalculator()! + // final fallback is ellipsoid + _collisionShapeType = SHAPE_TYPE_ELLIPSOID; + } } break; case entity::Shape::Cone: { - if (shapeCalculator) { - shapeCalculator(this, info); - // shapeCalculator only supports convex shapes (e.g. SHAPE_TYPE_HULL) + if (hullShapeCalculator) { + hullShapeCalculator(this, info); _collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; } else { _collisionShapeType = SHAPE_TYPE_ELLIPSOID; @@ -310,9 +321,8 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { case entity::Shape::Triangle: case entity::Shape::Hexagon: case entity::Shape::Octagon: { - if (shapeCalculator) { - shapeCalculator(this, info); - // shapeCalculator only supports convex shapes (e.g. SHAPE_TYPE_HULL) + if (hullShapeCalculator) { + hullShapeCalculator(this, info); _collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; } else { _collisionShapeType = SHAPE_TYPE_ELLIPSOID; @@ -324,9 +334,8 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { case entity::Shape::Octahedron: case entity::Shape::Dodecahedron: case entity::Shape::Icosahedron: { - if ( shapeCalculator ) { - shapeCalculator(this, info); - // shapeCalculator only supports convex shapes (e.g. SHAPE_TYPE_HULL) + if ( hullShapeCalculator ) { + hullShapeCalculator(this, info); _collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; } else { _collisionShapeType = SHAPE_TYPE_ELLIPSOID; From 3a977f60397077aa2a7f18712c41736c6b354f24 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 27 Oct 2017 22:59:23 +0200 Subject: [PATCH 053/183] Disabled stereo in batch when using full screen outline --- libraries/render-utils/src/OutlineEffect.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index f459ddc42c..ad4c59b35a 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -278,6 +278,9 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I auto outlineFrameBuffer = inputs.get1(); auto outlineRect = inputs.get3(); + // TODO : If scissor isn't possible in stereo, send the AABox in the shader + // and do a raycasting per pixel to determine if we need to do the outline + // This should improve performance. if (outlineFrameBuffer && outlineRect.z>0 && outlineRect.w>0) { auto sceneDepthBuffer = inputs.get2(); const auto frameTransform = inputs.get0(); @@ -299,6 +302,9 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { +#if !OUTLINE_USE_SCISSOR + batch.enableStereo(false); +#endif batch.setFramebuffer(destinationFrameBuffer); batch.setViewportTransform(args->_viewport); From bea0df8e60a443e87f38ee9336f7e0f712b4140b Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 27 Oct 2017 14:46:04 -0700 Subject: [PATCH 054/183] implemented remebering equiping entities offset --- .../controllerModules/equipEntity.js | 53 ++++++++++++------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 565a67e116..7843f3a18a 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -225,28 +225,41 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa } function getAttachPointForHotspotFromSettings(hotspot, hand) { + var skeletonModelURL = MyAvatar.skeletonModelURL; var attachPointSettings = getAttachPointSettings(); - var jointName = (hand === RIGHT_HAND) ? "RightHand" : "LeftHand"; - var joints = attachPointSettings[hotspot.key]; - if (joints) { - return joints[jointName]; - } else { - return undefined; + var avatarSettingsData = attachPointSettings[skeletonModelURL]; + if (avatarSettingsData) { + var jointName = (hand === RIGHT_HAND) ? "RightHand" : "LeftHand"; + var joints = avatarSettingsData[hotspot.key]; + if (joints) { + return joints[jointName]; + } } + return undefined; } function storeAttachPointForHotspotInSettings(hotspot, hand, offsetPosition, offsetRotation) { var attachPointSettings = getAttachPointSettings(); + var skeletonModelURL = MyAvatar.skeletonModelURL; + var avatarSettingsData = attachPointSettings[skeletonModelURL]; + if (!avatarSettingsData) { + avatarSettingsData = {}; + attachPointSettings[skeletonModelURL] = avatarSettingsData; + } var jointName = (hand === RIGHT_HAND) ? "RightHand" : "LeftHand"; - var joints = attachPointSettings[hotspot.key]; + var joints = avatarSettingsData[hotspot.key]; if (!joints) { joints = {}; - attachPointSettings[hotspot.key] = joints; + avatarSettingsData[hotspot.key] = joints; } joints[jointName] = [offsetPosition, offsetRotation]; setAttachPointSettings(attachPointSettings); } + function clearAttachPoints() { + setAttachPointSettings({}); + } + function EquipEntity(hand) { this.hand = hand; this.targetEntityID = null; @@ -538,6 +551,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa }; this.endEquipEntity = function () { + this.storeAttachPointInSettings(); Entities.editEntity(this.targetEntityID, { parentID: Uuid.NULL, parentJointIndex: -1 @@ -684,14 +698,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa if (dropDetected && !this.waitForTriggerRelease && this.triggerSmoothedGrab()) { this.waitForTriggerRelease = true; // store the offset attach points into preferences. - if (this.grabbedHotspot && this.targetEntityID) { - var prefprops = Entities.getEntityProperties(this.targetEntityID, ["localPosition", "localRotation"]); - if (prefprops && prefprops.localPosition && prefprops.localRotation) { - storeAttachPointForHotspotInSettings(this.grabbedHotspot, this.hand, - prefprops.localPosition, prefprops.localRotation); - } - } - this.endEquipEntity(); return makeRunningValues(false, [], []); } @@ -707,6 +713,16 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa return makeRunningValues(true, [this.targetEntityID], []); }; + this.storeAttachPointInSettings = function() { + if (this.grabbedHotspot && this.targetEntityID) { + var prefProps = Entities.getEntityProperties(this.targetEntityID, ["localPosition", "localRotation"]); + if (prefProps && prefProps.localPosition && prefProps.localRotation) { + storeAttachPointForHotspotInSettings(this.grabbedHotspot, this.hand, + prefProps.localPosition, prefProps.localRotation); + } + } + }; + this.cleanup = function () { if (this.targetEntityID) { this.endEquipEntity(); @@ -751,11 +767,12 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa enableDispatcherModule("LeftEquipEntity", leftEquipEntity); enableDispatcherModule("RightEquipEntity", rightEquipEntity); - this.cleanup = function () { + function cleanup() { leftEquipEntity.cleanup(); rightEquipEntity.cleanup(); disableDispatcherModule("LeftEquipEntity"); disableDispatcherModule("RightEquipEntity"); + clearAttachPoints(); }; - Script.scriptEnding.connect(this.cleanup); + Script.scriptEnding.connect(cleanup); }()); From a5a135c2bada77b0c7daff7163227a24ec47884e Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Fri, 27 Oct 2017 15:39:14 -0700 Subject: [PATCH 055/183] Fixes for 8672-8674. --- libraries/entities/src/EntityPropertyFlags.h | 36 +++---- libraries/entities/src/HazePropertyGroup.cpp | 1 + libraries/entities/src/ZoneEntityItem.cpp | 100 ------------------- libraries/entities/src/ZoneEntityItem.h | 41 -------- libraries/model/src/model/Stage.h | 22 ++-- 5 files changed, 30 insertions(+), 170 deletions(-) diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index c20b362b04..f0f22b0091 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -202,6 +202,24 @@ enum EntityPropertyList { PROP_ENTITY_INSTANCE_NUMBER, PROP_CERTIFICATE_ID, + PROP_HAZE_MODE, + + PROP_HAZE_RANGE, + PROP_HAZE_COLOR, + PROP_HAZE_GLARE_COLOR, + PROP_HAZE_ENABLE_GLARE, + PROP_HAZE_GLARE_ANGLE, + + PROP_HAZE_ALTITUDE_EFFECT, + PROP_HAZE_CEILING, + PROP_HAZE_BASE_REF, + + PROP_HAZE_BACKGROUND_BLEND, + + PROP_HAZE_ATTENUATE_KEYLIGHT, + PROP_HAZE_KEYLIGHT_RANGE, + PROP_HAZE_KEYLIGHT_ALTITUDE, + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, @@ -234,24 +252,6 @@ enum EntityPropertyList { PROP_STAGE_AUTOMATIC_HOURDAY = PROP_ANIMATION_FRAME_INDEX, PROP_BACKGROUND_MODE = PROP_MODEL_URL, - PROP_HAZE_MODE = PROP_COLOR, - - PROP_HAZE_RANGE = PROP_INTENSITY, - PROP_HAZE_COLOR = PROP_CUTOFF, - PROP_HAZE_GLARE_COLOR = PROP_EXPONENT, - PROP_HAZE_ENABLE_GLARE = PROP_IS_SPOTLIGHT, - PROP_HAZE_GLARE_ANGLE = PROP_DIFFUSE_COLOR, - - PROP_HAZE_ALTITUDE_EFFECT = PROP_AMBIENT_COLOR_UNUSED, - PROP_HAZE_CEILING = PROP_SPECULAR_COLOR_UNUSED, - PROP_HAZE_BASE_REF = PROP_LINEAR_ATTENUATION_UNUSED, - - PROP_HAZE_BACKGROUND_BLEND = PROP_QUADRATIC_ATTENUATION_UNUSED, - - PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_ANIMATION_FRAME_INDEX, - PROP_HAZE_KEYLIGHT_RANGE = PROP_MODEL_URL, - PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_ANIMATION_URL, - PROP_SKYBOX_COLOR = PROP_ANIMATION_URL, PROP_SKYBOX_URL = PROP_ANIMATION_FPS, PROP_KEYLIGHT_AMBIENT_URL = PROP_ANIMATION_PLAYING, diff --git a/libraries/entities/src/HazePropertyGroup.cpp b/libraries/entities/src/HazePropertyGroup.cpp index 3cc3e69960..f137fca5ce 100644 --- a/libraries/entities/src/HazePropertyGroup.cpp +++ b/libraries/entities/src/HazePropertyGroup.cpp @@ -293,6 +293,7 @@ EntityPropertyFlags HazePropertyGroup::getEntityProperties(EncodeBitstreamParams requestedProperties += PROP_HAZE_ENABLE_GLARE; requestedProperties += PROP_HAZE_GLARE_ANGLE; + requestedProperties += PROP_HAZE_ALTITUDE_EFFECT; requestedProperties += PROP_HAZE_CEILING; requestedProperties += PROP_HAZE_BASE_REF; diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 588c1f9386..8b3d22daaf 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -330,103 +330,3 @@ void ZoneEntityItem::setHazeMode(const uint32_t value) { uint32_t ZoneEntityItem::getHazeMode() const { return _hazeMode; } - -void ZoneEntityItem::setHazeRange(const float hazeRange) { - _hazeRange = hazeRange; - _hazePropertiesChanged = true; -} - -float ZoneEntityItem::getHazeRange() const { - return _hazeRange; -} - -void ZoneEntityItem::setHazeColor(const xColor hazeColor) { - _hazeColor = hazeColor; - _hazePropertiesChanged = true; -} - -xColor ZoneEntityItem::getHazeColor() const { - return _hazeColor; -} - -void ZoneEntityItem::setHazeGlareColor(const xColor hazeGlareColor) { - _hazeGlareColor = hazeGlareColor; - _hazePropertiesChanged = true; -} - -xColor ZoneEntityItem::getHazeGlareColor()const { - return _hazeGlareColor; -} - -void ZoneEntityItem::setHazeEnableGlare(const bool hazeEnableGlare) { - _hazeEnableGlare = hazeEnableGlare; - _hazePropertiesChanged = true; -} - -bool ZoneEntityItem::getHazeEnableGlare()const { - return _hazeEnableGlare; -} - -void ZoneEntityItem::setHazeGlareAngle(const float hazeGlareAngle) { - _hazeGlareAngle = hazeGlareAngle; - _hazePropertiesChanged = true; -} - -float ZoneEntityItem::getHazeGlareAngle() const { - return _hazeGlareAngle; -} - -void ZoneEntityItem::setHazeCeiling(const float hazeCeiling) { - _hazeCeiling = hazeCeiling; - _hazePropertiesChanged = true; -} - -float ZoneEntityItem::getHazeCeiling() const { - return _hazeCeiling; -} - -void ZoneEntityItem::setHazeBaseRef(const float hazeBaseRef) { - _hazeBaseRef = hazeBaseRef; - _hazePropertiesChanged = true; -} - -float ZoneEntityItem::getHazeBaseRef() const { - return _hazeBaseRef; -} - -void ZoneEntityItem::setHazeBackgroundBlend(const float hazeBackgroundBlend) { - _hazeBackgroundBlend = hazeBackgroundBlend; - _hazePropertiesChanged = true; -} - -float ZoneEntityItem::getHazeBackgroundBlend() const { - return _hazeBackgroundBlend; -} - -void ZoneEntityItem::setHazeAttenuateKeyLight(const bool hazeAttenuateKeyLight) { - _hazeAttenuateKeyLight = hazeAttenuateKeyLight; - _hazePropertiesChanged = true; -} - -bool ZoneEntityItem::getHazeAttenuateKeyLight() const { - return _hazeAttenuateKeyLight; -} - -void ZoneEntityItem::setHazeKeyLightRange(const float hazeKeyLightRange) { - _hazeKeyLightRange = hazeKeyLightRange; - _hazePropertiesChanged = true; -} - -float ZoneEntityItem::getHazeKeyLightRange() const { - return _hazeKeyLightRange; -} - -void ZoneEntityItem::setHazeKeyLightAltitude(const float hazeKeyLightAltitude) { - _hazeKeyLightAltitude = hazeKeyLightAltitude; - _hazePropertiesChanged = true; -} - -float ZoneEntityItem::getHazeKeyLightAltitude() const { - return _hazeKeyLightAltitude; -} - diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 628c228af6..ba5f3b3dee 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -74,32 +74,6 @@ public: void setHazeMode(const uint32_t value); uint32_t getHazeMode() const; - void setHazeRange(const float hazeRange); - float getHazeRange() const; - void setHazeColor(const xColor hazeColor); - xColor getHazeColor() const; - void setHazeGlareColor(const xColor hazeGlareColor); - xColor getHazeGlareColor() const; - void setHazeEnableGlare(const bool hazeEnableGlare); - bool getHazeEnableGlare() const; - void setHazeGlareAngle(const float hazeGlareAngle); - float getHazeGlareAngle() const; - - void setHazeCeiling(const float hazeCeiling); - float getHazeCeiling() const; - void setHazeBaseRef(const float hazeBaseRef); - float getHazeBaseRef() const; - - void setHazeBackgroundBlend(const float hazeBackgroundBlend); - float getHazeBackgroundBlend() const; - - void setHazeAttenuateKeyLight(const bool hazeAttenuateKeyLight); - bool getHazeAttenuateKeyLight() const; - void setHazeKeyLightRange(const float hazeKeyLightRange); - float getHazeKeyLightRange() const; - void setHazeKeyLightAltitude(const float hazeKeyLightAltitude); - float getHazeKeyLightAltitude() const; - SkyboxPropertyGroup getSkyboxProperties() const { return resultWithReadLock([&] { return _skyboxProperties; }); } const HazePropertyGroup& getHazeProperties() const { return _hazeProperties; } @@ -151,21 +125,6 @@ protected: uint32_t _hazeMode{ DEFAULT_HAZE_MODE }; - float _hazeRange{ model::initialHazeRange_m }; - xColor _hazeColor{ model::initialHazeColorXcolor }; - xColor _hazeGlareColor{ model::initialHazeGlareColorXcolor }; - bool _hazeEnableGlare{ false }; - float _hazeGlareAngle{ model::initialGlareAngle_degs }; - - float _hazeCeiling{ model::initialHazeBaseReference_m + model::initialHazeHeight_m }; - float _hazeBaseRef{ model::initialHazeBaseReference_m }; - - float _hazeBackgroundBlend{ model::initialHazeBackgroundBlend }; - - bool _hazeAttenuateKeyLight{ false }; - float _hazeKeyLightRange{ model::initialHazeKeyLightRange_m }; - float _hazeKeyLightAltitude{ model::initialHazeKeyLightAltitude_m }; - SkyboxPropertyGroup _skyboxProperties; HazePropertyGroup _hazeProperties; StagePropertyGroup _stageProperties; diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index e009684c62..a2eb7e3945 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -219,21 +219,21 @@ protected: uint8_t _hazeMode = (uint8_t)HAZE_OFF; - float _hazeRange; - xColor _hazeColor; - xColor _hazeGlareColor; - bool _hazeEnableGlare; - float _hazeGlareAngle; + float _hazeRange{ model::initialHazeRange_m }; + xColor _hazeColor{ model::initialHazeColorXcolor }; + xColor _hazeGlareColor{ model::initialHazeGlareColorXcolor }; + bool _hazeEnableGlare{ false }; + float _hazeGlareAngle{ model::initialGlareAngle_degs }; - bool _hazeAltitudeEffect; - float _hazeCeiling; + bool _hazeAltitudeEffect{ false }; + float _hazeCeiling{ model::initialHazeBaseReference_m + model::initialHazeHeight_m }; float _hazeBaseRef; - float _hazeBackgroundBlend; + float _hazeBackgroundBlend{ model::initialHazeBackgroundBlend }; - bool _hazeAttenuateKeyLight; - float _hazeKeyLightRange; - float _hazeKeyLightAltitude; + bool _hazeAttenuateKeyLight{ false }; + float _hazeKeyLightRange{ model::initialHazeKeyLightRange_m }; + float _hazeKeyLightAltitude{ model::initialHazeKeyLightAltitude_m }; LightPointer _sunLight; mutable SkyboxPointer _skybox; From d6b3fa4cb1bd65bd24a3bf6e9014d2e8e684c5fa Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Mon, 30 Oct 2017 10:49:08 -0700 Subject: [PATCH 056/183] Removed references to Haze from Stage. --- libraries/model/src/model/Stage.cpp | 7 -- libraries/model/src/model/Stage.h | 58 ----------- .../src/SceneScriptingInterface.cpp | 95 ------------------- .../src/SceneScriptingInterface.h | 52 ---------- 4 files changed, 212 deletions(-) diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index cd2312122c..5854162cfa 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -256,10 +256,3 @@ void SunSkyStage::setSkybox(const SkyboxPointer& skybox) { _skybox = skybox; invalidate(); } - -void SunSkyStage::setHazeMode(uint32_t hazeMode) { - if (hazeMode < COMPONENT_MODE_ITEM_COUNT) { - _hazeMode = hazeMode; - invalidate(); - } -} diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index a2eb7e3945..5f48824568 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -15,7 +15,6 @@ #include "Light.h" #include "Skybox.h" -#include "Haze.h" namespace model { @@ -175,65 +174,8 @@ public: void setSkybox(const SkyboxPointer& skybox); const SkyboxPointer& getSkybox() const { valid(); return _skybox; } - // Haze - enum HazeMode { - HAZE_OFF, - HAZE_ON, - - NUM_HAZE_MODES - }; - - void setHazeMode(uint32_t mode); - uint32_t getHazeMode() const { return _hazeMode; } - - void setHazeRange(float hazeRange) { _hazeRange = hazeRange; } - float getHazeRange() const { return _hazeRange; } - void setHazeColor(const xColor hazeColor) { _hazeColor = hazeColor; } - xColor getHazeColor() { return _hazeColor; } - void setHazeGlareColor(const xColor hazeGlareColor) { _hazeGlareColor = hazeGlareColor; } - xColor getHazeGlareColor() const { return _hazeGlareColor; } - void setHazeEnableGlare(bool hazeEnableGlare) { _hazeEnableGlare = hazeEnableGlare; } - bool getHazeEnableGlare() const { return _hazeEnableGlare; } - void setHazeGlareAngle(float hazeGlareAngle) { _hazeGlareAngle = hazeGlareAngle; } - float getHazeGlareAngle() const { return _hazeGlareAngle; } - - void setHazeAltitudeEffect(bool hazeAltitudeEffect) { _hazeAltitudeEffect = hazeAltitudeEffect; } - bool getHazeAltitudeEffect() const { return _hazeAltitudeEffect; } - void setHazeCeiling(float hazeCeiling) { _hazeCeiling = hazeCeiling; } - float getHazeCeiling() const { return _hazeCeiling; } - void setHazeBaseRef(float hazeBaseRef) { _hazeBaseRef = hazeBaseRef; } - float getHazeBaseRef() const { return _hazeBaseRef; } - - void setHazeBackgroundBlend(float hazeBackgroundBlend) { _hazeBackgroundBlend = hazeBackgroundBlend; } - float getHazeBackgroundBlend() const { return _hazeBackgroundBlend; } - - void setHazeAttenuateKeyLight(bool hazeAttenuateKeyLight) { _hazeAttenuateKeyLight = hazeAttenuateKeyLight; } - bool getHazeAttenuateKeyLight() const { return _hazeAttenuateKeyLight; } - void setHazeKeyLightRange(float hazeKeyLightRange) { _hazeKeyLightRange = hazeKeyLightRange; } - float getHazeKeyLightRange() const { return _hazeKeyLightRange; } - void setHazeKeyLightAltitude(float hazeKeyLightAltitude) { _hazeKeyLightAltitude = hazeKeyLightAltitude; } - float getHazeKeyLightAltitude() const { return _hazeKeyLightAltitude; } - protected: BackgroundMode _backgroundMode = SKY_DEFAULT; - - uint8_t _hazeMode = (uint8_t)HAZE_OFF; - - float _hazeRange{ model::initialHazeRange_m }; - xColor _hazeColor{ model::initialHazeColorXcolor }; - xColor _hazeGlareColor{ model::initialHazeGlareColorXcolor }; - bool _hazeEnableGlare{ false }; - float _hazeGlareAngle{ model::initialGlareAngle_degs }; - - bool _hazeAltitudeEffect{ false }; - float _hazeCeiling{ model::initialHazeBaseReference_m + model::initialHazeHeight_m }; - float _hazeBaseRef; - - float _hazeBackgroundBlend{ model::initialHazeBackgroundBlend }; - - bool _hazeAttenuateKeyLight{ false }; - float _hazeKeyLightRange{ model::initialHazeKeyLightRange_m }; - float _hazeKeyLightAltitude{ model::initialHazeKeyLightAltitude_m }; LightPointer _sunLight; mutable SkyboxPointer _skybox; diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp index aa22eaa2d1..3883b948df 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.cpp +++ b/libraries/script-engine/src/SceneScriptingInterface.cpp @@ -129,101 +129,6 @@ QString SceneScripting::Stage::getBackgroundMode() const { }; } -void SceneScripting::Stage::setHazeMode(const QString& mode) { - if (mode == QString("haze off")) { - _skyStage->setHazeMode(model::SunSkyStage::HAZE_OFF); - } else if (mode == QString("haze on")) { - _skyStage->setHazeMode(model::SunSkyStage::HAZE_ON); - } -} - -QString SceneScripting::Stage::getHazeMode() const { - switch (_skyStage->getHazeMode()) { - case model::SunSkyStage::HAZE_OFF: - return QString("haze off"); - case model::SunSkyStage::HAZE_ON: - return QString("haze on"); - default: - return QString("inherit"); - }; -} - -void SceneScripting::Stage::setHazeRange(const float hazeRange) { - _skyStage->setHazeRange(hazeRange); -} -float SceneScripting::Stage::getHazeRange() const { - return _skyStage->getHazeRange(); -} -void SceneScripting::Stage::setHazeColor(const xColor hazeColor) { - _skyStage->setHazeColor(hazeColor); -} -xColor SceneScripting::Stage::getHazeColor() const { - return _skyStage->getHazeColor(); -} -void SceneScripting::Stage::setHazeGlareColor(const xColor hazeGlareColor) { - _skyStage->setHazeGlareColor(hazeGlareColor); -} -xColor SceneScripting::Stage::getHazeGlareColor() const { - return _skyStage->getHazeGlareColor(); -} -void SceneScripting::Stage::setHazeEnableGlare(const bool hazeEnableGlare) { - _skyStage->setHazeEnableGlare(hazeEnableGlare); -} -bool SceneScripting::Stage::getHazeEnableGlare() const { - return _skyStage->getHazeEnableGlare(); -} -void SceneScripting::Stage::setHazeGlareAngle(const float hazeGlareAngle) { - _skyStage->setHazeGlareAngle(hazeGlareAngle); -} -float SceneScripting::Stage::getHazeGlareAngle() const { - return _skyStage->getHazeGlareAngle(); -} - -void SceneScripting::Stage::setHazeAltitudeEffect(const bool hazeAltitudeEffect) { - _skyStage->setHazeAltitudeEffect(hazeAltitudeEffect); -} -bool SceneScripting::Stage::getHazeAltitudeEffect() const { - return _skyStage->getHazeAltitudeEffect(); -} -void SceneScripting::Stage::setHazeCeiling(const float hazeCeiling) { - _skyStage->setHazeCeiling(hazeCeiling); -} -float SceneScripting::Stage::getHazeCeiling() const { - return _skyStage->getHazeCeiling(); -} -void SceneScripting::Stage::setHazeBaseRef(const float hazeBaseRef) { - _skyStage->setHazeBaseRef(hazeBaseRef); -} -float SceneScripting::Stage::getHazeBaseRef() const { - return _skyStage->getHazeBaseRef(); -} - -void SceneScripting::Stage::setHazeBackgroundBlend(const float hazeBackgroundBlend) { - _skyStage->setHazeBackgroundBlend(hazeBackgroundBlend); -} -float SceneScripting::Stage::getHazeBackgroundBlend() const { - return _skyStage->getHazeBackgroundBlend(); -} - -void SceneScripting::Stage::setHazeAttenuateKeyLight(const bool hazeAttenuateKeyLight) { - _skyStage->setHazeAttenuateKeyLight(hazeAttenuateKeyLight); -} -bool SceneScripting::Stage::getHazeAttenuateKeyLight() const { - return _skyStage->getHazeAttenuateKeyLight(); -} -void SceneScripting::Stage::setHazeKeyLightRange(const float hazeKeyLightRange) { - _skyStage->setHazeKeyLightRange(hazeKeyLightRange); -} -float SceneScripting::Stage::getHazeKeyLightRange() const { - return _skyStage->getHazeKeyLightRange(); -} -void SceneScripting::Stage::setHazeKeyLightAltitude(const float hazeKeyLightAltitude) { - _skyStage->setHazeKeyLightAltitude(hazeKeyLightAltitude); -} -float SceneScripting::Stage::getHazeKeyLightAltitude() const { - return _skyStage->getHazeKeyLightAltitude(); -} - SceneScriptingInterface::SceneScriptingInterface() : _stage{ new SceneScripting::Stage{ _skyStage } } { // Let's make sure the sunSkyStage is using a proceduralSkybox _skyStage->setSkybox(model::SkyboxPointer(new ProceduralSkybox())); diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 791390236a..7bc22eb3e6 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -121,58 +121,6 @@ namespace SceneScripting { void setBackgroundMode(const QString& mode); QString getBackgroundMode() const; - Q_PROPERTY(QString hazeMode READ getHazeMode WRITE setHazeMode) - void setHazeMode(const QString& mode); - QString getHazeMode() const; - - Q_PROPERTY(float hazeRange READ getHazeRange WRITE setHazeRange) - void setHazeRange(float value); - float getHazeRange() const; - - Q_PROPERTY(xColor hazeColor READ getHazeColor WRITE setHazeColor) - void setHazeColor(xColor value); - xColor getHazeColor() const; - - Q_PROPERTY(xColor hazeGlareColor READ getHazeGlareColor WRITE setHazeGlareColor) - void setHazeGlareColor(xColor value); - xColor getHazeGlareColor() const; - - Q_PROPERTY(bool hazeEnableGlare READ getHazeEnableGlare WRITE setHazeEnableGlare) - void setHazeEnableGlare(bool value); - bool getHazeEnableGlare() const; - - Q_PROPERTY(float hazeGlareAngle READ getHazeGlareAngle WRITE setHazeGlareAngle) - void setHazeGlareAngle(float value); - float getHazeGlareAngle() const; - - Q_PROPERTY(bool hazeAltitudeEffect READ getHazeAltitudeEffect WRITE setHazeAltitudeEffect) - void setHazeAltitudeEffect(bool value); - bool getHazeAltitudeEffect() const; - - Q_PROPERTY(float hazeCeiling READ getHazeCeiling WRITE setHazeCeiling) - void setHazeCeiling(float value); - float getHazeCeiling() const; - - Q_PROPERTY(float hazeBaseRef READ getHazeBaseRef WRITE setHazeBaseRef) - void setHazeBaseRef(float value); - float getHazeBaseRef() const; - - Q_PROPERTY(float hazeBackgroundBlend READ getHazeBackgroundBlend WRITE setHazeBackgroundBlend) - void setHazeBackgroundBlend(float value); - float getHazeBackgroundBlend() const; - - Q_PROPERTY(bool hazeAttenuateKeyLight READ getHazeAttenuateKeyLight WRITE setHazeAttenuateKeyLight) - void setHazeAttenuateKeyLight(bool value); - bool getHazeAttenuateKeyLight() const; - - Q_PROPERTY(float hazeKeyLightRange READ getHazeKeyLightRange WRITE setHazeKeyLightRange) - void setHazeKeyLightRange(float value); - float getHazeKeyLightRange() const; - - Q_PROPERTY(float hazeKeyLightAltitude READ getHazeKeyLightAltitude WRITE setHazeKeyLightAltitude) - void setHazeKeyLightAltitude(float value); - float getHazeKeyLightAltitude() const; - protected: model::SunSkyStagePointer _skyStage; LocationPointer _location; From 5fc68cae0d5d24f0745546a1d55397484e68c89d Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Mon, 30 Oct 2017 11:51:19 -0700 Subject: [PATCH 057/183] Converted Haze initialization values to static. --- libraries/entities/CMakeLists.txt | 2 +- libraries/entities/src/HazePropertyGroup.h | 20 +++---- libraries/entities/src/ZoneEntityItem.h | 2 +- libraries/model/src/model/Haze.cpp | 25 +++++++- libraries/model/src/model/Haze.h | 55 ++++++++++++++++- libraries/model/src/model/HazeInit.h | 69 ---------------------- libraries/render-utils/src/DrawHaze.h | 52 ++++++++-------- libraries/render-utils/src/HazeStage.h | 26 ++++---- 8 files changed, 128 insertions(+), 123 deletions(-) delete mode 100644 libraries/model/src/model/HazeInit.h diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index c23740654e..146aecf1f6 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") -link_hifi_libraries(shared networking octree avatars model) +link_hifi_libraries(shared networking octree avatars model gpu) diff --git a/libraries/entities/src/HazePropertyGroup.h b/libraries/entities/src/HazePropertyGroup.h index 1cbaa24f2a..1585f35c45 100644 --- a/libraries/entities/src/HazePropertyGroup.h +++ b/libraries/entities/src/HazePropertyGroup.h @@ -21,7 +21,7 @@ #include "PropertyGroup.h" #include "EntityItemPropertiesMacros.h" -#include +#include class EntityItemProperties; class EncodeBitstreamParams; @@ -77,24 +77,24 @@ public: bool& somethingChanged) override; // Range only parameters - DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, model::initialHazeRange_m); - DEFINE_PROPERTY_REF(PROP_HAZE_COLOR, HazeColor, hazeColor, xColor, model::initialHazeColorXcolor); - DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_COLOR, HazeGlareColor, hazeGlareColor, xColor, model::initialHazeGlareColorXcolor); + DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, model::Haze::initialHazeRange_m); + DEFINE_PROPERTY_REF(PROP_HAZE_COLOR, HazeColor, hazeColor, xColor, model::Haze::initialHazeColorXcolor); + DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_COLOR, HazeGlareColor, hazeGlareColor, xColor, model::Haze::initialHazeGlareColorXcolor); DEFINE_PROPERTY(PROP_HAZE_ENABLE_GLARE, HazeEnableGlare, hazeEnableGlare, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_ANGLE, HazeGlareAngle, hazeGlareAngle, float, model::initialGlareAngle_degs); + DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_ANGLE, HazeGlareAngle, hazeGlareAngle, float, model::Haze::initialGlareAngle_degs); // Altitude parameters DEFINE_PROPERTY(PROP_HAZE_ALTITUDE_EFFECT, HazeAltitudeEffect, hazeAltitudeEffect, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_CEILING, HazeCeiling, hazeCeiling, float, model::initialHazeBaseReference_m + model::initialHazeHeight_m); - DEFINE_PROPERTY_REF(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, model::initialHazeBaseReference_m); + DEFINE_PROPERTY_REF(PROP_HAZE_CEILING, HazeCeiling, hazeCeiling, float, model::Haze::initialHazeBaseReference_m + model::Haze::initialHazeHeight_m); + DEFINE_PROPERTY_REF(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, model::Haze::initialHazeBaseReference_m); // Background (skybox) blend value - DEFINE_PROPERTY_REF(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend, hazeBackgroundBlend, float, model::initialHazeBackgroundBlend); + DEFINE_PROPERTY_REF(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend, hazeBackgroundBlend, float, model::Haze::initialHazeBackgroundBlend); // hazeDirectional light attenuation DEFINE_PROPERTY(PROP_HAZE_ATTENUATE_KEYLIGHT, HazeAttenuateKeyLight, hazeAttenuateKeyLight, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, model::initialHazeKeyLightRange_m); - DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, model::initialHazeKeyLightAltitude_m); + DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, model::Haze::initialHazeKeyLightRange_m); + DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, model::Haze::initialHazeKeyLightAltitude_m); }; #endif // hifi_HazePropertyGroup_h diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index ba5f3b3dee..3f78591745 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -19,7 +19,7 @@ #include "HazePropertyGroup.h" #include "StagePropertyGroup.h" #include -#include +#include class ZoneEntityItem : public EntityItem { public: diff --git a/libraries/model/src/model/Haze.cpp b/libraries/model/src/model/Haze.cpp index 1c9b989fd1..92042364c2 100644 --- a/libraries/model/src/model/Haze.cpp +++ b/libraries/model/src/model/Haze.cpp @@ -9,12 +9,35 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include -#include #include "Haze.h" using namespace model; +const float Haze::initialHazeRange_m{ 1000.0f }; +const float Haze::initialHazeHeight_m{ 200.0f }; + +const float Haze::initialHazeKeyLightRange_m{ 1000.0f }; +const float Haze::initialHazeKeyLightAltitude_m{ 200.0f }; + +const float Haze::initialHazeBackgroundBlend{ 0.0f }; + +const glm::vec3 Haze::initialColorModulationFactor{ + convertHazeRangeToHazeRangeFactor(initialHazeRange_m), + convertHazeRangeToHazeRangeFactor(initialHazeRange_m), + convertHazeRangeToHazeRangeFactor(initialHazeRange_m) +}; + +const glm::vec3 Haze::initialHazeColor{ 0.5f, 0.6f, 0.7f }; // Bluish +const xColor Haze::initialHazeColorXcolor{ 128, 154, 179 }; + +const float Haze::initialGlareAngle_degs{ 20.0f }; + +const glm::vec3 Haze::initialHazeGlareColor{ 1.0f, 0.9f, 0.7f }; +const xColor Haze::initialHazeGlareColorXcolor{ 255, 229, 179 }; + +const float Haze::initialHazeBaseReference_m{ 0.0f }; + Haze::Haze() { Parameters parameters; _hazeParametersBuffer = gpu::BufferView(std::make_shared(sizeof(Parameters), (const gpu::Byte*) ¶meters)); diff --git a/libraries/model/src/model/Haze.h b/libraries/model/src/model/Haze.h index bed82c80f9..c361fcde8c 100644 --- a/libraries/model/src/model/Haze.h +++ b/libraries/model/src/model/Haze.h @@ -12,17 +12,68 @@ #define hifi_model_Haze_h #include +#include + #include "Transform.h" #include "NumericalConstants.h" -#include "HazeInit.h" - namespace model { + const float LOG_P_005 = logf(0.05f); + const float LOG_P_05 = logf(0.5f); + + // Derivation (d is distance, b is haze coefficient, f is attenuation, solve for f = 0.05 + // f = exp(-d * b) + // ln(f) = -d * b + // b = -ln(f)/d + inline glm::vec3 convertHazeRangeToHazeRangeFactor(const glm::vec3 hazeRange_m) { + return glm::vec3( + -LOG_P_005 / hazeRange_m.x, + -LOG_P_005 / hazeRange_m.y, + -LOG_P_005 / hazeRange_m.z); + } + + // limit range and altitude to no less than 1.0 metres + inline float convertHazeRangeToHazeRangeFactor(const float hazeRange_m) { return -LOG_P_005 / glm::max(hazeRange_m, 1.0f); } + + inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeHeight_m) { return -LOG_P_005 / glm::max(hazeHeight_m, 1.0f); } + + // Derivation (s is the proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5 + // s = dot(lookAngle, sunAngle) = cos(a) + // m = pow(s, p) + // log(m) = p * log(s) + // p = log(m) / log(s) + // limit to 0.1 degrees + inline float convertGlareAngleToPower(const float hazeGlareAngle) { + const float GLARE_ANGLE_LIMIT = 0.1f; + return LOG_P_05 / logf(cosf(RADIANS_PER_DEGREE * glm::max(GLARE_ANGLE_LIMIT, hazeGlareAngle))); + } + // Haze range is defined here as the range the visibility is reduced by 95% // Haze altitude is defined here as the altitude (above 0) that the haze is reduced by 95% class Haze { public: + // Initial values + static const float initialHazeRange_m; + static const float initialHazeHeight_m; + + static const float initialHazeKeyLightRange_m; + static const float initialHazeKeyLightAltitude_m; + + static const float initialHazeBackgroundBlend; + + static const glm::vec3 initialColorModulationFactor; + + static const glm::vec3 initialHazeColor; + static const xColor initialHazeColorXcolor; + + static const float initialGlareAngle_degs; + + static const glm::vec3 initialHazeGlareColor; + static const xColor initialHazeGlareColorXcolor; + + static const float initialHazeBaseReference_m; + using UniformBufferView = gpu::BufferView; Haze(); diff --git a/libraries/model/src/model/HazeInit.h b/libraries/model/src/model/HazeInit.h deleted file mode 100644 index 218a79fc1d..0000000000 --- a/libraries/model/src/model/HazeInit.h +++ /dev/null @@ -1,69 +0,0 @@ -// -// MakeHaze.h -// libraries/model/src/model -// -// Created by Nissim Hadar on 10/26/2017. -// 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 -// -#ifndef hifi_model_HazeInit_h -#define hifi_model_HazeInit_h - -namespace model { - const float LOG_P_005 = logf(0.05f); - const float LOG_P_05 = logf(0.5f); - - // Derivation (d is distance, b is haze coefficient, f is attenuation, solve for f = 0.05 - // f = exp(-d * b) - // ln(f) = -d * b - // b = -ln(f)/d - inline glm::vec3 convertHazeRangeToHazeRangeFactor(const glm::vec3 hazeRange_m) { - return glm::vec3( - -LOG_P_005 / hazeRange_m.x, - -LOG_P_005 / hazeRange_m.y, - -LOG_P_005 / hazeRange_m.z); - } - - // limit range and altitude to no less than 1.0 metres - inline float convertHazeRangeToHazeRangeFactor(const float hazeRange_m) { return -LOG_P_005 / glm::max(hazeRange_m, 1.0f); } - - inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeHeight_m) { return -LOG_P_005 / glm::max(hazeHeight_m, 1.0f); } - - // Derivation (s is the proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5 - // s = dot(lookAngle, sunAngle) = cos(a) - // m = pow(s, p) - // log(m) = p * log(s) - // p = log(m) / log(s) - // limit to 0.1 degrees - inline float convertGlareAngleToPower(const float hazeGlareAngle) { - const float GLARE_ANGLE_LIMIT = 0.1f; - return LOG_P_05 / logf(cosf(RADIANS_PER_DEGREE * glm::max(GLARE_ANGLE_LIMIT, hazeGlareAngle))); - } - - const float initialHazeRange_m{ 1000.0f }; - const float initialHazeHeight_m{ 200.0f }; - - const float initialHazeKeyLightRange_m{ 1000.0f }; - const float initialHazeKeyLightAltitude_m{ 200.0f }; - - const float initialHazeBackgroundBlend{ 0.0f }; - - const glm::vec3 initialColorModulationFactor{ - convertHazeRangeToHazeRangeFactor(initialHazeRange_m), - convertHazeRangeToHazeRangeFactor(initialHazeRange_m), - convertHazeRangeToHazeRangeFactor(initialHazeRange_m) - }; - - const glm::vec3 initialHazeColor{ 0.5f, 0.6f, 0.7f }; // Bluish - const xColor initialHazeColorXcolor{ 128, 154, 179 }; - - const float initialGlareAngle_degs{ 20.0f }; - - const glm::vec3 initialHazeGlareColor{ 1.0f, 0.9f, 0.7f }; - const xColor initialHazeGlareColorXcolor{ 255, 229, 179 }; - - const float initialHazeBaseReference_m{ 0.0f }; -} -#endif // hifi_model_HazeInit_h diff --git a/libraries/render-utils/src/DrawHaze.h b/libraries/render-utils/src/DrawHaze.h index e7a3f2c636..786c39133b 100644 --- a/libraries/render-utils/src/DrawHaze.h +++ b/libraries/render-utils/src/DrawHaze.h @@ -56,15 +56,15 @@ class MakeHazeConfig : public render::Job::Config { public: MakeHazeConfig() : render::Job::Config() {} - float hazeColorR{ model::initialHazeColor.r }; - float hazeColorG{ model::initialHazeColor.g }; - float hazeColorB{ model::initialHazeColor.b }; - float hazeGlareAngle_degs{ model::initialGlareAngle_degs }; + float hazeColorR{ model::Haze::initialHazeColor.r }; + float hazeColorG{ model::Haze::initialHazeColor.g }; + float hazeColorB{ model::Haze::initialHazeColor.b }; + float hazeGlareAngle_degs{ model::Haze::initialGlareAngle_degs }; - float hazeGlareColorR{ model::initialHazeGlareColor.r }; - float hazeGlareColorG{ model::initialHazeGlareColor.g }; - float hazeGlareColorB{ model::initialHazeGlareColor.b }; - float hazeBaseReference_m{ model::initialHazeBaseReference_m }; + float hazeGlareColorR{ model::Haze::initialHazeGlareColor.r }; + float hazeGlareColorG{ model::Haze::initialHazeGlareColor.g }; + float hazeGlareColorB{ model::Haze::initialHazeGlareColor.b }; + float hazeBaseReference_m{ model::Haze::initialHazeBaseReference_m }; bool isHazeActive{ false }; bool isAltitudeBased{ false }; @@ -72,13 +72,13 @@ public: bool isModulateColorActive{ false }; bool isHazeEnableGlare{ false }; - float hazeRange_m{ model::initialHazeRange_m }; - float hazeHeight_m{ model::initialHazeHeight_m }; + float hazeRange_m{ model::Haze::initialHazeRange_m }; + float hazeHeight_m{ model::Haze::initialHazeHeight_m }; - float hazeKeyLightRange_m{ model::initialHazeKeyLightRange_m }; - float hazeKeyLightAltitude_m{ model::initialHazeKeyLightAltitude_m }; + float hazeKeyLightRange_m{ model::Haze::initialHazeKeyLightRange_m }; + float hazeKeyLightAltitude_m{ model::Haze::initialHazeKeyLightAltitude_m }; - float hazeBackgroundBlend{ model::initialHazeBackgroundBlend }; + float hazeBackgroundBlend{ model::Haze::initialHazeBackgroundBlend }; public slots: void setHazeColorR(const float value) { hazeColorR = value; emit dirty(); } @@ -128,15 +128,15 @@ public: HazeConfig() : render::Job::Config(true) {} // attributes - float hazeColorR{ model::initialHazeColor.r }; - float hazeColorG{ model::initialHazeColor.g }; - float hazeColorB{ model::initialHazeColor.b }; - float hazeGlareAngle_degs{ model::initialGlareAngle_degs }; + float hazeColorR{ model::Haze::initialHazeColor.r }; + float hazeColorG{ model::Haze::initialHazeColor.g }; + float hazeColorB{ model::Haze::initialHazeColor.b }; + float hazeGlareAngle_degs{ model::Haze::initialGlareAngle_degs }; - float hazeGlareColorR{ model::initialHazeGlareColor.r }; - float hazeGlareColorG{ model::initialHazeGlareColor.g }; - float hazeGlareColorB{ model::initialHazeGlareColor.b }; - float hazeBaseReference_m{ model::initialHazeBaseReference_m }; + float hazeGlareColorR{ model::Haze::initialHazeGlareColor.r }; + float hazeGlareColorG{ model::Haze::initialHazeGlareColor.g }; + float hazeGlareColorB{ model::Haze::initialHazeGlareColor.b }; + float hazeBaseReference_m{ model::Haze::initialHazeBaseReference_m }; bool isHazeActive{ false }; // Setting this to true will set haze to on bool isAltitudeBased{ false }; @@ -144,13 +144,13 @@ public: bool isModulateColorActive{ false }; bool isHazeEnableGlare{ false }; - float hazeRange_m{ model::initialHazeRange_m }; - float hazeHeight_m{ model::initialHazeHeight_m }; + float hazeRange_m{ model::Haze::initialHazeRange_m }; + float hazeHeight_m{ model::Haze::initialHazeHeight_m }; - float hazeKeyLightRange_m{ model::initialHazeKeyLightRange_m }; - float hazeKeyLightAltitude_m{ model::initialHazeKeyLightAltitude_m }; + float hazeKeyLightRange_m{ model::Haze::initialHazeKeyLightRange_m }; + float hazeKeyLightAltitude_m{ model::Haze::initialHazeKeyLightAltitude_m }; - float hazeBackgroundBlend{ model::initialHazeBackgroundBlend }; + float hazeBackgroundBlend{ model::Haze::initialHazeBackgroundBlend }; // methods void setHazeColorR(const float value); diff --git a/libraries/render-utils/src/HazeStage.h b/libraries/render-utils/src/HazeStage.h index e2d09f3011..e3b061dffd 100644 --- a/libraries/render-utils/src/HazeStage.h +++ b/libraries/render-utils/src/HazeStage.h @@ -110,15 +110,15 @@ class FetchHazeConfig : public render::Job::Config { public: FetchHazeConfig() : render::Job::Config() {} - float hazeColorR{ model::initialHazeColor.r }; - float hazeColorG{ model::initialHazeColor.g }; - float hazeColorB{ model::initialHazeColor.b }; - float hazeGlareAngle_degs{ model::initialGlareAngle_degs }; + float hazeColorR{ model::Haze::initialHazeColor.r }; + float hazeColorG{ model::Haze::initialHazeColor.g }; + float hazeColorB{ model::Haze::initialHazeColor.b }; + float hazeGlareAngle_degs{ model::Haze::initialGlareAngle_degs }; - float hazeGlareColorR{ model::initialHazeGlareColor.r }; - float hazeGlareColorG{ model::initialHazeGlareColor.g }; - float hazeGlareColorB{ model::initialHazeGlareColor.b }; - float hazeBaseReference_m{ model::initialHazeBaseReference_m }; + float hazeGlareColorR{ model::Haze::initialHazeGlareColor.r }; + float hazeGlareColorG{ model::Haze::initialHazeGlareColor.g }; + float hazeGlareColorB{ model::Haze::initialHazeGlareColor.b }; + float hazeBaseReference_m{ model::Haze::initialHazeBaseReference_m }; bool isHazeActive{ false }; bool isAltitudeBased{ false }; @@ -126,13 +126,13 @@ public: bool isModulateColorActive{ false }; bool isHazeEnableGlare{ false }; - float hazeRange_m{ model::initialHazeRange_m }; - float hazeHeight_m{ model::initialHazeHeight_m }; + float hazeRange_m{ model::Haze::initialHazeRange_m }; + float hazeHeight_m{ model::Haze::initialHazeHeight_m }; - float hazeKeyLightRange_m{ model::initialHazeKeyLightRange_m }; - float hazeKeyLightAltitude_m{ model::initialHazeKeyLightAltitude_m }; + float hazeKeyLightRange_m{ model::Haze::initialHazeKeyLightRange_m }; + float hazeKeyLightAltitude_m{ model::Haze::initialHazeKeyLightAltitude_m }; - float hazeBackgroundBlend{ model::initialHazeBackgroundBlend }; + float hazeBackgroundBlend{ model::Haze::initialHazeBackgroundBlend }; public slots: void setHazeColorR(const float value) { hazeColorR = value; emit dirty(); } From 6391282680d0f2732083fa95898f458a491b1242 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Mon, 30 Oct 2017 12:05:23 -0700 Subject: [PATCH 058/183] Swapped location of keylight attenuation and the blending factor. --- scripts/system/html/entityProperties.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index f898eb3b9a..10ccfc52a7 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -602,6 +602,12 @@
+
+
+ + +
+
@@ -614,12 +620,6 @@ min="-1000" max="50000" step="10">
-
-
- - -
-
From 1357877618759784482fa4aa9acd58b8d9dc7dcb Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Mon, 30 Oct 2017 12:41:09 -0700 Subject: [PATCH 059/183] Replaced separate RGB components of colours with vec3's. --- libraries/render-utils/src/DrawHaze.cpp | 28 ++++------------ libraries/render-utils/src/DrawHaze.h | 40 ++++++----------------- libraries/render-utils/src/HazeStage.cpp | 4 +-- libraries/render-utils/src/HazeStage.h | 24 ++++---------- scripts/developer/debugging/debugHaze.qml | 20 ++++++------ 5 files changed, 34 insertions(+), 82 deletions(-) diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index 071db8cf25..5c3d527e91 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -21,32 +21,16 @@ #include "Haze_frag.h" -void HazeConfig::setHazeColorR(const float value) { - hazeColorR = value; -} - -void HazeConfig::setHazeColorG(const float value) { - hazeColorG = value; -} - -void HazeConfig::setHazeColorB(const float value) { - hazeColorB = value; +void HazeConfig::setHazeColor(const glm::vec3 value) { + hazeColor = value; } void HazeConfig::setHazeGlareAngle_degs(const float value) { hazeGlareAngle_degs = value; } -void HazeConfig::setHazeGlareColorR(const float value) { - hazeGlareColorR = value; -} - -void HazeConfig::setHazeGlareColorG(const float value) { - hazeGlareColorG = value; -} - -void HazeConfig::setHazeGlareColorB(const float value) { - hazeGlareColorB = value; +void HazeConfig::setHazeGlareColor(const glm::vec3 value) { + hazeGlareColor = value; } void HazeConfig::setHazeBaseReference(const float value) { @@ -98,10 +82,10 @@ MakeHaze::MakeHaze() { } void MakeHaze::configure(const Config& config) { - _haze->setHazeColor(glm::vec3(config.hazeColorR, config.hazeColorG, config.hazeColorB)); + _haze->setHazeColor(config.hazeColor); _haze->setHazeGlareBlend(model::convertGlareAngleToPower(config.hazeGlareAngle_degs)); - _haze->setHazeGlareColor(glm::vec3(config.hazeGlareColorR, config.hazeGlareColorG, config.hazeGlareColorB)); + _haze->setHazeGlareColor(config.hazeGlareColor); _haze->setHazeBaseReference(config.hazeBaseReference_m); _haze->setHazeActive(config.isHazeActive); diff --git a/libraries/render-utils/src/DrawHaze.h b/libraries/render-utils/src/DrawHaze.h index 786c39133b..3005203c5b 100644 --- a/libraries/render-utils/src/DrawHaze.h +++ b/libraries/render-utils/src/DrawHaze.h @@ -29,14 +29,10 @@ using LinearDepthFramebufferPointer = std::shared_ptr; class MakeHazeConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(float hazeColorR MEMBER hazeColorR WRITE setHazeColorR NOTIFY dirty); - Q_PROPERTY(float hazeColorG MEMBER hazeColorG WRITE setHazeColorG NOTIFY dirty); - Q_PROPERTY(float hazeColorB MEMBER hazeColorB WRITE setHazeColorB NOTIFY dirty); + Q_PROPERTY(glm::vec3 hazeColor MEMBER hazeColor WRITE setHazeColor NOTIFY dirty); Q_PROPERTY(float hazeGlareAngle_degs MEMBER hazeGlareAngle_degs WRITE setHazeGlareAngle_degs NOTIFY dirty); - Q_PROPERTY(float hazeGlareColorR MEMBER hazeGlareColorR WRITE setHazeGlareColorR NOTIFY dirty); - Q_PROPERTY(float hazeGlareColorG MEMBER hazeGlareColorG WRITE setHazeGlareColorG NOTIFY dirty); - Q_PROPERTY(float hazeGlareColorB MEMBER hazeGlareColorB WRITE setHazeGlareColorB NOTIFY dirty); + Q_PROPERTY(glm::vec3 hazeGlareColor MEMBER hazeGlareColor WRITE setHazeGlareColor NOTIFY dirty); Q_PROPERTY(float hazeBaseReference_m MEMBER hazeBaseReference_m WRITE setHazeBaseReference NOTIFY dirty); Q_PROPERTY(bool isHazeActive MEMBER isHazeActive WRITE setHazeActive NOTIFY dirty); @@ -56,14 +52,10 @@ class MakeHazeConfig : public render::Job::Config { public: MakeHazeConfig() : render::Job::Config() {} - float hazeColorR{ model::Haze::initialHazeColor.r }; - float hazeColorG{ model::Haze::initialHazeColor.g }; - float hazeColorB{ model::Haze::initialHazeColor.b }; + glm::vec3 hazeColor{ model::Haze::initialHazeColor }; float hazeGlareAngle_degs{ model::Haze::initialGlareAngle_degs }; - float hazeGlareColorR{ model::Haze::initialHazeGlareColor.r }; - float hazeGlareColorG{ model::Haze::initialHazeGlareColor.g }; - float hazeGlareColorB{ model::Haze::initialHazeGlareColor.b }; + glm::vec3 hazeGlareColor{ model::Haze::initialHazeGlareColor }; float hazeBaseReference_m{ model::Haze::initialHazeBaseReference_m }; bool isHazeActive{ false }; @@ -81,14 +73,10 @@ public: float hazeBackgroundBlend{ model::Haze::initialHazeBackgroundBlend }; public slots: - void setHazeColorR(const float value) { hazeColorR = value; emit dirty(); } - void setHazeColorG(const float value) { hazeColorG = value; emit dirty(); } - void setHazeColorB(const float value) { hazeColorB = value; emit dirty(); } + void setHazeColor(const glm::vec3 value) { hazeColor = value; emit dirty(); } void setHazeGlareAngle_degs(const float value) { hazeGlareAngle_degs = value; emit dirty(); } - void setHazeGlareColorR(const float value) { hazeGlareColorR = value; emit dirty(); } - void setHazeGlareColorG(const float value) { hazeGlareColorG = value; emit dirty(); } - void setHazeGlareColorB(const float value) { hazeGlareColorB = value; emit dirty(); } + void setHazeGlareColor(const glm::vec3 value) { hazeGlareColor = value; emit dirty(); } void setHazeBaseReference(const float value) { hazeBaseReference_m = value; ; emit dirty(); } void setHazeActive(const bool active) { isHazeActive = active; emit dirty(); } @@ -128,14 +116,10 @@ public: HazeConfig() : render::Job::Config(true) {} // attributes - float hazeColorR{ model::Haze::initialHazeColor.r }; - float hazeColorG{ model::Haze::initialHazeColor.g }; - float hazeColorB{ model::Haze::initialHazeColor.b }; + glm::vec3 hazeColor{ model::Haze::initialHazeColor }; float hazeGlareAngle_degs{ model::Haze::initialGlareAngle_degs }; - float hazeGlareColorR{ model::Haze::initialHazeGlareColor.r }; - float hazeGlareColorG{ model::Haze::initialHazeGlareColor.g }; - float hazeGlareColorB{ model::Haze::initialHazeGlareColor.b }; + glm::vec3 hazeGlareColor{ model::Haze::initialHazeGlareColor }; float hazeBaseReference_m{ model::Haze::initialHazeBaseReference_m }; bool isHazeActive{ false }; // Setting this to true will set haze to on @@ -153,14 +137,10 @@ public: float hazeBackgroundBlend{ model::Haze::initialHazeBackgroundBlend }; // methods - void setHazeColorR(const float value); - void setHazeColorG(const float value); - void setHazeColorB(const float value); + void setHazeColor(const glm::vec3 value); void setHazeGlareAngle_degs(const float value); - void setHazeGlareColorR(const float value); - void setHazeGlareColorG(const float value); - void setHazeGlareColorB(const float value); + void setHazeGlareColor(const glm::vec3 value); void setHazeBaseReference(const float value); void setHazeActive(const bool active); diff --git a/libraries/render-utils/src/HazeStage.cpp b/libraries/render-utils/src/HazeStage.cpp index 6a6104a1df..71baecb0e4 100644 --- a/libraries/render-utils/src/HazeStage.cpp +++ b/libraries/render-utils/src/HazeStage.cpp @@ -20,10 +20,10 @@ FetchHazeStage::FetchHazeStage() { } void FetchHazeStage::configure(const Config& config) { - _haze->setHazeColor(glm::vec3(config.hazeColorR, config.hazeColorG, config.hazeColorB)); + _haze->setHazeColor(config.hazeColor); _haze->setHazeGlareBlend(model::convertGlareAngleToPower(config.hazeGlareAngle_degs)); - _haze->setHazeGlareColor(glm::vec3(config.hazeGlareColorR, config.hazeGlareColorG, config.hazeGlareColorB)); + _haze->setHazeGlareColor(config.hazeGlareColor); _haze->setHazeBaseReference(config.hazeBaseReference_m); _haze->setHazeActive(config.isHazeActive); diff --git a/libraries/render-utils/src/HazeStage.h b/libraries/render-utils/src/HazeStage.h index e3b061dffd..1f1a94a806 100644 --- a/libraries/render-utils/src/HazeStage.h +++ b/libraries/render-utils/src/HazeStage.h @@ -83,14 +83,10 @@ protected: class FetchHazeConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(float hazeColorR MEMBER hazeColorR WRITE setHazeColorR NOTIFY dirty); - Q_PROPERTY(float hazeColorG MEMBER hazeColorG WRITE setHazeColorG NOTIFY dirty); - Q_PROPERTY(float hazeColorB MEMBER hazeColorB WRITE setHazeColorB NOTIFY dirty); + Q_PROPERTY(glm::vec3 hazeColor MEMBER hazeColor WRITE setHazeColor NOTIFY dirty); Q_PROPERTY(float hazeGlareAngle_degs MEMBER hazeGlareAngle_degs WRITE setHazeGlareAngle_degs NOTIFY dirty); - Q_PROPERTY(float hazeGlareColorR MEMBER hazeGlareColorR WRITE setHazeGlareColorR NOTIFY dirty); - Q_PROPERTY(float hazeGlareColorG MEMBER hazeGlareColorG WRITE setHazeGlareColorG NOTIFY dirty); - Q_PROPERTY(float hazeGlareColorB MEMBER hazeGlareColorB WRITE setHazeGlareColorB NOTIFY dirty); + Q_PROPERTY(glm::vec3 hazeGlareColor MEMBER hazeGlareColor WRITE setHazeGlareColor NOTIFY dirty); Q_PROPERTY(float hazeBaseReference_m MEMBER hazeBaseReference_m WRITE setHazeBaseReference NOTIFY dirty); Q_PROPERTY(bool isHazeActive MEMBER isHazeActive WRITE setHazeActive NOTIFY dirty); @@ -110,14 +106,10 @@ class FetchHazeConfig : public render::Job::Config { public: FetchHazeConfig() : render::Job::Config() {} - float hazeColorR{ model::Haze::initialHazeColor.r }; - float hazeColorG{ model::Haze::initialHazeColor.g }; - float hazeColorB{ model::Haze::initialHazeColor.b }; + glm::vec3 hazeColor{ model::Haze::initialHazeColor }; float hazeGlareAngle_degs{ model::Haze::initialGlareAngle_degs }; - float hazeGlareColorR{ model::Haze::initialHazeGlareColor.r }; - float hazeGlareColorG{ model::Haze::initialHazeGlareColor.g }; - float hazeGlareColorB{ model::Haze::initialHazeGlareColor.b }; + glm::vec3 hazeGlareColor{ model::Haze::initialHazeGlareColor }; float hazeBaseReference_m{ model::Haze::initialHazeBaseReference_m }; bool isHazeActive{ false }; @@ -135,14 +127,10 @@ public: float hazeBackgroundBlend{ model::Haze::initialHazeBackgroundBlend }; public slots: - void setHazeColorR(const float value) { hazeColorR = value; emit dirty(); } - void setHazeColorG(const float value) { hazeColorG = value; emit dirty(); } - void setHazeColorB(const float value) { hazeColorB = value; emit dirty(); } + void setHazeColor(const glm::vec3 value) { hazeColor = value; emit dirty(); } void setHazeGlareAngle_degs(const float value) { hazeGlareAngle_degs = value; emit dirty(); } - void setHazeGlareColorR(const float value) { hazeGlareColorR = value; emit dirty(); } - void setHazeGlareColorG(const float value) { hazeGlareColorG = value; emit dirty(); } - void setHazeGlareColorB(const float value) { hazeGlareColorB = value; emit dirty(); } + void setHazeGlareColor(const glm::vec3 value) { hazeGlareColor = value; emit dirty(); } void setHazeBaseReference(const float value) { hazeBaseReference_m = value; ; emit dirty(); } void setHazeActive(const bool active) { isHazeActive = active; emit dirty(); } diff --git a/scripts/developer/debugging/debugHaze.qml b/scripts/developer/debugging/debugHaze.qml index e197050efd..5a18f88c79 100644 --- a/scripts/developer/debugging/debugHaze.qml +++ b/scripts/developer/debugging/debugHaze.qml @@ -68,7 +68,7 @@ Item { label: "Haze Color R" integral: false config: root.hazeModel - property: "hazeColorR" + property: "hazeColor.r" max: 1.0 min: 0.0 width: 280 @@ -78,7 +78,7 @@ Item { label: "Haze Color G" integral: false config: root.hazeModel - property: "hazeColorG" + property: "hazeColor.g" max: 1.0 min: 0.0 width: 280 @@ -88,7 +88,7 @@ Item { label: "Haze Color B" integral: false config: root.hazeModel - property: "hazeColorB" + property: "hazeColor.b" max: 1.0 min: 0.0 width: 280 @@ -98,7 +98,7 @@ Item { label: "Sun R" integral: false config: root.hazeModel - property: "hazeDirectionalLightColorR" + property: "hazeGlareColor.r" max: 1.0 min: 0.0 width: 280 @@ -108,7 +108,7 @@ Item { label: "Sun G" integral: false config: root.hazeModel - property: "hazeDirectionalLightColorG" + property: "hazeGlareColor.g" max: 1.0 min: 0.0 width: 280 @@ -118,7 +118,7 @@ Item { label: "Sun B" integral: false config: root.hazeModel - property: "hazeDirectionalLightColorB" + property: "hazeGlareColor.b" max: 1.0 min: 0.0 width: 280 @@ -128,7 +128,7 @@ Item { label: "Sun glare angle" integral: false config: root.hazeModel - property: "hazeDirectionalLightAngle_degs" + property: "hazeGlareAngle_degs" max: 70.0 min: 0.0 width: 280 @@ -148,7 +148,7 @@ Item { label: "BG Blend" integral: false config: root.hazeModel - property: "hazeBackgroundBlendValue" + property: "hazeBackgroundBlend" max: 1.0 min: 0.0 width: 280 @@ -156,9 +156,9 @@ Item { CheckBox { text: "Keylight Attenuation" - checked: root.hazeModel["isDirectionaLightAttenuationActive"] + checked: root.hazeModel["isKeyLightAttenuationActive"] onCheckedChanged: { - root.hazeModel["isDirectionaLightAttenuationActive"] = checked; + root.hazeModel["isKeyLightAttenuationActive"] = checked; } } From 19420a0ff26b691ee7e0eeb2e1a734302c244be8 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 30 Oct 2017 17:01:55 -0700 Subject: [PATCH 060/183] Move static cert verify to properties --- .../src/entities/EntityServer.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 114 ----------------- libraries/entities/src/EntityItem.h | 3 - .../entities/src/EntityItemProperties.cpp | 116 ++++++++++++++++++ libraries/entities/src/EntityItemProperties.h | 4 + .../entities/src/EntityScriptingInterface.cpp | 2 +- libraries/entities/src/EntityTree.cpp | 2 +- 7 files changed, 123 insertions(+), 120 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index fa9c73b12d..702ca88787 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -459,7 +459,7 @@ void EntityServer::startDynamicDomainVerification() { EntityItemPointer entity = tree->findEntityByEntityItemID(i.value()); if (entity) { - if (!entity->verifyStaticCertificateProperties()) { + if (!entity->getProperties().verifyStaticCertificateProperties()) { qCDebug(entities) << "During Dynamic Domain Verification, a certified entity with ID" << i.value() << "failed" << "static certificate verification."; // Delete the entity if it doesn't pass static certificate verification diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 4f5db991c8..c355ce90fc 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -14,10 +14,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include @@ -1575,116 +1571,6 @@ float EntityItem::getRadius() const { return 0.5f * glm::length(getDimensions()); } -// Checking Certifiable Properties -#define ADD_STRING_PROPERTY(n, N) if (!propertySet.get##N().isEmpty()) json[#n] = propertySet.get##N() -#define ADD_ENUM_PROPERTY(n, N) json[#n] = propertySet.get##N##AsString() -#define ADD_INT_PROPERTY(n, N) if (propertySet.get##N() != 0) json[#n] = (propertySet.get##N() == (quint32) -1) ? -1.0 : ((double) propertySet.get##N()) -QByteArray EntityItem::getStaticCertificateJSON() const { - // Produce a compact json of every non-default static certificate property, with the property names in alphabetical order. - // The static certificate properties include all an only those properties that cannot be changed without altering the identity - // of the entity as reviewed during the certification submission. - - QJsonObject json; - EntityItemProperties propertySet = getProperties(); // Note: neither EntityItem nor EntityitemProperties "properties" are QObject "properties"! - // It is important that this be reproducible in the same order each time. Since we also generate these on the server, we do it alphabetically - // to help maintainence in two different code bases. - if (!propertySet.getAnimation().getURL().isEmpty()) { - json["animationURL"] = propertySet.getAnimation().getURL(); - } - ADD_STRING_PROPERTY(collisionSoundURL, CollisionSoundURL); - ADD_STRING_PROPERTY(compoundShapeURL, CompoundShapeURL); - ADD_INT_PROPERTY(editionNumber, EditionNumber); - ADD_INT_PROPERTY(instanceNumber, EntityInstanceNumber); - ADD_STRING_PROPERTY(itemArtist, ItemArtist); - ADD_STRING_PROPERTY(itemCategories, ItemCategories); - ADD_STRING_PROPERTY(itemDescription, ItemDescription); - ADD_STRING_PROPERTY(itemLicenseUrl, ItemLicense); - ADD_STRING_PROPERTY(itemName, ItemName); - ADD_INT_PROPERTY(limitedRun, LimitedRun); - ADD_STRING_PROPERTY(marketplaceID, MarketplaceID); - ADD_STRING_PROPERTY(modelURL, ModelURL); - ADD_STRING_PROPERTY(script, Script); - ADD_ENUM_PROPERTY(shapeType, ShapeType); - json["type"] = EntityTypes::getEntityTypeName(propertySet.getType()); - - return QJsonDocument(json).toJson(QJsonDocument::Compact); -} -QByteArray EntityItem::getStaticCertificateHash() const { - return QCryptographicHash::hash(getStaticCertificateJSON(), QCryptographicHash::Sha256); -} - -bool EntityItem::verifyStaticCertificateProperties() { - // True IIF a non-empty certificateID matches the static certificate json. - // I.e., if we can verify that the certificateID was produced by High Fidelity signing the static certificate hash. - - if (getCertificateID().isEmpty()) { - return false; - } - - const QByteArray marketplacePublicKeyByteArray = EntityItem::_marketplacePublicKey.toUtf8(); - const unsigned char* marketplacePublicKey = reinterpret_cast(marketplacePublicKeyByteArray.constData()); - int marketplacePublicKeyLength = marketplacePublicKeyByteArray.length(); - - BIO *bio = BIO_new_mem_buf((void*)marketplacePublicKey, marketplacePublicKeyLength); - EVP_PKEY* evp_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); - if (evp_key) { - RSA* rsa = EVP_PKEY_get1_RSA(evp_key); - if (rsa) { - const QByteArray digestByteArray = getStaticCertificateHash(); - const unsigned char* digest = reinterpret_cast(digestByteArray.constData()); - int digestLength = digestByteArray.length(); - - const QByteArray signatureByteArray = QByteArray::fromBase64(getCertificateID().toUtf8()); - const unsigned char* signature = reinterpret_cast(signatureByteArray.constData()); - int signatureLength = signatureByteArray.length(); - - ERR_clear_error(); - bool answer = RSA_verify(NID_sha256, - digest, - digestLength, - signature, - signatureLength, - rsa); - long error = ERR_get_error(); - if (error != 0) { - const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "ERROR while verifying static certificate properties! RSA error:" << error_str - << "\nStatic Cert JSON:" << getStaticCertificateJSON() - << "\nKey:" << EntityItem::_marketplacePublicKey << "\nKey Length:" << marketplacePublicKeyLength - << "\nDigest:" << digest << "\nDigest Length:" << digestLength - << "\nSignature:" << signature << "\nSignature Length:" << signatureLength; - } - RSA_free(rsa); - if (bio) { - BIO_free(bio); - } - if (evp_key) { - EVP_PKEY_free(evp_key); - } - return answer; - } else { - if (bio) { - BIO_free(bio); - } - if (evp_key) { - EVP_PKEY_free(evp_key); - } - long error = ERR_get_error(); - const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "Failed to verify static certificate properties! RSA error:" << error_str; - return false; - } - } else { - if (bio) { - BIO_free(bio); - } - long error = ERR_get_error(); - const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "Failed to verify static certificate properties! RSA error:" << error_str; - return false; - } -} - void EntityItem::adjustShapeInfoByRegistration(ShapeInfo& info) const { if (_registrationPoint != ENTITY_ITEM_DEFAULT_REGISTRATION_POINT) { glm::mat4 scale = glm::scale(getDimensions()); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 79862b9bd2..76a5205960 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -328,9 +328,6 @@ public: void setEntityInstanceNumber(const quint32&); QString getCertificateID() const; void setCertificateID(const QString& value); - QByteArray getStaticCertificateJSON() const; - QByteArray getStaticCertificateHash() const; - bool verifyStaticCertificateProperties(); // TODO: get rid of users of getRadius()... float getRadius() const; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 3bbd6ce8e6..f774b208c4 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -14,6 +14,15 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include #include @@ -2471,3 +2480,110 @@ bool EntityItemProperties::parentRelatedPropertyChanged() const { bool EntityItemProperties::queryAACubeRelatedPropertyChanged() const { return parentRelatedPropertyChanged() || dimensionsChanged(); } + +// Checking Certifiable Properties +#define ADD_STRING_PROPERTY(n, N) if (!get##N().isEmpty()) json[#n] = get##N() +#define ADD_ENUM_PROPERTY(n, N) json[#n] = get##N##AsString() +#define ADD_INT_PROPERTY(n, N) if (get##N() != 0) json[#n] = (get##N() == (quint32) -1) ? -1.0 : ((double) get##N()) +QByteArray EntityItemProperties::getStaticCertificateJSON() const { + // Produce a compact json of every non-default static certificate property, with the property names in alphabetical order. + // The static certificate properties include all an only those properties that cannot be changed without altering the identity + // of the entity as reviewed during the certification submission. + + QJsonObject json; + if (!getAnimation().getURL().isEmpty()) { + json["animationURL"] = getAnimation().getURL(); + } + ADD_STRING_PROPERTY(collisionSoundURL, CollisionSoundURL); + ADD_STRING_PROPERTY(compoundShapeURL, CompoundShapeURL); + ADD_INT_PROPERTY(editionNumber, EditionNumber); + ADD_INT_PROPERTY(instanceNumber, EntityInstanceNumber); + ADD_STRING_PROPERTY(itemArtist, ItemArtist); + ADD_STRING_PROPERTY(itemCategories, ItemCategories); + ADD_STRING_PROPERTY(itemDescription, ItemDescription); + ADD_STRING_PROPERTY(itemLicenseUrl, ItemLicense); + ADD_STRING_PROPERTY(itemName, ItemName); + ADD_INT_PROPERTY(limitedRun, LimitedRun); + ADD_STRING_PROPERTY(marketplaceID, MarketplaceID); + ADD_STRING_PROPERTY(modelURL, ModelURL); + ADD_STRING_PROPERTY(script, Script); + ADD_ENUM_PROPERTY(shapeType, ShapeType); + json["type"] = EntityTypes::getEntityTypeName(getType()); + + return QJsonDocument(json).toJson(QJsonDocument::Compact); +} +QByteArray EntityItemProperties::getStaticCertificateHash() const { + return QCryptographicHash::hash(getStaticCertificateJSON(), QCryptographicHash::Sha256); +} + +bool EntityItemProperties::verifyStaticCertificateProperties() { + // True IIF a non-empty certificateID matches the static certificate json. + // I.e., if we can verify that the certificateID was produced by High Fidelity signing the static certificate hash. + + if (getCertificateID().isEmpty()) { + return false; + } + + const QByteArray marketplacePublicKeyByteArray = EntityItem::_marketplacePublicKey.toUtf8(); + const unsigned char* marketplacePublicKey = reinterpret_cast(marketplacePublicKeyByteArray.constData()); + int marketplacePublicKeyLength = marketplacePublicKeyByteArray.length(); + + BIO *bio = BIO_new_mem_buf((void*)marketplacePublicKey, marketplacePublicKeyLength); + EVP_PKEY* evp_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); + if (evp_key) { + RSA* rsa = EVP_PKEY_get1_RSA(evp_key); + if (rsa) { + const QByteArray digestByteArray = getStaticCertificateHash(); + const unsigned char* digest = reinterpret_cast(digestByteArray.constData()); + int digestLength = digestByteArray.length(); + + const QByteArray signatureByteArray = QByteArray::fromBase64(getCertificateID().toUtf8()); + const unsigned char* signature = reinterpret_cast(signatureByteArray.constData()); + int signatureLength = signatureByteArray.length(); + + ERR_clear_error(); + bool answer = RSA_verify(NID_sha256, + digest, + digestLength, + signature, + signatureLength, + rsa); + long error = ERR_get_error(); + if (error != 0) { + const char* error_str = ERR_error_string(error, NULL); + qCWarning(entities) << "ERROR while verifying static certificate properties! RSA error:" << error_str + << "\nStatic Cert JSON:" << getStaticCertificateJSON() + << "\nKey:" << EntityItem::_marketplacePublicKey << "\nKey Length:" << marketplacePublicKeyLength + << "\nDigest:" << digest << "\nDigest Length:" << digestLength + << "\nSignature:" << signature << "\nSignature Length:" << signatureLength; + } + RSA_free(rsa); + if (bio) { + BIO_free(bio); + } + if (evp_key) { + EVP_PKEY_free(evp_key); + } + return answer; + } else { + if (bio) { + BIO_free(bio); + } + if (evp_key) { + EVP_PKEY_free(evp_key); + } + long error = ERR_get_error(); + const char* error_str = ERR_error_string(error, NULL); + qCWarning(entities) << "Failed to verify static certificate properties! RSA error:" << error_str; + return false; + } + } else { + if (bio) { + BIO_free(bio); + } + long error = ERR_get_error(); + const char* error_str = ERR_error_string(error, NULL); + qCWarning(entities) << "Failed to verify static certificate properties! RSA error:" << error_str; + return false; + } +} diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 6547026e5c..a8bb063934 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -336,6 +336,10 @@ public: QByteArray getPackedStrokeColors() const; QByteArray packStrokeColors(const QVector& strokeColors) const; + QByteArray getStaticCertificateJSON() const; + QByteArray getStaticCertificateHash() const; + bool verifyStaticCertificateProperties(); + protected: QString getCollisionMaskAsString() const; void setCollisionMaskFromString(const QString& maskString); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index c83a5f60a1..998a2d4dfe 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1827,7 +1827,7 @@ bool EntityScriptingInterface::verifyStaticCertificateProperties(const QUuid& en _entityTree->withReadLock([&] { EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(entityID)); if (entity) { - result = entity->verifyStaticCertificateProperties(); + result = entity->getProperties().verifyStaticCertificateProperties(); } }); } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 9397f38cdd..22348360ed 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1528,7 +1528,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c _totalCreates++; if (newEntity && isCertified && getIsServer()) { - if (!newEntity->verifyStaticCertificateProperties()) { + if (!properties.verifyStaticCertificateProperties()) { qCDebug(entities) << "User" << senderNode->getUUID() << "attempted to add a certified entity with ID" << entityItemID << "which failed" << "static certificate verification."; From b00db6a68f9557682c57a88fd8975582c7d43c3a Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Mon, 30 Oct 2017 19:20:49 -0700 Subject: [PATCH 061/183] Correction. --- libraries/render-utils/src/DeferredLightingEffect.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 428dbc623e..2187cb70b1 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -498,7 +498,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, auto lightStage = renderContext->_scene->getStage(); assert(lightStage); assert(lightStage->getNumLights() > 0); - auto lightAndShadow = lightStage->getLightAndShadow(0); + auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow(); const auto& globalShadow = lightAndShadow.second; // Bind the shadow buffer @@ -509,7 +509,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, auto& program = deferredLightingEffect->_directionalSkyboxLight; LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations; - auto keyLight = lightStage->getLight(0); + auto keyLight = lightAndShadow.first; model::LightPointer keyAmbientLight; if (lightStage && lightStage->_currentFrame._ambientLights.size()) { From 636f7858a3492b1f7b8ee6588e0ad847483bbc2f Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Mon, 30 Oct 2017 19:45:08 -0700 Subject: [PATCH 062/183] Removed _degs and _m suffixes. --- libraries/entities/src/HazePropertyGroup.h | 12 ++--- libraries/model/src/model/Haze.cpp | 18 +++---- libraries/model/src/model/Haze.h | 36 +++++++------- libraries/render-utils/src/DrawHaze.cpp | 34 ++++++------- libraries/render-utils/src/DrawHaze.h | 58 +++++++++++----------- libraries/render-utils/src/HazeStage.cpp | 12 ++--- libraries/render-utils/src/HazeStage.h | 36 +++++++------- 7 files changed, 103 insertions(+), 103 deletions(-) diff --git a/libraries/entities/src/HazePropertyGroup.h b/libraries/entities/src/HazePropertyGroup.h index 1585f35c45..17db8a6369 100644 --- a/libraries/entities/src/HazePropertyGroup.h +++ b/libraries/entities/src/HazePropertyGroup.h @@ -77,24 +77,24 @@ public: bool& somethingChanged) override; // Range only parameters - DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, model::Haze::initialHazeRange_m); + DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, model::Haze::initialHazeRange); DEFINE_PROPERTY_REF(PROP_HAZE_COLOR, HazeColor, hazeColor, xColor, model::Haze::initialHazeColorXcolor); DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_COLOR, HazeGlareColor, hazeGlareColor, xColor, model::Haze::initialHazeGlareColorXcolor); DEFINE_PROPERTY(PROP_HAZE_ENABLE_GLARE, HazeEnableGlare, hazeEnableGlare, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_ANGLE, HazeGlareAngle, hazeGlareAngle, float, model::Haze::initialGlareAngle_degs); + DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_ANGLE, HazeGlareAngle, hazeGlareAngle, float, model::Haze::initialGlareAngle); // Altitude parameters DEFINE_PROPERTY(PROP_HAZE_ALTITUDE_EFFECT, HazeAltitudeEffect, hazeAltitudeEffect, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_CEILING, HazeCeiling, hazeCeiling, float, model::Haze::initialHazeBaseReference_m + model::Haze::initialHazeHeight_m); - DEFINE_PROPERTY_REF(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, model::Haze::initialHazeBaseReference_m); + DEFINE_PROPERTY_REF(PROP_HAZE_CEILING, HazeCeiling, hazeCeiling, float, model::Haze::initialHazeBaseReference + model::Haze::initialHazeHeight); + DEFINE_PROPERTY_REF(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, model::Haze::initialHazeBaseReference); // Background (skybox) blend value DEFINE_PROPERTY_REF(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend, hazeBackgroundBlend, float, model::Haze::initialHazeBackgroundBlend); // hazeDirectional light attenuation DEFINE_PROPERTY(PROP_HAZE_ATTENUATE_KEYLIGHT, HazeAttenuateKeyLight, hazeAttenuateKeyLight, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, model::Haze::initialHazeKeyLightRange_m); - DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, model::Haze::initialHazeKeyLightAltitude_m); + DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, model::Haze::initialHazeKeyLightRange); + DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, model::Haze::initialHazeKeyLightAltitude); }; #endif // hifi_HazePropertyGroup_h diff --git a/libraries/model/src/model/Haze.cpp b/libraries/model/src/model/Haze.cpp index 92042364c2..f29824936f 100644 --- a/libraries/model/src/model/Haze.cpp +++ b/libraries/model/src/model/Haze.cpp @@ -14,29 +14,29 @@ using namespace model; -const float Haze::initialHazeRange_m{ 1000.0f }; -const float Haze::initialHazeHeight_m{ 200.0f }; +const float Haze::initialHazeRange{ 1000.0f }; +const float Haze::initialHazeHeight{ 200.0f }; -const float Haze::initialHazeKeyLightRange_m{ 1000.0f }; -const float Haze::initialHazeKeyLightAltitude_m{ 200.0f }; +const float Haze::initialHazeKeyLightRange{ 1000.0f }; +const float Haze::initialHazeKeyLightAltitude{ 200.0f }; const float Haze::initialHazeBackgroundBlend{ 0.0f }; const glm::vec3 Haze::initialColorModulationFactor{ - convertHazeRangeToHazeRangeFactor(initialHazeRange_m), - convertHazeRangeToHazeRangeFactor(initialHazeRange_m), - convertHazeRangeToHazeRangeFactor(initialHazeRange_m) + convertHazeRangeToHazeRangeFactor(initialHazeRange), + convertHazeRangeToHazeRangeFactor(initialHazeRange), + convertHazeRangeToHazeRangeFactor(initialHazeRange) }; const glm::vec3 Haze::initialHazeColor{ 0.5f, 0.6f, 0.7f }; // Bluish const xColor Haze::initialHazeColorXcolor{ 128, 154, 179 }; -const float Haze::initialGlareAngle_degs{ 20.0f }; +const float Haze::initialGlareAngle{ 20.0f }; const glm::vec3 Haze::initialHazeGlareColor{ 1.0f, 0.9f, 0.7f }; const xColor Haze::initialHazeGlareColorXcolor{ 255, 229, 179 }; -const float Haze::initialHazeBaseReference_m{ 0.0f }; +const float Haze::initialHazeBaseReference{ 0.0f }; Haze::Haze() { Parameters parameters; diff --git a/libraries/model/src/model/Haze.h b/libraries/model/src/model/Haze.h index c361fcde8c..00e8f3625c 100644 --- a/libraries/model/src/model/Haze.h +++ b/libraries/model/src/model/Haze.h @@ -25,17 +25,17 @@ namespace model { // f = exp(-d * b) // ln(f) = -d * b // b = -ln(f)/d - inline glm::vec3 convertHazeRangeToHazeRangeFactor(const glm::vec3 hazeRange_m) { + inline glm::vec3 convertHazeRangeToHazeRangeFactor(const glm::vec3 hazeRange) { return glm::vec3( - -LOG_P_005 / hazeRange_m.x, - -LOG_P_005 / hazeRange_m.y, - -LOG_P_005 / hazeRange_m.z); + -LOG_P_005 / hazeRange.x, + -LOG_P_005 / hazeRange.y, + -LOG_P_005 / hazeRange.z); } // limit range and altitude to no less than 1.0 metres - inline float convertHazeRangeToHazeRangeFactor(const float hazeRange_m) { return -LOG_P_005 / glm::max(hazeRange_m, 1.0f); } + inline float convertHazeRangeToHazeRangeFactor(const float hazeRange) { return -LOG_P_005 / glm::max(hazeRange, 1.0f); } - inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeHeight_m) { return -LOG_P_005 / glm::max(hazeHeight_m, 1.0f); } + inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeHeight) { return -LOG_P_005 / glm::max(hazeHeight, 1.0f); } // Derivation (s is the proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5 // s = dot(lookAngle, sunAngle) = cos(a) @@ -54,11 +54,11 @@ namespace model { class Haze { public: // Initial values - static const float initialHazeRange_m; - static const float initialHazeHeight_m; + static const float initialHazeRange; + static const float initialHazeHeight; - static const float initialHazeKeyLightRange_m; - static const float initialHazeKeyLightAltitude_m; + static const float initialHazeKeyLightRange; + static const float initialHazeKeyLightAltitude; static const float initialHazeBackgroundBlend; @@ -67,12 +67,12 @@ namespace model { static const glm::vec3 initialHazeColor; static const xColor initialHazeColorXcolor; - static const float initialGlareAngle_degs; + static const float initialGlareAngle; static const glm::vec3 initialHazeGlareColor; static const xColor initialHazeGlareColorXcolor; - static const float initialHazeBaseReference_m; + static const float initialHazeBaseReference; using UniformBufferView = gpu::BufferView; @@ -107,10 +107,10 @@ namespace model { public: // DO NOT CHANGE ORDER HERE WITHOUT UNDERSTANDING THE std140 LAYOUT glm::vec3 hazeColor{ initialHazeColor }; - float hazeGlareBlend{ convertGlareAngleToPower(initialGlareAngle_degs) }; + float hazeGlareBlend{ convertGlareAngleToPower(initialGlareAngle) }; glm::vec3 hazeGlareColor{ initialHazeGlareColor }; - float hazeBaseReference{ initialHazeBaseReference_m }; + float hazeBaseReference{ initialHazeBaseReference }; glm::vec3 colorModulationFactor{ initialColorModulationFactor }; int hazeMode{ 0 }; // bit 0 - set to activate haze attenuation of fragment color @@ -124,11 +124,11 @@ namespace model { float hazeBackgroundBlend{ initialHazeBackgroundBlend }; // The haze attenuation exponents used by both fragment and directional light attenuation - float hazeRangeFactor{ convertHazeRangeToHazeRangeFactor(initialHazeRange_m) }; - float hazeHeightFactor{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeHeight_m) }; + float hazeRangeFactor{ convertHazeRangeToHazeRangeFactor(initialHazeRange) }; + float hazeHeightFactor{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeHeight) }; - float hazeKeyLightRangeFactor{ convertHazeRangeToHazeRangeFactor(initialHazeKeyLightRange_m) }; - float hazeKeyLightAltitudeFactor{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeKeyLightAltitude_m) }; + float hazeKeyLightRangeFactor{ convertHazeRangeToHazeRangeFactor(initialHazeKeyLightRange) }; + float hazeKeyLightAltitudeFactor{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeKeyLightAltitude) }; Parameters() {} }; diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index 5c3d527e91..3be74da26a 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -25,8 +25,8 @@ void HazeConfig::setHazeColor(const glm::vec3 value) { hazeColor = value; } -void HazeConfig::setHazeGlareAngle_degs(const float value) { - hazeGlareAngle_degs = value; +void HazeConfig::setHazeGlareAngle(const float value) { + hazeGlareAngle = value; } void HazeConfig::setHazeGlareColor(const glm::vec3 value) { @@ -34,7 +34,7 @@ void HazeConfig::setHazeGlareColor(const glm::vec3 value) { } void HazeConfig::setHazeBaseReference(const float value) { - hazeBaseReference_m = value; + hazeBaseReference = value; } void HazeConfig::setHazeActive(const bool active) { @@ -57,20 +57,20 @@ void HazeConfig::setHazeEnableGlare(const bool active) { isHazeEnableGlare = active; } -void HazeConfig::setHazeRange_m(const float value) { - hazeRange_m = value; +void HazeConfig::setHazeRange(const float value) { + hazeRange = value; } -void HazeConfig::setHazeAltitude_m(const float value) { - hazeHeight_m = value; +void HazeConfig::setHazeAltitude(const float value) { + hazeHeight = value; } -void HazeConfig::setHazeKeyLightRange_m(const float value) { - hazeKeyLightRange_m = value; +void HazeConfig::setHazeKeyLightRange(const float value) { + hazeKeyLightRange = value; } -void HazeConfig::setHazeKeyLightAltitude_m(const float value) { - hazeKeyLightAltitude_m = value; +void HazeConfig::setHazeKeyLightAltitude(const float value) { + hazeKeyLightAltitude = value; } void HazeConfig::setHazeBackgroundBlend(const float value) { @@ -83,10 +83,10 @@ MakeHaze::MakeHaze() { void MakeHaze::configure(const Config& config) { _haze->setHazeColor(config.hazeColor); - _haze->setHazeGlareBlend(model::convertGlareAngleToPower(config.hazeGlareAngle_degs)); + _haze->setHazeGlareBlend(model::convertGlareAngleToPower(config.hazeGlareAngle)); _haze->setHazeGlareColor(config.hazeGlareColor); - _haze->setHazeBaseReference(config.hazeBaseReference_m); + _haze->setHazeBaseReference(config.hazeBaseReference); _haze->setHazeActive(config.isHazeActive); _haze->setAltitudeBased(config.isAltitudeBased); @@ -94,11 +94,11 @@ void MakeHaze::configure(const Config& config) { _haze->setModulateColorActive(config.isModulateColorActive); _haze->setHazeEnableGlare(config.isHazeEnableGlare); - _haze->setHazeRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeRange_m)); - _haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight_m)); + _haze->setHazeRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeRange)); + _haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight)); - _haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange_m)); - _haze->setHazeKeyLightAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude_m)); + _haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange)); + _haze->setHazeKeyLightAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude)); _haze->setHazeBackgroundBlend(config.hazeBackgroundBlend); } diff --git a/libraries/render-utils/src/DrawHaze.h b/libraries/render-utils/src/DrawHaze.h index 3005203c5b..15337c850b 100644 --- a/libraries/render-utils/src/DrawHaze.h +++ b/libraries/render-utils/src/DrawHaze.h @@ -30,10 +30,10 @@ class MakeHazeConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(glm::vec3 hazeColor MEMBER hazeColor WRITE setHazeColor NOTIFY dirty); - Q_PROPERTY(float hazeGlareAngle_degs MEMBER hazeGlareAngle_degs WRITE setHazeGlareAngle_degs NOTIFY dirty); + Q_PROPERTY(float hazeGlareAngle MEMBER hazeGlareAngle WRITE setHazeGlareAngle NOTIFY dirty); Q_PROPERTY(glm::vec3 hazeGlareColor MEMBER hazeGlareColor WRITE setHazeGlareColor NOTIFY dirty); - Q_PROPERTY(float hazeBaseReference_m MEMBER hazeBaseReference_m WRITE setHazeBaseReference NOTIFY dirty); + Q_PROPERTY(float hazeBaseReference MEMBER hazeBaseReference WRITE setHazeBaseReference NOTIFY dirty); Q_PROPERTY(bool isHazeActive MEMBER isHazeActive WRITE setHazeActive NOTIFY dirty); Q_PROPERTY(bool isAltitudeBased MEMBER isAltitudeBased WRITE setAltitudeBased NOTIFY dirty); @@ -41,11 +41,11 @@ class MakeHazeConfig : public render::Job::Config { Q_PROPERTY(bool isModulateColorActive MEMBER isModulateColorActive WRITE setModulateColorActive NOTIFY dirty); Q_PROPERTY(bool isHazeEnableGlare MEMBER isHazeEnableGlare WRITE setHazeEnableGlare NOTIFY dirty); - Q_PROPERTY(float hazeRange_m MEMBER hazeRange_m WRITE setHazeRange_m NOTIFY dirty); - Q_PROPERTY(float hazeHeight_m MEMBER hazeHeight_m WRITE setHazeAltitude_m NOTIFY dirty); + Q_PROPERTY(float hazeRange MEMBER hazeRange WRITE setHazeRange NOTIFY dirty); + Q_PROPERTY(float hazeHeight MEMBER hazeHeight WRITE setHazeAltitude NOTIFY dirty); - Q_PROPERTY(float hazeKeyLightRange_m MEMBER hazeKeyLightRange_m WRITE setHazeKeyLightRange_m NOTIFY dirty); - Q_PROPERTY(float hazeKeyLightAltitude_m MEMBER hazeKeyLightAltitude_m WRITE setHazeKeyLightAltitude_m NOTIFY dirty); + Q_PROPERTY(float hazeKeyLightRange MEMBER hazeKeyLightRange WRITE setHazeKeyLightRange NOTIFY dirty); + Q_PROPERTY(float hazeKeyLightAltitude MEMBER hazeKeyLightAltitude WRITE setHazeKeyLightAltitude NOTIFY dirty); Q_PROPERTY(float hazeBackgroundBlend MEMBER hazeBackgroundBlend WRITE setHazeBackgroundBlend NOTIFY dirty); @@ -53,10 +53,10 @@ public: MakeHazeConfig() : render::Job::Config() {} glm::vec3 hazeColor{ model::Haze::initialHazeColor }; - float hazeGlareAngle_degs{ model::Haze::initialGlareAngle_degs }; + float hazeGlareAngle{ model::Haze::initialGlareAngle }; glm::vec3 hazeGlareColor{ model::Haze::initialHazeGlareColor }; - float hazeBaseReference_m{ model::Haze::initialHazeBaseReference_m }; + float hazeBaseReference{ model::Haze::initialHazeBaseReference }; bool isHazeActive{ false }; bool isAltitudeBased{ false }; @@ -64,20 +64,20 @@ public: bool isModulateColorActive{ false }; bool isHazeEnableGlare{ false }; - float hazeRange_m{ model::Haze::initialHazeRange_m }; - float hazeHeight_m{ model::Haze::initialHazeHeight_m }; + float hazeRange{ model::Haze::initialHazeRange }; + float hazeHeight{ model::Haze::initialHazeHeight }; - float hazeKeyLightRange_m{ model::Haze::initialHazeKeyLightRange_m }; - float hazeKeyLightAltitude_m{ model::Haze::initialHazeKeyLightAltitude_m }; + float hazeKeyLightRange{ model::Haze::initialHazeKeyLightRange }; + float hazeKeyLightAltitude{ model::Haze::initialHazeKeyLightAltitude }; float hazeBackgroundBlend{ model::Haze::initialHazeBackgroundBlend }; public slots: void setHazeColor(const glm::vec3 value) { hazeColor = value; emit dirty(); } - void setHazeGlareAngle_degs(const float value) { hazeGlareAngle_degs = value; emit dirty(); } + void setHazeGlareAngle(const float value) { hazeGlareAngle = value; emit dirty(); } void setHazeGlareColor(const glm::vec3 value) { hazeGlareColor = value; emit dirty(); } - void setHazeBaseReference(const float value) { hazeBaseReference_m = value; ; emit dirty(); } + void setHazeBaseReference(const float value) { hazeBaseReference = value; ; emit dirty(); } void setHazeActive(const bool active) { isHazeActive = active; emit dirty(); } void setAltitudeBased(const bool active) { isAltitudeBased = active; emit dirty(); } @@ -85,11 +85,11 @@ public slots: void setModulateColorActive(const bool active) { isModulateColorActive = active; emit dirty(); } void setHazeEnableGlare(const bool active) { isHazeEnableGlare = active; emit dirty(); } - void setHazeRange_m(const float value) { hazeRange_m = value; emit dirty(); } - void setHazeAltitude_m(const float value) { hazeHeight_m = value; emit dirty(); } + void setHazeRange(const float value) { hazeRange = value; emit dirty(); } + void setHazeAltitude(const float value) { hazeHeight = value; emit dirty(); } - void setHazeKeyLightRange_m(const float value) { hazeKeyLightRange_m = value; emit dirty(); } - void setHazeKeyLightAltitude_m(const float value) { hazeKeyLightAltitude_m = value; emit dirty(); } + void setHazeKeyLightRange(const float value) { hazeKeyLightRange = value; emit dirty(); } + void setHazeKeyLightAltitude(const float value) { hazeKeyLightAltitude = value; emit dirty(); } void setHazeBackgroundBlend(const float value) { hazeBackgroundBlend = value; ; emit dirty(); } @@ -117,10 +117,10 @@ public: // attributes glm::vec3 hazeColor{ model::Haze::initialHazeColor }; - float hazeGlareAngle_degs{ model::Haze::initialGlareAngle_degs }; + float hazeGlareAngle{ model::Haze::initialGlareAngle }; glm::vec3 hazeGlareColor{ model::Haze::initialHazeGlareColor }; - float hazeBaseReference_m{ model::Haze::initialHazeBaseReference_m }; + float hazeBaseReference{ model::Haze::initialHazeBaseReference }; bool isHazeActive{ false }; // Setting this to true will set haze to on bool isAltitudeBased{ false }; @@ -128,17 +128,17 @@ public: bool isModulateColorActive{ false }; bool isHazeEnableGlare{ false }; - float hazeRange_m{ model::Haze::initialHazeRange_m }; - float hazeHeight_m{ model::Haze::initialHazeHeight_m }; + float hazeRange{ model::Haze::initialHazeRange }; + float hazeHeight{ model::Haze::initialHazeHeight }; - float hazeKeyLightRange_m{ model::Haze::initialHazeKeyLightRange_m }; - float hazeKeyLightAltitude_m{ model::Haze::initialHazeKeyLightAltitude_m }; + float hazeKeyLightRange{ model::Haze::initialHazeKeyLightRange }; + float hazeKeyLightAltitude{ model::Haze::initialHazeKeyLightAltitude }; float hazeBackgroundBlend{ model::Haze::initialHazeBackgroundBlend }; // methods void setHazeColor(const glm::vec3 value); - void setHazeGlareAngle_degs(const float value); + void setHazeGlareAngle(const float value); void setHazeGlareColor(const glm::vec3 value); void setHazeBaseReference(const float value); @@ -149,11 +149,11 @@ public: void setModulateColorActive(const bool active); void setHazeEnableGlare(const bool active); - void setHazeRange_m(const float value); - void setHazeAltitude_m(const float value); + void setHazeRange(const float value); + void setHazeAltitude(const float value); - void setHazeKeyLightRange_m(const float value); - void setHazeKeyLightAltitude_m(const float value); + void setHazeKeyLightRange(const float value); + void setHazeKeyLightAltitude(const float value); void setHazeBackgroundBlend(const float value); }; diff --git a/libraries/render-utils/src/HazeStage.cpp b/libraries/render-utils/src/HazeStage.cpp index 71baecb0e4..c9e6ef90cb 100644 --- a/libraries/render-utils/src/HazeStage.cpp +++ b/libraries/render-utils/src/HazeStage.cpp @@ -21,10 +21,10 @@ FetchHazeStage::FetchHazeStage() { void FetchHazeStage::configure(const Config& config) { _haze->setHazeColor(config.hazeColor); - _haze->setHazeGlareBlend(model::convertGlareAngleToPower(config.hazeGlareAngle_degs)); + _haze->setHazeGlareBlend(model::convertGlareAngleToPower(config.hazeGlareAngle)); _haze->setHazeGlareColor(config.hazeGlareColor); - _haze->setHazeBaseReference(config.hazeBaseReference_m); + _haze->setHazeBaseReference(config.hazeBaseReference); _haze->setHazeActive(config.isHazeActive); _haze->setAltitudeBased(config.isAltitudeBased); @@ -32,11 +32,11 @@ void FetchHazeStage::configure(const Config& config) { _haze->setModulateColorActive(config.isModulateColorActive); _haze->setHazeEnableGlare(config.isHazeEnableGlare); - _haze->setHazeRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeRange_m)); - _haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight_m)); + _haze->setHazeRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeRange)); + _haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight)); - _haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange_m)); - _haze->setHazeKeyLightAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude_m)); + _haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange)); + _haze->setHazeKeyLightAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude)); _haze->setHazeBackgroundBlend(config.hazeBackgroundBlend); } diff --git a/libraries/render-utils/src/HazeStage.h b/libraries/render-utils/src/HazeStage.h index 1f1a94a806..42f26a2679 100644 --- a/libraries/render-utils/src/HazeStage.h +++ b/libraries/render-utils/src/HazeStage.h @@ -84,10 +84,10 @@ class FetchHazeConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(glm::vec3 hazeColor MEMBER hazeColor WRITE setHazeColor NOTIFY dirty); - Q_PROPERTY(float hazeGlareAngle_degs MEMBER hazeGlareAngle_degs WRITE setHazeGlareAngle_degs NOTIFY dirty); + Q_PROPERTY(float hazeGlareAngle MEMBER hazeGlareAngle WRITE setHazeGlareAngle NOTIFY dirty); Q_PROPERTY(glm::vec3 hazeGlareColor MEMBER hazeGlareColor WRITE setHazeGlareColor NOTIFY dirty); - Q_PROPERTY(float hazeBaseReference_m MEMBER hazeBaseReference_m WRITE setHazeBaseReference NOTIFY dirty); + Q_PROPERTY(float hazeBaseReference MEMBER hazeBaseReference WRITE setHazeBaseReference NOTIFY dirty); Q_PROPERTY(bool isHazeActive MEMBER isHazeActive WRITE setHazeActive NOTIFY dirty); Q_PROPERTY(bool isAltitudeBased MEMBER isAltitudeBased WRITE setAltitudeBased NOTIFY dirty); @@ -95,11 +95,11 @@ class FetchHazeConfig : public render::Job::Config { Q_PROPERTY(bool isModulateColorActive MEMBER isModulateColorActive WRITE setModulateColorActive NOTIFY dirty); Q_PROPERTY(bool isHazeEnableGlare MEMBER isHazeEnableGlare WRITE setHazeEnableGlare NOTIFY dirty); - Q_PROPERTY(float hazeRange_m MEMBER hazeRange_m WRITE setHazeRange_m NOTIFY dirty); - Q_PROPERTY(float hazeHeight_m MEMBER hazeHeight_m WRITE setHazeAltitude_m NOTIFY dirty); + Q_PROPERTY(float hazeRange MEMBER hazeRange WRITE setHazeRange NOTIFY dirty); + Q_PROPERTY(float hazeHeight MEMBER hazeHeight WRITE setHazeAltitude NOTIFY dirty); - Q_PROPERTY(float hazeKeyLightRange_m MEMBER hazeKeyLightRange_m WRITE setHazeKeyLightRange_m NOTIFY dirty); - Q_PROPERTY(float hazeKeyLightAltitude_m MEMBER hazeKeyLightAltitude_m WRITE setHazeKeyLightAltitude_m NOTIFY dirty); + Q_PROPERTY(float hazeKeyLightRange MEMBER hazeKeyLightRange WRITE setHazeKeyLightRange NOTIFY dirty); + Q_PROPERTY(float hazeKeyLightAltitude MEMBER hazeKeyLightAltitude WRITE setHazeKeyLightAltitude NOTIFY dirty); Q_PROPERTY(float hazeBackgroundBlend MEMBER hazeBackgroundBlend WRITE setHazeBackgroundBlend NOTIFY dirty); @@ -107,10 +107,10 @@ public: FetchHazeConfig() : render::Job::Config() {} glm::vec3 hazeColor{ model::Haze::initialHazeColor }; - float hazeGlareAngle_degs{ model::Haze::initialGlareAngle_degs }; + float hazeGlareAngle{ model::Haze::initialGlareAngle }; glm::vec3 hazeGlareColor{ model::Haze::initialHazeGlareColor }; - float hazeBaseReference_m{ model::Haze::initialHazeBaseReference_m }; + float hazeBaseReference{ model::Haze::initialHazeBaseReference }; bool isHazeActive{ false }; bool isAltitudeBased{ false }; @@ -118,20 +118,20 @@ public: bool isModulateColorActive{ false }; bool isHazeEnableGlare{ false }; - float hazeRange_m{ model::Haze::initialHazeRange_m }; - float hazeHeight_m{ model::Haze::initialHazeHeight_m }; + float hazeRange{ model::Haze::initialHazeRange }; + float hazeHeight{ model::Haze::initialHazeHeight }; - float hazeKeyLightRange_m{ model::Haze::initialHazeKeyLightRange_m }; - float hazeKeyLightAltitude_m{ model::Haze::initialHazeKeyLightAltitude_m }; + float hazeKeyLightRange{ model::Haze::initialHazeKeyLightRange }; + float hazeKeyLightAltitude{ model::Haze::initialHazeKeyLightAltitude }; float hazeBackgroundBlend{ model::Haze::initialHazeBackgroundBlend }; public slots: void setHazeColor(const glm::vec3 value) { hazeColor = value; emit dirty(); } - void setHazeGlareAngle_degs(const float value) { hazeGlareAngle_degs = value; emit dirty(); } + void setHazeGlareAngle(const float value) { hazeGlareAngle = value; emit dirty(); } void setHazeGlareColor(const glm::vec3 value) { hazeGlareColor = value; emit dirty(); } - void setHazeBaseReference(const float value) { hazeBaseReference_m = value; ; emit dirty(); } + void setHazeBaseReference(const float value) { hazeBaseReference = value; ; emit dirty(); } void setHazeActive(const bool active) { isHazeActive = active; emit dirty(); } void setAltitudeBased(const bool active) { isAltitudeBased = active; emit dirty(); } @@ -139,11 +139,11 @@ public slots: void setModulateColorActive(const bool active) { isModulateColorActive = active; emit dirty(); } void setHazeEnableGlare(const bool active) { isHazeEnableGlare = active; emit dirty(); } - void setHazeRange_m(const float value) { hazeRange_m = value; emit dirty(); } - void setHazeAltitude_m(const float value) { hazeHeight_m = value; emit dirty(); } + void setHazeRange(const float value) { hazeRange = value; emit dirty(); } + void setHazeAltitude(const float value) { hazeHeight = value; emit dirty(); } - void setHazeKeyLightRange_m(const float value) { hazeKeyLightRange_m = value; emit dirty(); } - void setHazeKeyLightAltitude_m(const float value) { hazeKeyLightAltitude_m = value; emit dirty(); } + void setHazeKeyLightRange(const float value) { hazeKeyLightRange = value; emit dirty(); } + void setHazeKeyLightAltitude(const float value) { hazeKeyLightAltitude = value; emit dirty(); } void setHazeBackgroundBlend(const float value) { hazeBackgroundBlend = value; ; emit dirty(); } From 3ddf970be3b950bb93d4ff78ce197ac3c4037ba5 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Mon, 30 Oct 2017 21:40:14 -0700 Subject: [PATCH 063/183] Removed haze init variables from the model namespace. --- libraries/entities/CMakeLists.txt | 2 +- libraries/entities/src/HazePropertyGroup.h | 33 ++++++++---- libraries/entities/src/ZoneEntityItem.h | 1 - libraries/model/src/model/Haze.cpp | 26 ++++----- libraries/model/src/model/Haze.h | 61 +++++++++++----------- libraries/render-utils/src/DrawHaze.h | 39 +++++++------- libraries/render-utils/src/HazeStage.h | 18 +++---- 7 files changed, 90 insertions(+), 90 deletions(-) diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 146aecf1f6..c23740654e 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") -link_hifi_libraries(shared networking octree avatars model gpu) +link_hifi_libraries(shared networking octree avatars model) diff --git a/libraries/entities/src/HazePropertyGroup.h b/libraries/entities/src/HazePropertyGroup.h index 17db8a6369..965f112af9 100644 --- a/libraries/entities/src/HazePropertyGroup.h +++ b/libraries/entities/src/HazePropertyGroup.h @@ -21,14 +21,25 @@ #include "PropertyGroup.h" #include "EntityItemPropertiesMacros.h" -#include - class EntityItemProperties; class EncodeBitstreamParams; class OctreePacketData; class EntityTreeElementExtraEncodeData; class ReadBitstreamToTreeParams; +static const float initialHazeRange{ 1000.0f }; +static const xColor initialHazeGlareColorXcolor{ 255, 229, 179 }; +static const xColor initialHazeColorXcolor{ 128, 154, 179 }; +static const float initialGlareAngle{ 20.0f }; + +static const float initialHazeBaseReference{ 0.0f }; +static const float initialHazeHeight{ 200.0f }; + +static const float initialHazeBackgroundBlend{ 0.0f }; + +static const float initialHazeKeyLightRange{ 1000.0f }; +static const float initialHazeKeyLightAltitude{ 200.0f }; + class HazePropertyGroup : public PropertyGroup { public: // EntityItemProperty related helpers @@ -77,24 +88,24 @@ public: bool& somethingChanged) override; // Range only parameters - DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, model::Haze::initialHazeRange); - DEFINE_PROPERTY_REF(PROP_HAZE_COLOR, HazeColor, hazeColor, xColor, model::Haze::initialHazeColorXcolor); - DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_COLOR, HazeGlareColor, hazeGlareColor, xColor, model::Haze::initialHazeGlareColorXcolor); + DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, initialHazeRange); + DEFINE_PROPERTY_REF(PROP_HAZE_COLOR, HazeColor, hazeColor, xColor, initialHazeColorXcolor); + DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_COLOR, HazeGlareColor, hazeGlareColor, xColor, initialHazeGlareColorXcolor); DEFINE_PROPERTY(PROP_HAZE_ENABLE_GLARE, HazeEnableGlare, hazeEnableGlare, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_ANGLE, HazeGlareAngle, hazeGlareAngle, float, model::Haze::initialGlareAngle); + DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_ANGLE, HazeGlareAngle, hazeGlareAngle, float, initialGlareAngle); // Altitude parameters DEFINE_PROPERTY(PROP_HAZE_ALTITUDE_EFFECT, HazeAltitudeEffect, hazeAltitudeEffect, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_CEILING, HazeCeiling, hazeCeiling, float, model::Haze::initialHazeBaseReference + model::Haze::initialHazeHeight); - DEFINE_PROPERTY_REF(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, model::Haze::initialHazeBaseReference); + DEFINE_PROPERTY_REF(PROP_HAZE_CEILING, HazeCeiling, hazeCeiling, float, initialHazeBaseReference + initialHazeHeight); + DEFINE_PROPERTY_REF(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, initialHazeBaseReference); // Background (skybox) blend value - DEFINE_PROPERTY_REF(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend, hazeBackgroundBlend, float, model::Haze::initialHazeBackgroundBlend); + DEFINE_PROPERTY_REF(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend, hazeBackgroundBlend, float, initialHazeBackgroundBlend); // hazeDirectional light attenuation DEFINE_PROPERTY(PROP_HAZE_ATTENUATE_KEYLIGHT, HazeAttenuateKeyLight, hazeAttenuateKeyLight, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, model::Haze::initialHazeKeyLightRange); - DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, model::Haze::initialHazeKeyLightAltitude); + DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, initialHazeKeyLightRange); + DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, initialHazeKeyLightAltitude); }; #endif // hifi_HazePropertyGroup_h diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 3f78591745..46e8a00c24 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -19,7 +19,6 @@ #include "HazePropertyGroup.h" #include "StagePropertyGroup.h" #include -#include class ZoneEntityItem : public EntityItem { public: diff --git a/libraries/model/src/model/Haze.cpp b/libraries/model/src/model/Haze.cpp index f29824936f..01cb32a98b 100644 --- a/libraries/model/src/model/Haze.cpp +++ b/libraries/model/src/model/Haze.cpp @@ -14,29 +14,21 @@ using namespace model; -const float Haze::initialHazeRange{ 1000.0f }; -const float Haze::initialHazeHeight{ 200.0f }; +const float HazeInit::initialHazeRange{ 1000.0f }; +const float HazeInit::initialHazeHeight{ 200.0f }; -const float Haze::initialHazeKeyLightRange{ 1000.0f }; -const float Haze::initialHazeKeyLightAltitude{ 200.0f }; +const float HazeInit::initialHazeKeyLightRange{ 1000.0f }; +const float HazeInit::initialHazeKeyLightAltitude{ 200.0f }; -const float Haze::initialHazeBackgroundBlend{ 0.0f }; +const float HazeInit::initialHazeBackgroundBlend{ 0.0f }; -const glm::vec3 Haze::initialColorModulationFactor{ - convertHazeRangeToHazeRangeFactor(initialHazeRange), - convertHazeRangeToHazeRangeFactor(initialHazeRange), - convertHazeRangeToHazeRangeFactor(initialHazeRange) -}; +const glm::vec3 HazeInit::initialHazeColor{ 0.5f, 0.6f, 0.7f }; // Bluish -const glm::vec3 Haze::initialHazeColor{ 0.5f, 0.6f, 0.7f }; // Bluish -const xColor Haze::initialHazeColorXcolor{ 128, 154, 179 }; +const float HazeInit::initialGlareAngle{ 20.0f }; -const float Haze::initialGlareAngle{ 20.0f }; +const glm::vec3 HazeInit::initialHazeGlareColor{ 1.0f, 0.9f, 0.7f }; -const glm::vec3 Haze::initialHazeGlareColor{ 1.0f, 0.9f, 0.7f }; -const xColor Haze::initialHazeGlareColorXcolor{ 255, 229, 179 }; - -const float Haze::initialHazeBaseReference{ 0.0f }; +const float HazeInit::initialHazeBaseReference{ 0.0f }; Haze::Haze() { Parameters parameters; diff --git a/libraries/model/src/model/Haze.h b/libraries/model/src/model/Haze.h index 00e8f3625c..b02a044459 100644 --- a/libraries/model/src/model/Haze.h +++ b/libraries/model/src/model/Haze.h @@ -17,6 +17,26 @@ #include "Transform.h" #include "NumericalConstants.h" +class HazeInit { +public: + // Initial values + static const float initialHazeRange; + static const float initialHazeHeight; + + static const float initialHazeKeyLightRange; + static const float initialHazeKeyLightAltitude; + + static const float initialHazeBackgroundBlend; + + static const glm::vec3 initialHazeColor; + + static const float initialGlareAngle; + + static const glm::vec3 initialHazeGlareColor; + + static const float initialHazeBaseReference; +}; + namespace model { const float LOG_P_005 = logf(0.05f); const float LOG_P_05 = logf(0.5f); @@ -53,27 +73,6 @@ namespace model { class Haze { public: - // Initial values - static const float initialHazeRange; - static const float initialHazeHeight; - - static const float initialHazeKeyLightRange; - static const float initialHazeKeyLightAltitude; - - static const float initialHazeBackgroundBlend; - - static const glm::vec3 initialColorModulationFactor; - - static const glm::vec3 initialHazeColor; - static const xColor initialHazeColorXcolor; - - static const float initialGlareAngle; - - static const glm::vec3 initialHazeGlareColor; - static const xColor initialHazeGlareColorXcolor; - - static const float initialHazeBaseReference; - using UniformBufferView = gpu::BufferView; Haze(); @@ -106,13 +105,13 @@ namespace model { class Parameters { public: // DO NOT CHANGE ORDER HERE WITHOUT UNDERSTANDING THE std140 LAYOUT - glm::vec3 hazeColor{ initialHazeColor }; - float hazeGlareBlend{ convertGlareAngleToPower(initialGlareAngle) }; + glm::vec3 hazeColor{ HazeInit::initialHazeColor }; + float hazeGlareBlend{ convertGlareAngleToPower(HazeInit::initialGlareAngle) }; - glm::vec3 hazeGlareColor{ initialHazeGlareColor }; - float hazeBaseReference{ initialHazeBaseReference }; + glm::vec3 hazeGlareColor{ HazeInit::initialHazeGlareColor }; + float hazeBaseReference{ HazeInit::initialHazeBaseReference }; - glm::vec3 colorModulationFactor{ initialColorModulationFactor }; + glm::vec3 colorModulationFactor; int hazeMode{ 0 }; // bit 0 - set to activate haze attenuation of fragment color // bit 1 - set to add the effect of altitude to the haze attenuation // bit 2 - set to activate directional light attenuation mode @@ -121,14 +120,14 @@ namespace model { glm::mat4 zoneTransform; // Amount of background (skybox) to display, overriding the haze effect for the background - float hazeBackgroundBlend{ initialHazeBackgroundBlend }; + float hazeBackgroundBlend{ HazeInit::initialHazeBackgroundBlend }; // The haze attenuation exponents used by both fragment and directional light attenuation - float hazeRangeFactor{ convertHazeRangeToHazeRangeFactor(initialHazeRange) }; - float hazeHeightFactor{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeHeight) }; + float hazeRangeFactor{ convertHazeRangeToHazeRangeFactor(HazeInit::initialHazeRange) }; + float hazeHeightFactor{ convertHazeAltitudeToHazeAltitudeFactor(HazeInit::initialHazeHeight) }; - float hazeKeyLightRangeFactor{ convertHazeRangeToHazeRangeFactor(initialHazeKeyLightRange) }; - float hazeKeyLightAltitudeFactor{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeKeyLightAltitude) }; + float hazeKeyLightRangeFactor{ convertHazeRangeToHazeRangeFactor(HazeInit::initialHazeKeyLightRange) }; + float hazeKeyLightAltitudeFactor{ convertHazeAltitudeToHazeAltitudeFactor(HazeInit::initialHazeKeyLightAltitude) }; Parameters() {} }; diff --git a/libraries/render-utils/src/DrawHaze.h b/libraries/render-utils/src/DrawHaze.h index 15337c850b..c460d38bf1 100644 --- a/libraries/render-utils/src/DrawHaze.h +++ b/libraries/render-utils/src/DrawHaze.h @@ -19,11 +19,10 @@ #include #include #include +#include #include "SurfaceGeometryPass.h" -#include - using LinearDepthFramebufferPointer = std::shared_ptr; class MakeHazeConfig : public render::Job::Config { @@ -52,11 +51,11 @@ class MakeHazeConfig : public render::Job::Config { public: MakeHazeConfig() : render::Job::Config() {} - glm::vec3 hazeColor{ model::Haze::initialHazeColor }; - float hazeGlareAngle{ model::Haze::initialGlareAngle }; + glm::vec3 hazeColor{ HazeInit::initialHazeColor }; + float hazeGlareAngle{ HazeInit::initialGlareAngle }; - glm::vec3 hazeGlareColor{ model::Haze::initialHazeGlareColor }; - float hazeBaseReference{ model::Haze::initialHazeBaseReference }; + glm::vec3 hazeGlareColor{ HazeInit::initialHazeGlareColor }; + float hazeBaseReference{ HazeInit::initialHazeBaseReference }; bool isHazeActive{ false }; bool isAltitudeBased{ false }; @@ -64,13 +63,13 @@ public: bool isModulateColorActive{ false }; bool isHazeEnableGlare{ false }; - float hazeRange{ model::Haze::initialHazeRange }; - float hazeHeight{ model::Haze::initialHazeHeight }; + float hazeRange{ HazeInit::initialHazeRange }; + float hazeHeight{ HazeInit::initialHazeHeight }; - float hazeKeyLightRange{ model::Haze::initialHazeKeyLightRange }; - float hazeKeyLightAltitude{ model::Haze::initialHazeKeyLightAltitude }; + float hazeKeyLightRange{ HazeInit::initialHazeKeyLightRange }; + float hazeKeyLightAltitude{ HazeInit::initialHazeKeyLightAltitude }; - float hazeBackgroundBlend{ model::Haze::initialHazeBackgroundBlend }; + float hazeBackgroundBlend{ HazeInit::initialHazeBackgroundBlend }; public slots: void setHazeColor(const glm::vec3 value) { hazeColor = value; emit dirty(); } @@ -116,11 +115,11 @@ public: HazeConfig() : render::Job::Config(true) {} // attributes - glm::vec3 hazeColor{ model::Haze::initialHazeColor }; - float hazeGlareAngle{ model::Haze::initialGlareAngle }; + glm::vec3 hazeColor{ HazeInit::initialHazeColor }; + float hazeGlareAngle{ HazeInit::initialGlareAngle }; - glm::vec3 hazeGlareColor{ model::Haze::initialHazeGlareColor }; - float hazeBaseReference{ model::Haze::initialHazeBaseReference }; + glm::vec3 hazeGlareColor{ HazeInit::initialHazeGlareColor }; + float hazeBaseReference{ HazeInit::initialHazeBaseReference }; bool isHazeActive{ false }; // Setting this to true will set haze to on bool isAltitudeBased{ false }; @@ -128,13 +127,13 @@ public: bool isModulateColorActive{ false }; bool isHazeEnableGlare{ false }; - float hazeRange{ model::Haze::initialHazeRange }; - float hazeHeight{ model::Haze::initialHazeHeight }; + float hazeRange{ HazeInit::initialHazeRange }; + float hazeHeight{ HazeInit::initialHazeHeight }; - float hazeKeyLightRange{ model::Haze::initialHazeKeyLightRange }; - float hazeKeyLightAltitude{ model::Haze::initialHazeKeyLightAltitude }; + float hazeKeyLightRange{ HazeInit::initialHazeKeyLightRange }; + float hazeKeyLightAltitude{ HazeInit::initialHazeKeyLightAltitude }; - float hazeBackgroundBlend{ model::Haze::initialHazeBackgroundBlend }; + float hazeBackgroundBlend{ HazeInit::initialHazeBackgroundBlend }; // methods void setHazeColor(const glm::vec3 value); diff --git a/libraries/render-utils/src/HazeStage.h b/libraries/render-utils/src/HazeStage.h index 42f26a2679..ac5a8dd6f5 100644 --- a/libraries/render-utils/src/HazeStage.h +++ b/libraries/render-utils/src/HazeStage.h @@ -106,11 +106,11 @@ class FetchHazeConfig : public render::Job::Config { public: FetchHazeConfig() : render::Job::Config() {} - glm::vec3 hazeColor{ model::Haze::initialHazeColor }; - float hazeGlareAngle{ model::Haze::initialGlareAngle }; + glm::vec3 hazeColor{ HazeInit::initialHazeColor }; + float hazeGlareAngle{ HazeInit::initialGlareAngle }; - glm::vec3 hazeGlareColor{ model::Haze::initialHazeGlareColor }; - float hazeBaseReference{ model::Haze::initialHazeBaseReference }; + glm::vec3 hazeGlareColor{ HazeInit::initialHazeGlareColor }; + float hazeBaseReference{ HazeInit::initialHazeBaseReference }; bool isHazeActive{ false }; bool isAltitudeBased{ false }; @@ -118,13 +118,13 @@ public: bool isModulateColorActive{ false }; bool isHazeEnableGlare{ false }; - float hazeRange{ model::Haze::initialHazeRange }; - float hazeHeight{ model::Haze::initialHazeHeight }; + float hazeRange{ HazeInit::initialHazeRange }; + float hazeHeight{ HazeInit::initialHazeHeight }; - float hazeKeyLightRange{ model::Haze::initialHazeKeyLightRange }; - float hazeKeyLightAltitude{ model::Haze::initialHazeKeyLightAltitude }; + float hazeKeyLightRange{ HazeInit::initialHazeKeyLightRange }; + float hazeKeyLightAltitude{ HazeInit::initialHazeKeyLightAltitude }; - float hazeBackgroundBlend{ model::Haze::initialHazeBackgroundBlend }; + float hazeBackgroundBlend{ HazeInit::initialHazeBackgroundBlend }; public slots: void setHazeColor(const glm::vec3 value) { hazeColor = value; emit dirty(); } From 90e92511767a5bbe3f248afd4d474e423bac5791 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 31 Oct 2017 11:08:02 -0700 Subject: [PATCH 064/183] It's a start --- .../octree/OctreeInboundPacketProcessor.cpp | 4 + .../ui/overlays/ContextOverlayInterface.cpp | 37 +++++++ .../src/ui/overlays/ContextOverlayInterface.h | 2 +- libraries/entities/src/EntityTree.cpp | 101 +++++++++++++----- libraries/entities/src/EntityTree.h | 2 + libraries/networking/src/udt/PacketHeaders.h | 2 + libraries/octree/src/Octree.h | 1 + 7 files changed, 119 insertions(+), 30 deletions(-) diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index 3f835678ac..50c95ffc5d 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp @@ -96,6 +96,10 @@ void OctreeInboundPacketProcessor::processPacket(QSharedPointer _myServer->getOctree()->withWriteLock([&] { _myServer->getOctree()->processChallengeOwnershipPacket(*message, sendingNode); }); + } else if (packetType == PacketType::ChallengeOwnershipRequest) { + _myServer->getOctree()->withWriteLock([&] { + _myServer->getOctree()->processChallengeOwnershipPacket(*message, sendingNode); + }); } else if (_myServer->getOctree()->handlesEditPacketType(packetType)) { PerformanceWarning warn(debugProcessPacket, "processPacket KNOWN TYPE", debugProcessPacket); _receivedPacketCount++; diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 70b75a0b17..402e72f2cf 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -42,6 +42,8 @@ ContextOverlayInterface::ContextOverlayInterface() { _entityPropertyFlags += PROP_DIMENSIONS; _entityPropertyFlags += PROP_REGISTRATION_POINT; _entityPropertyFlags += PROP_CERTIFICATE_ID; + _entityPropertyFlags += PROP_CLIENT_ONLY; + _entityPropertyFlags += PROP_OWNING_AVATAR_ID; auto entityScriptingInterface = DependencyManager::get().data(); connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity, this, &ContextOverlayInterface::createOrDestroyContextOverlay); @@ -260,6 +262,41 @@ void ContextOverlayInterface::openInspectionCertificate() { auto tablet = dynamic_cast(_tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); tablet->loadQMLSource(INSPECTION_CERTIFICATE_QML_PATH); _hmdScriptingInterface->openTablet(); + + EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_currentEntityWithContextOverlay, _entityPropertyFlags); + + QUuid nodeToChallenge = entityProperties.getOwningAvatarID(); + auto nodeList = DependencyManager::get(); + + qDebug() << "ZRF FIXME" << entityProperties.getClientOnly() << nodeToChallenge << nodeList->getSessionUUID(); + + // Don't challenge ownership of avatar entities that I own + if (entityProperties.getClientOnly() && nodeToChallenge != nodeList->getSessionUUID()) { + SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer); + + if (entityServer) { + QByteArray certID = entityProperties.getCertificateID().toUtf8(); + QByteArray ownerKey; // ZRF FIXME! + QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122(); + + int certIDByteArraySize = certID.length(); + int ownerKeyByteArraySize = ownerKey.length(); + int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length(); + + auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, + certIDByteArraySize + ownerKeyByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int), + true); + challengeOwnershipPacket->writePrimitive(certIDByteArraySize); + challengeOwnershipPacket->writePrimitive(ownerKeyByteArraySize); + challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize); + challengeOwnershipPacket->write(certID); + challengeOwnershipPacket->write(ownerKey); + challengeOwnershipPacket->write(nodeToChallengeByteArray); + nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer); + } else { + qCWarning(context_overlay) << "Couldn't get Entity Server!"; + } + } } } diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index b4d3ddc0c2..a063fdde23 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -73,7 +73,7 @@ public slots: private: bool _verboseLogging { true }; bool _enabled { true }; - QUuid _currentEntityWithContextOverlay{}; + EntityItemID _currentEntityWithContextOverlay{}; QString _entityMarketplaceID; bool _contextOverlayJustClicked { false }; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 22348360ed..90ee1190d5 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1153,8 +1153,8 @@ void EntityTree::startChallengeOwnershipTimer(const EntityItemID& entityItemID) _challengeOwnershipTimeoutTimer->deleteLater(); } }); - _challengeOwnershipTimeoutTimer->setSingleShot(true); - _challengeOwnershipTimeoutTimer->start(5000); +_challengeOwnershipTimeoutTimer->setSingleShot(true); +_challengeOwnershipTimeoutTimer->start(5000); } void EntityTree::startPendingTransferStatusTimer(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode) { @@ -1225,7 +1225,7 @@ bool EntityTree::verifyDecryptedNonce(const QString& certID, const QString& decr if (!id.isNull()) { qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed; deleting entity" << id << "\nActual nonce:" << actualNonce << "\nDecrypted nonce:" << decryptedNonce; - deleteEntity(id, true); + deleteEntity(id, true); } } else { qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "succeeded; keeping entity" << id; @@ -1234,6 +1234,71 @@ bool EntityTree::verifyDecryptedNonce(const QString& certID, const QString& decr return verificationSuccess; } +void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { + int certIDByteArraySize; + int ownerKeyByteArraySize; + int nodeToChallengeByteArraySize; + + message.readPrimitive(&certIDByteArraySize); + message.readPrimitive(&ownerKeyByteArraySize); + message.readPrimitive(&nodeToChallengeByteArraySize); + + QString certID(message.read(certIDByteArraySize)); + QString ownerKey(message.read(ownerKeyByteArraySize)); + QUuid nodeToChallenge = QUuid::fromRfc4122(message.read(nodeToChallengeByteArraySize)); + + sendChallengeOwnershipPacket(certID, ownerKey, EntityItemID(), sourceNode, nodeToChallenge); +} + +void EntityTree::sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, const QUuid& nodeToChallenge) { + // 1. Encrypt a nonce with the owner's public key + auto nodeList = DependencyManager::get(); + QByteArray encryptedText = computeEncryptedNonce(certID, ownerKey); + + if (encryptedText == "") { + qCDebug(entities) << "CRITICAL ERROR: Couldn't compute encrypted nonce."; + } else { + // In this case, the server is challenging a client. That client has just rezzed a new certified entity. + if (nodeToChallenge.isNull()) { + // 2. Send the encrypted text to the rezzing avatar's node + QByteArray certIDByteArray = certID.toUtf8(); + int certIDByteArraySize = certIDByteArray.size(); + auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnership, + certIDByteArraySize + encryptedText.length() + 2 * sizeof(int), + true); + challengeOwnershipPacket->writePrimitive(certIDByteArraySize); + challengeOwnershipPacket->writePrimitive(encryptedText.length()); + challengeOwnershipPacket->write(certIDByteArray); + challengeOwnershipPacket->write(encryptedText); + nodeList->sendPacket(std::move(challengeOwnershipPacket), *senderNode); + + // 3. Kickoff a 10-second timeout timer that deletes the entity if we don't get an ownership response in time + if (thread() != QThread::currentThread()) { + QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer", Q_ARG(const EntityItemID&, entityItemID)); + return; + } else { + startChallengeOwnershipTimer(entityItemID); + } + // In this case, Client A is challenging Client B. Client A is inspecting a certified entity that it wants + // to make sure belongs to Avatar B. + } else { + QByteArray senderNodeUUID = senderNode->getUUID().toRfc4122(); + QByteArray certIDByteArray = certID.toUtf8(); + int certIDByteArraySize = certIDByteArray.size(); + auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, + certIDByteArraySize + encryptedText.length() + senderNodeUUID.length() + 3 * sizeof(int), + true); + challengeOwnershipPacket->writePrimitive(certIDByteArraySize); + challengeOwnershipPacket->writePrimitive(encryptedText.length()); + challengeOwnershipPacket->writePrimitive(senderNodeUUID.length()); + challengeOwnershipPacket->write(certIDByteArray); + challengeOwnershipPacket->write(encryptedText); + challengeOwnershipPacket->write(senderNodeUUID); + nodeList->sendPacket(std::move(challengeOwnershipPacket), *(nodeList->nodeWithUUID(nodeToChallenge))); + } + } +} + void EntityTree::validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation) { // Start owner verification. auto nodeList = DependencyManager::get(); @@ -1279,33 +1344,11 @@ void EntityTree::validatePop(const QString& certID, const EntityItemID& entityIt } } else { // Second, challenge ownership of the PoP cert - // 1. Encrypt a nonce with the owner's public key - QByteArray encryptedText = computeEncryptedNonce(certID, jsonObject["transfer_recipient_key"].toString()); + sendChallengeOwnershipPacket(certID, + jsonObject["transfer_recipient_key"].toString(), + entityItemID, + senderNode); - if (encryptedText == "") { - qCDebug(entities) << "CRITICAL ERROR: Couldn't compute encrypted nonce. Deleting entity..."; - deleteEntity(entityItemID, true); - } else { - // 2. Send the encrypted text to the rezzing avatar's node - QByteArray certIDByteArray = certID.toUtf8(); - int certIDByteArraySize = certIDByteArray.size(); - auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnership, - certIDByteArraySize + encryptedText.length() + 2 * sizeof(int), - true); - challengeOwnershipPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipPacket->writePrimitive(encryptedText.length()); - challengeOwnershipPacket->write(certIDByteArray); - challengeOwnershipPacket->write(encryptedText); - nodeList->sendPacket(std::move(challengeOwnershipPacket), *senderNode); - - // 3. Kickoff a 10-second timeout timer that deletes the entity if we don't get an ownership response in time - if (thread() != QThread::currentThread()) { - QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer", Q_ARG(const EntityItemID&, entityItemID)); - return; - } else { - startChallengeOwnershipTimer(entityItemID); - } - } } } else { qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << "; deleting entity" << entityItemID diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 518cde9a59..3c11557dac 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -93,6 +93,7 @@ public: void fixupTerseEditLogging(EntityItemProperties& properties, QList& changedProperties); virtual int processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode) override; + virtual void processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) override; virtual void processChallengeOwnershipPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) override; virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, @@ -377,6 +378,7 @@ protected: private: QByteArray computeEncryptedNonce(const QString& certID, const QString ownerKey); bool verifyDecryptedNonce(const QString& certID, const QString& decryptedNonce); + void sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, const QUuid& nodeToChallenge = NULL); void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); }; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 049cb0f1a8..8d48b106e4 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -124,6 +124,8 @@ public: OctreeFileReplacementFromUrl, ChallengeOwnership, EntityScriptCallMethod, + ChallengeOwnershipRequest, + ChallengeOwnershipReply, NUM_PACKET_TYPE }; diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 2761dffb1b..fe8868b342 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -212,6 +212,7 @@ public: virtual bool handlesEditPacketType(PacketType packetType) const { return false; } virtual int processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength, const SharedNodePointer& sourceNode) { return 0; } + virtual void processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { return; } virtual void processChallengeOwnershipPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { return; } virtual bool recurseChildrenWithData() const { return true; } From 6f96e0c7bd30623c33add2fbaebfad6e8f4ea6e3 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 31 Oct 2017 12:14:12 -0700 Subject: [PATCH 065/183] More progress --- .../octree/OctreeInboundPacketProcessor.cpp | 6 +- interface/src/commerce/Wallet.cpp | 41 +++++-- interface/src/commerce/Wallet.h | 1 + .../ui/overlays/ContextOverlayInterface.cpp | 85 +++++++++---- libraries/entities/src/EntityTree.cpp | 112 ++++++++++++------ libraries/entities/src/EntityTree.h | 9 +- libraries/octree/src/Octree.h | 1 + 7 files changed, 186 insertions(+), 69 deletions(-) diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index 50c95ffc5d..bce6e7fe44 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp @@ -98,7 +98,11 @@ void OctreeInboundPacketProcessor::processPacket(QSharedPointer }); } else if (packetType == PacketType::ChallengeOwnershipRequest) { _myServer->getOctree()->withWriteLock([&] { - _myServer->getOctree()->processChallengeOwnershipPacket(*message, sendingNode); + _myServer->getOctree()->processChallengeOwnershipRequestPacket(*message, sendingNode); + }); + } else if (packetType == PacketType::ChallengeOwnershipReply) { + _myServer->getOctree()->withWriteLock([&] { + _myServer->getOctree()->processChallengeOwnershipReplyPacket(*message, sendingNode); }); } else if (_myServer->getOctree()->handlesEditPacketType(packetType)) { PerformanceWarning warn(debugProcessPacket, "processPacket KNOWN TYPE", debugProcessPacket); diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index c7c09d8b03..2389e8e39d 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -319,6 +319,7 @@ Wallet::Wallet() { auto& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::ChallengeOwnership, this, "handleChallengeOwnershipPacket"); + packetReceiver.registerListener(PacketType::ChallengeOwnershipRequest, this, "handleChallengeOwnershipPacket"); connect(ledger.data(), &Ledger::accountResult, this, [&]() { auto wallet = DependencyManager::get(); @@ -717,15 +718,24 @@ bool Wallet::changePassphrase(const QString& newPassphrase) { } void Wallet::handleChallengeOwnershipPacket(QSharedPointer packet, SharedNodePointer sendingNode) { + bool challengeOriginatedFromClient = packet->getType() == PacketType::ChallengeOwnershipRequest; unsigned char decryptedText[64]; int certIDByteArraySize; int encryptedTextByteArraySize; + int senderNodeUUIDByteArraySize; packet->readPrimitive(&certIDByteArraySize); packet->readPrimitive(&encryptedTextByteArraySize); + if (challengeOriginatedFromClient) { + packet->readPrimitive(&senderNodeUUIDByteArraySize); + } QByteArray certID = packet->read(certIDByteArraySize); QByteArray encryptedText = packet->read(encryptedTextByteArraySize); + QByteArray senderNodeUUID; + if (challengeOriginatedFromClient) { + packet->readPrimitive(&senderNodeUUID); + } RSA* rsa = readKeys(keyFilePath().toStdString().c_str()); @@ -745,16 +755,33 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack int decryptedTextByteArraySize = decryptedTextByteArray.size(); int certIDSize = certID.size(); // setup the packet - auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnership, certIDSize + decryptedTextByteArraySize + 2 * sizeof(int), true); + if (challengeOriginatedFromClient) { + auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, + certIDSize + decryptedTextByteArraySize + senderNodeUUIDByteArraySize + 3 * sizeof(int), + true); - decryptedTextPacket->writePrimitive(certIDSize); - decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); - decryptedTextPacket->write(certID); - decryptedTextPacket->write(decryptedTextByteArray); + decryptedTextPacket->writePrimitive(certIDSize); + decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); + decryptedTextPacket->writePrimitive(senderNodeUUIDByteArraySize); + decryptedTextPacket->write(certID); + decryptedTextPacket->write(decryptedTextByteArray); + decryptedTextPacket->write(senderNodeUUID); - qCDebug(commerce) << "Sending ChallengeOwnership Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; + qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; - nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); + nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); + } else { + auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnership, certIDSize + decryptedTextByteArraySize + 2 * sizeof(int), true); + + decryptedTextPacket->writePrimitive(certIDSize); + decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); + decryptedTextPacket->write(certID); + decryptedTextPacket->write(decryptedTextByteArray); + + qCDebug(commerce) << "Sending ChallengeOwnership Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; + + nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); + } } else { qCDebug(commerce) << "During entity ownership challenge, decrypting the encrypted text failed."; } diff --git a/interface/src/commerce/Wallet.h b/interface/src/commerce/Wallet.h index ed145df451..fcc508b4e9 100644 --- a/interface/src/commerce/Wallet.h +++ b/interface/src/commerce/Wallet.h @@ -67,6 +67,7 @@ signals: private slots: void handleChallengeOwnershipPacket(QSharedPointer packet, SharedNodePointer sendingNode); + void handleChallengeOwnershipRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); private: QStringList _publicKeys{}; diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 402e72f2cf..cfc2156a0f 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -14,6 +14,9 @@ #include #include +#include +#include +#include #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -268,31 +271,73 @@ void ContextOverlayInterface::openInspectionCertificate() { QUuid nodeToChallenge = entityProperties.getOwningAvatarID(); auto nodeList = DependencyManager::get(); - qDebug() << "ZRF FIXME" << entityProperties.getClientOnly() << nodeToChallenge << nodeList->getSessionUUID(); - - // Don't challenge ownership of avatar entities that I own - if (entityProperties.getClientOnly() && nodeToChallenge != nodeList->getSessionUUID()) { + // ZRF FIXME: Don't challenge ownership of avatar entities that I own + if (entityProperties.getClientOnly()/* && nodeToChallenge != nodeList->getSessionUUID()*/) { SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer); if (entityServer) { - QByteArray certID = entityProperties.getCertificateID().toUtf8(); - QByteArray ownerKey; // ZRF FIXME! - QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122(); + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkRequest networkRequest; + networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL; + requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer"); + QJsonObject request; + request["certificate_id"] = entityProperties.getCertificateID(); + networkRequest.setUrl(requestURL); - int certIDByteArraySize = certID.length(); - int ownerKeyByteArraySize = ownerKey.length(); - int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length(); + QNetworkReply* networkReply = NULL; + networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson()); - auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, - certIDByteArraySize + ownerKeyByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int), - true); - challengeOwnershipPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipPacket->writePrimitive(ownerKeyByteArraySize); - challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize); - challengeOwnershipPacket->write(certID); - challengeOwnershipPacket->write(ownerKey); - challengeOwnershipPacket->write(nodeToChallengeByteArray); - nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer); + connect(networkReply, &QNetworkReply::finished, [=]() { + QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object(); + jsonObject = jsonObject["data"].toObject(); + + if (networkReply->error() == QNetworkReply::NoError) { + if (!jsonObject["invalid_reason"].toString().isEmpty()) { + qCDebug(entities) << "invalid_reason not empty"; + } else if (jsonObject["transfer_status"].toArray().first().toString() == "failed") { + qCDebug(entities) << "'transfer_status' is 'failed'";; + } else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") { + qCDebug(entities) << "'transfer_status' is 'pending'";; + } else { + QByteArray certID = entityProperties.getCertificateID().toUtf8(); + QByteArray ownerKey = jsonObject["transfer_recipient_key"].toString().toUtf8(); + QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122(); + QByteArray encryptedText = DependencyManager::get()->getTree()->computeEncryptedNonce(certID, ownerKey); + + int certIDByteArraySize = certID.length(); + int ownerKeyByteArraySize = ownerKey.length(); + int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length(); + int encryptedTextByteArraySize = encryptedText.length(); + + auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, + certIDByteArraySize + ownerKeyByteArraySize + nodeToChallengeByteArraySize + encryptedTextByteArraySize + 4 * sizeof(int), + true); + challengeOwnershipPacket->writePrimitive(certIDByteArraySize); + challengeOwnershipPacket->writePrimitive(ownerKeyByteArraySize); + challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize); + challengeOwnershipPacket->writePrimitive(encryptedTextByteArraySize); + challengeOwnershipPacket->write(certID); + challengeOwnershipPacket->write(ownerKey); + challengeOwnershipPacket->write(nodeToChallengeByteArray); + challengeOwnershipPacket->write(encryptedText); + nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer); + + // Kickoff a 10-second timeout timer that marks the cert if we don't get an ownership response in time + //if (thread() != QThread::currentThread()) { + // QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer", Q_ARG(const EntityItemID&, entityItemID)); + // return; + //} else { + // startChallengeOwnershipTimer(entityItemID); + //} + } + } else { + qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error(); + } + + networkReply->deleteLater(); + }); } else { qCWarning(context_overlay) << "Couldn't get Entity Server!"; } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 90ee1190d5..71c6864b4f 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1237,68 +1237,104 @@ bool EntityTree::verifyDecryptedNonce(const QString& certID, const QString& decr void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { int certIDByteArraySize; int ownerKeyByteArraySize; + int encryptedTextByteArraySize; int nodeToChallengeByteArraySize; message.readPrimitive(&certIDByteArraySize); message.readPrimitive(&ownerKeyByteArraySize); + message.readPrimitive(&encryptedTextByteArraySize); message.readPrimitive(&nodeToChallengeByteArraySize); QString certID(message.read(certIDByteArraySize)); QString ownerKey(message.read(ownerKeyByteArraySize)); + QString encryptedText(message.read(encryptedTextByteArraySize)); QUuid nodeToChallenge = QUuid::fromRfc4122(message.read(nodeToChallengeByteArraySize)); - sendChallengeOwnershipPacket(certID, ownerKey, EntityItemID(), sourceNode, nodeToChallenge); + sendChallengeOwnershipRequestPacket(certID, ownerKey, encryptedText, sourceNode, nodeToChallenge); } -void EntityTree::sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, const QUuid& nodeToChallenge) { +void EntityTree::processChallengeOwnershipReplyPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { + auto nodeList = DependencyManager::get(); + + int certIDByteArraySize; + int decryptedTextByteArraySize; + int senderNodeUUIDByteArraySize; + + message.readPrimitive(&certIDByteArraySize); + message.readPrimitive(&decryptedTextByteArraySize); + message.readPrimitive(&senderNodeUUIDByteArraySize); + + QByteArray certID(message.read(certIDByteArraySize)); + QByteArray decryptedText(message.read(decryptedTextByteArraySize)); + QUuid challengingNode = QUuid::fromRfc4122(message.read(senderNodeUUIDByteArraySize)); + + + + auto challengeOwnershipReplyPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, + certIDByteArraySize + decryptedText.length() + 2 * sizeof(int), + true); + challengeOwnershipReplyPacket->writePrimitive(certIDByteArraySize); + challengeOwnershipReplyPacket->writePrimitive(decryptedText.length()); + challengeOwnershipReplyPacket->write(certID); + challengeOwnershipReplyPacket->write(decryptedText); + + nodeList->sendPacket(std::move(challengeOwnershipReplyPacket), *(nodeList->nodeWithUUID(challengingNode))); +} + +void EntityTree::sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode) { // 1. Encrypt a nonce with the owner's public key auto nodeList = DependencyManager::get(); + QByteArray encryptedText = computeEncryptedNonce(certID, ownerKey); if (encryptedText == "") { - qCDebug(entities) << "CRITICAL ERROR: Couldn't compute encrypted nonce."; + qCDebug(entities) << "CRITICAL ERROR: Couldn't compute encrypted nonce. Deleting entity..."; + deleteEntity(entityItemID, true); } else { - // In this case, the server is challenging a client. That client has just rezzed a new certified entity. - if (nodeToChallenge.isNull()) { - // 2. Send the encrypted text to the rezzing avatar's node - QByteArray certIDByteArray = certID.toUtf8(); - int certIDByteArraySize = certIDByteArray.size(); - auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnership, - certIDByteArraySize + encryptedText.length() + 2 * sizeof(int), - true); - challengeOwnershipPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipPacket->writePrimitive(encryptedText.length()); - challengeOwnershipPacket->write(certIDByteArray); - challengeOwnershipPacket->write(encryptedText); - nodeList->sendPacket(std::move(challengeOwnershipPacket), *senderNode); + // 2. Send the encrypted text to the rezzing avatar's node + QByteArray certIDByteArray = certID.toUtf8(); + int certIDByteArraySize = certIDByteArray.size(); + auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnership, + certIDByteArraySize + encryptedText.length() + 2 * sizeof(int), + true); + challengeOwnershipPacket->writePrimitive(certIDByteArraySize); + challengeOwnershipPacket->writePrimitive(encryptedText.length()); + challengeOwnershipPacket->write(certIDByteArray); + challengeOwnershipPacket->write(encryptedText); + nodeList->sendPacket(std::move(challengeOwnershipPacket), *senderNode); - // 3. Kickoff a 10-second timeout timer that deletes the entity if we don't get an ownership response in time - if (thread() != QThread::currentThread()) { - QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer", Q_ARG(const EntityItemID&, entityItemID)); - return; - } else { - startChallengeOwnershipTimer(entityItemID); - } - // In this case, Client A is challenging Client B. Client A is inspecting a certified entity that it wants - // to make sure belongs to Avatar B. + // 3. Kickoff a 10-second timeout timer that deletes the entity if we don't get an ownership response in time + if (thread() != QThread::currentThread()) { + QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer", Q_ARG(const EntityItemID&, entityItemID)); + return; } else { - QByteArray senderNodeUUID = senderNode->getUUID().toRfc4122(); - QByteArray certIDByteArray = certID.toUtf8(); - int certIDByteArraySize = certIDByteArray.size(); - auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, - certIDByteArraySize + encryptedText.length() + senderNodeUUID.length() + 3 * sizeof(int), - true); - challengeOwnershipPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipPacket->writePrimitive(encryptedText.length()); - challengeOwnershipPacket->writePrimitive(senderNodeUUID.length()); - challengeOwnershipPacket->write(certIDByteArray); - challengeOwnershipPacket->write(encryptedText); - challengeOwnershipPacket->write(senderNodeUUID); - nodeList->sendPacket(std::move(challengeOwnershipPacket), *(nodeList->nodeWithUUID(nodeToChallenge))); + startChallengeOwnershipTimer(entityItemID); } } } +void EntityTree::sendChallengeOwnershipRequestPacket(const QString& certID, const QString& ownerKey, const QString& encryptedText, const SharedNodePointer& senderNode, const QUuid& nodeToChallenge) { + // 1. Encrypt a nonce with the owner's public key + auto nodeList = DependencyManager::get(); + + // In this case, Client A is challenging Client B. Client A is inspecting a certified entity that it wants + // to make sure belongs to Avatar B. + QByteArray senderNodeUUID = senderNode->getUUID().toRfc4122(); + QByteArray encryptedTextByteArray = encryptedText.toUtf8(); + QByteArray certIDByteArray = certID.toUtf8(); + int certIDByteArraySize = certIDByteArray.size(); + auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, + certIDByteArraySize + encryptedTextByteArray.length() + senderNodeUUID.length() + 3 * sizeof(int), + true); + challengeOwnershipPacket->writePrimitive(certIDByteArraySize); + challengeOwnershipPacket->writePrimitive(encryptedTextByteArray.length()); + challengeOwnershipPacket->writePrimitive(senderNodeUUID.length()); + challengeOwnershipPacket->write(certIDByteArray); + challengeOwnershipPacket->write(encryptedTextByteArray); + challengeOwnershipPacket->write(senderNodeUUID); + nodeList->sendPacket(std::move(challengeOwnershipPacket), *(nodeList->nodeWithUUID(nodeToChallenge))); +} + void EntityTree::validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation) { // Start owner verification. auto nodeList = DependencyManager::get(); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 3c11557dac..05b32676ed 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -94,6 +94,7 @@ public: virtual int processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode) override; virtual void processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) override; + virtual void processChallengeOwnershipReplyPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) override; virtual void processChallengeOwnershipPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) override; virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, @@ -274,6 +275,9 @@ public: static const float DEFAULT_MAX_TMP_ENTITY_LIFETIME; + QByteArray computeEncryptedNonce(const QString& certID, const QString ownerKey); + bool verifyDecryptedNonce(const QString& certID, const QString& decryptedNonce); + signals: void deletingEntity(const EntityItemID& entityID); void deletingEntityPointer(EntityItem* entityID); @@ -376,9 +380,8 @@ protected: Q_INVOKABLE void startPendingTransferStatusTimer(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode); private: - QByteArray computeEncryptedNonce(const QString& certID, const QString ownerKey); - bool verifyDecryptedNonce(const QString& certID, const QString& decryptedNonce); - void sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, const QUuid& nodeToChallenge = NULL); + void sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode); + void sendChallengeOwnershipRequestPacket(const QString& certID, const QString& ownerKey, const QString& encryptedText, const SharedNodePointer& senderNode, const QUuid& nodeToChallenge); void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); }; diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index fe8868b342..ec6a0e810d 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -213,6 +213,7 @@ public: virtual int processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength, const SharedNodePointer& sourceNode) { return 0; } virtual void processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { return; } + virtual void processChallengeOwnershipReplyPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { return; } virtual void processChallengeOwnershipPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { return; } virtual bool recurseChildrenWithData() const { return true; } From f5ada4fe62b94bb1703c18c19a977a51e4ac0bf9 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 31 Oct 2017 12:31:42 -0700 Subject: [PATCH 066/183] Will it compile? --- interface/src/commerce/Wallet.h | 1 - .../ui/overlays/ContextOverlayInterface.cpp | 20 +++++++++ .../src/ui/overlays/ContextOverlayInterface.h | 3 ++ libraries/entities/src/EntityTree.cpp | 42 ++++++++++--------- libraries/entities/src/EntityTree.h | 2 +- 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/interface/src/commerce/Wallet.h b/interface/src/commerce/Wallet.h index fcc508b4e9..ed145df451 100644 --- a/interface/src/commerce/Wallet.h +++ b/interface/src/commerce/Wallet.h @@ -67,7 +67,6 @@ signals: private slots: void handleChallengeOwnershipPacket(QSharedPointer packet, SharedNodePointer sendingNode); - void handleChallengeOwnershipRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); private: QStringList _publicKeys{}; diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index cfc2156a0f..8f6a38ce09 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -71,6 +71,10 @@ ContextOverlayInterface::ContextOverlayInterface() { connect(&qApp->getOverlays(), &Overlays::hoverLeaveOverlay, this, &ContextOverlayInterface::contextOverlays_hoverLeaveOverlay); connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandler, &SelectionToSceneHandler::selectedItemsListChanged); + + auto nodeList = DependencyManager::get(); + auto& packetReceiver = nodeList->getPacketReceiver(); + packetReceiver.registerListener(PacketType::ChallengeOwnershipReply, this, "handleChallengeOwnershipReplyPacket"); } static const uint32_t MOUSE_HW_ID = 0; @@ -375,3 +379,19 @@ void ContextOverlayInterface::deletingEntity(const EntityItemID& entityID) { destroyContextOverlay(_currentEntityWithContextOverlay, PointerEvent()); } } + +void ContextOverlayInterface::handleChallengeOwnershipReplyPacket(QSharedPointer packet, SharedNodePointer sendingNode) { + int certIDByteArraySize; + int decryptedTextByteArraySize; + + packet->readPrimitive(&certIDByteArraySize); + packet->readPrimitive(&decryptedTextByteArraySize); + + QString certID(packet->read(certIDByteArraySize)); + QString decryptedText(packet->read(decryptedTextByteArraySize)); + + EntityItemID id; + bool verificationSuccess = DependencyManager::get()->getTree()->verifyDecryptedNonce(certID, decryptedText, id); + + qDebug() << "ZRF VERIFICATION STATUS:" << verificationSuccess; +} diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index a063fdde23..eedc1790d3 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -70,6 +70,9 @@ public slots: void contextOverlays_hoverLeaveEntity(const EntityItemID& entityID, const PointerEvent& event); bool contextOverlayFilterPassed(const EntityItemID& entityItemID); +private slots: + void handleChallengeOwnershipReplyPacket(QSharedPointer packet, SharedNodePointer sendingNode); + private: bool _verboseLogging { true }; bool _enabled { true }; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 71c6864b4f..dc99a7b6c9 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1206,9 +1206,7 @@ QByteArray EntityTree::computeEncryptedNonce(const QString& certID, const QStrin } } -bool EntityTree::verifyDecryptedNonce(const QString& certID, const QString& decryptedNonce) { - - EntityItemID id; +bool EntityTree::verifyDecryptedNonce(const QString& certID, const QString& decryptedNonce, EntityItemID& id) { { QReadLocker certIdMapLocker(&_entityCertificateIDMapLock); id = _entityCertificateIDMap.value(certID); @@ -1221,14 +1219,12 @@ bool EntityTree::verifyDecryptedNonce(const QString& certID, const QString& decr } bool verificationSuccess = (actualNonce == decryptedNonce); - if (!verificationSuccess) { - if (!id.isNull()) { - qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed; deleting entity" << id - << "\nActual nonce:" << actualNonce << "\nDecrypted nonce:" << decryptedNonce; - deleteEntity(id, true); - } + + if (verificationSuccess) { + qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "succeeded for entity" << id; } else { - qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "succeeded; keeping entity" << id; + qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed for entity" << id + << "\nActual nonce:" << actualNonce << "\nDecrypted nonce:" << decryptedNonce; } return verificationSuccess; @@ -1268,8 +1264,6 @@ void EntityTree::processChallengeOwnershipReplyPacket(ReceivedMessage& message, QByteArray decryptedText(message.read(decryptedTextByteArraySize)); QUuid challengingNode = QUuid::fromRfc4122(message.read(senderNodeUUIDByteArraySize)); - - auto challengeOwnershipReplyPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, certIDByteArraySize + decryptedText.length() + 2 * sizeof(int), true); @@ -1319,19 +1313,24 @@ void EntityTree::sendChallengeOwnershipRequestPacket(const QString& certID, cons // In this case, Client A is challenging Client B. Client A is inspecting a certified entity that it wants // to make sure belongs to Avatar B. - QByteArray senderNodeUUID = senderNode->getUUID().toRfc4122(); - QByteArray encryptedTextByteArray = encryptedText.toUtf8(); QByteArray certIDByteArray = certID.toUtf8(); - int certIDByteArraySize = certIDByteArray.size(); + QByteArray encryptedTextByteArray = encryptedText.toUtf8(); + QByteArray senderNodeUUID = senderNode->getUUID().toRfc4122(); + + int certIDByteArraySize = certIDByteArray.length(); + int encryptedTextByteArraySize = encryptedTextByteArray.length(); + int senderNodeUUIDSize = senderNodeUUID.length(); + auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, - certIDByteArraySize + encryptedTextByteArray.length() + senderNodeUUID.length() + 3 * sizeof(int), + certIDByteArraySize + encryptedTextByteArraySize + senderNodeUUIDSize + 3 * sizeof(int), true); challengeOwnershipPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipPacket->writePrimitive(encryptedTextByteArray.length()); - challengeOwnershipPacket->writePrimitive(senderNodeUUID.length()); + challengeOwnershipPacket->writePrimitive(encryptedTextByteArraySize); + challengeOwnershipPacket->writePrimitive(senderNodeUUIDSize); challengeOwnershipPacket->write(certIDByteArray); challengeOwnershipPacket->write(encryptedTextByteArray); challengeOwnershipPacket->write(senderNodeUUID); + nodeList->sendPacket(std::move(challengeOwnershipPacket), *(nodeList->nodeWithUUID(nodeToChallenge))); } @@ -1408,7 +1407,12 @@ void EntityTree::processChallengeOwnershipPacket(ReceivedMessage& message, const emit killChallengeOwnershipTimeoutTimer(certID); - verifyDecryptedNonce(certID, decryptedText); + EntityItemID id; + if (!verifyDecryptedNonce(certID, decryptedText, id)) { + if (!id.isNull()) { + deleteEntity(id, true); + } + } } int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength, diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 05b32676ed..3048917a49 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -276,7 +276,7 @@ public: static const float DEFAULT_MAX_TMP_ENTITY_LIFETIME; QByteArray computeEncryptedNonce(const QString& certID, const QString ownerKey); - bool verifyDecryptedNonce(const QString& certID, const QString& decryptedNonce); + bool verifyDecryptedNonce(const QString& certID, const QString& decryptedNonce, EntityItemID& id); signals: void deletingEntity(const EntityItemID& entityID); From e9c144892a6d1d3d7e9c17f799b3824097ece56d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 31 Oct 2017 12:55:41 -0700 Subject: [PATCH 067/183] Fixes --- assignment-client/src/entities/EntityServer.cpp | 10 ++++++++-- interface/src/commerce/Wallet.cpp | 2 +- interface/src/ui/overlays/ContextOverlayInterface.cpp | 3 ++- libraries/entities/src/EntityTree.cpp | 4 ++-- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 702ca88787..3a31b21f08 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -41,8 +41,14 @@ EntityServer::EntityServer(ReceivedMessage& message) : DependencyManager::set(); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); - packetReceiver.registerListenerForTypes({ PacketType::EntityAdd, PacketType::EntityEdit, PacketType::EntityErase, PacketType::EntityPhysics, PacketType::ChallengeOwnership }, - this, "handleEntityPacket"); + packetReceiver.registerListenerForTypes({ PacketType::EntityAdd, + PacketType::EntityEdit, + PacketType::EntityErase, + PacketType::EntityPhysics, + PacketType::ChallengeOwnership, + PacketType::ChallengeOwnershipRequest }, + this, + "handleEntityPacket"); connect(&_dynamicDomainVerificationTimer, &QTimer::timeout, this, &EntityServer::startDynamicDomainVerification); _dynamicDomainVerificationTimer.setSingleShot(true); diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 2389e8e39d..4414c7b206 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -734,7 +734,7 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack QByteArray encryptedText = packet->read(encryptedTextByteArraySize); QByteArray senderNodeUUID; if (challengeOriginatedFromClient) { - packet->readPrimitive(&senderNodeUUID); + senderNodeUUID = packet->read(senderNodeUUIDByteArraySize); } RSA* rsa = readKeys(keyFilePath().toStdString().c_str()); diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 8f6a38ce09..85bdef22ca 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -337,7 +337,8 @@ void ContextOverlayInterface::openInspectionCertificate() { //} } } else { - qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error(); + qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << + "More info:" << networkReply->readAll(); } networkReply->deleteLater(); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index dc99a7b6c9..ba84c45311 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1238,13 +1238,13 @@ void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message message.readPrimitive(&certIDByteArraySize); message.readPrimitive(&ownerKeyByteArraySize); - message.readPrimitive(&encryptedTextByteArraySize); message.readPrimitive(&nodeToChallengeByteArraySize); + message.readPrimitive(&encryptedTextByteArraySize); QString certID(message.read(certIDByteArraySize)); QString ownerKey(message.read(ownerKeyByteArraySize)); - QString encryptedText(message.read(encryptedTextByteArraySize)); QUuid nodeToChallenge = QUuid::fromRfc4122(message.read(nodeToChallengeByteArraySize)); + QString encryptedText(message.read(encryptedTextByteArraySize)); sendChallengeOwnershipRequestPacket(certID, ownerKey, encryptedText, sourceNode, nodeToChallenge); } From 03d2ca19b9b161393f0c718a1550bd7235ba61f0 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Tue, 31 Oct 2017 13:46:58 -0700 Subject: [PATCH 068/183] Moving consts into mode::Haze namespace. --- .../src/RenderableZoneEntityItem.cpp | 10 +- libraries/entities/src/HazePropertyGroup.h | 28 ++--- libraries/model/src/model/Haze.cpp | 21 ++-- libraries/model/src/model/Haze.h | 116 +++++++++--------- .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- libraries/render-utils/src/DrawHaze.cpp | 10 +- libraries/render-utils/src/DrawHaze.h | 36 +++--- libraries/render-utils/src/HazeStage.cpp | 10 +- libraries/render-utils/src/HazeStage.h | 18 +-- 10 files changed, 127 insertions(+), 127 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 877e245006..7c96f00ede 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -342,23 +342,23 @@ void ZoneEntityRenderer::updateHazeFromEntity(const TypedEntityPointer& entity) haze->setHazeActive(hazeMode == COMPONENT_MODE_ENABLED); haze->setAltitudeBased(_hazeProperties.getHazeAltitudeEffect()); - haze->setHazeRangeFactor(model::convertHazeRangeToHazeRangeFactor(_hazeProperties.getHazeRange())); + haze->setHazeRangeFactor(model::Haze::convertHazeRangeToHazeRangeFactor(_hazeProperties.getHazeRange())); xColor hazeColor = _hazeProperties.getHazeColor(); haze->setHazeColor(glm::vec3(hazeColor.red / 255.0, hazeColor.green / 255.0, hazeColor.blue / 255.0)); xColor hazeGlareColor = _hazeProperties.getHazeGlareColor(); haze->setHazeGlareColor(glm::vec3(hazeGlareColor.red / 255.0, hazeGlareColor.green / 255.0, hazeGlareColor.blue / 255.0)); haze->setHazeEnableGlare(_hazeProperties.getHazeEnableGlare()); - haze->setHazeGlareBlend(model::convertGlareAngleToPower(_hazeProperties.getHazeGlareAngle())); + haze->setHazeGlareBlend(model::Haze::convertGlareAngleToPower(_hazeProperties.getHazeGlareAngle())); float hazeAltitude = _hazeProperties.getHazeCeiling() - _hazeProperties.getHazeBaseRef(); - haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(hazeAltitude)); + haze->setHazeAltitudeFactor(model::Haze::convertHazeAltitudeToHazeAltitudeFactor(hazeAltitude)); haze->setHazeBaseReference(_hazeProperties.getHazeBaseRef()); haze->setHazeBackgroundBlend(_hazeProperties.getHazeBackgroundBlend()); haze->setHazeAttenuateKeyLight(_hazeProperties.getHazeAttenuateKeyLight()); - haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(_hazeProperties.getHazeKeyLightRange())); - haze->setHazeKeyLightAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(_hazeProperties.getHazeKeyLightAltitude())); + haze->setHazeKeyLightRangeFactor(model::Haze::convertHazeRangeToHazeRangeFactor(_hazeProperties.getHazeKeyLightRange())); + haze->setHazeKeyLightAltitudeFactor(model::Haze::convertHazeAltitudeToHazeAltitudeFactor(_hazeProperties.getHazeKeyLightAltitude())); haze->setZoneTransform(entity->getTransform().getMatrix()); } diff --git a/libraries/entities/src/HazePropertyGroup.h b/libraries/entities/src/HazePropertyGroup.h index 965f112af9..939391caf9 100644 --- a/libraries/entities/src/HazePropertyGroup.h +++ b/libraries/entities/src/HazePropertyGroup.h @@ -27,18 +27,18 @@ class OctreePacketData; class EntityTreeElementExtraEncodeData; class ReadBitstreamToTreeParams; -static const float initialHazeRange{ 1000.0f }; +static const float INITIAL_HAZE_RANGE{ 1000.0f }; static const xColor initialHazeGlareColorXcolor{ 255, 229, 179 }; static const xColor initialHazeColorXcolor{ 128, 154, 179 }; -static const float initialGlareAngle{ 20.0f }; +static const float INITIAL_HAZE_GLARE_ANGLE{ 20.0f }; -static const float initialHazeBaseReference{ 0.0f }; -static const float initialHazeHeight{ 200.0f }; +static const float INITIAL_HAZE_BASE_REFERENCE{ 0.0f }; +static const float INITIAL_HAZE_HEIGHT{ 200.0f }; -static const float initialHazeBackgroundBlend{ 0.0f }; +static const float INITIAL_HAZE_BACKGROUND_BLEND{ 0.0f }; -static const float initialHazeKeyLightRange{ 1000.0f }; -static const float initialHazeKeyLightAltitude{ 200.0f }; +static const float INITIAL_KEY_LIGHT_RANGE{ 1000.0f }; +static const float INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f }; class HazePropertyGroup : public PropertyGroup { public: @@ -88,24 +88,24 @@ public: bool& somethingChanged) override; // Range only parameters - DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, initialHazeRange); + DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, INITIAL_HAZE_RANGE); DEFINE_PROPERTY_REF(PROP_HAZE_COLOR, HazeColor, hazeColor, xColor, initialHazeColorXcolor); DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_COLOR, HazeGlareColor, hazeGlareColor, xColor, initialHazeGlareColorXcolor); DEFINE_PROPERTY(PROP_HAZE_ENABLE_GLARE, HazeEnableGlare, hazeEnableGlare, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_ANGLE, HazeGlareAngle, hazeGlareAngle, float, initialGlareAngle); + DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_ANGLE, HazeGlareAngle, hazeGlareAngle, float, INITIAL_HAZE_GLARE_ANGLE); // Altitude parameters DEFINE_PROPERTY(PROP_HAZE_ALTITUDE_EFFECT, HazeAltitudeEffect, hazeAltitudeEffect, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_CEILING, HazeCeiling, hazeCeiling, float, initialHazeBaseReference + initialHazeHeight); - DEFINE_PROPERTY_REF(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, initialHazeBaseReference); + DEFINE_PROPERTY_REF(PROP_HAZE_CEILING, HazeCeiling, hazeCeiling, float, INITIAL_HAZE_BASE_REFERENCE + INITIAL_HAZE_HEIGHT); + DEFINE_PROPERTY_REF(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, INITIAL_HAZE_BASE_REFERENCE); // Background (skybox) blend value - DEFINE_PROPERTY_REF(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend, hazeBackgroundBlend, float, initialHazeBackgroundBlend); + DEFINE_PROPERTY_REF(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend, hazeBackgroundBlend, float, INITIAL_HAZE_BACKGROUND_BLEND); // hazeDirectional light attenuation DEFINE_PROPERTY(PROP_HAZE_ATTENUATE_KEYLIGHT, HazeAttenuateKeyLight, hazeAttenuateKeyLight, bool, false); - DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, initialHazeKeyLightRange); - DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, initialHazeKeyLightAltitude); + DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, INITIAL_KEY_LIGHT_RANGE); + DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, INITIAL_KEY_LIGHT_ALTITUDE); }; #endif // hifi_HazePropertyGroup_h diff --git a/libraries/model/src/model/Haze.cpp b/libraries/model/src/model/Haze.cpp index 01cb32a98b..c9c73bcee9 100644 --- a/libraries/model/src/model/Haze.cpp +++ b/libraries/model/src/model/Haze.cpp @@ -14,21 +14,24 @@ using namespace model; -const float HazeInit::initialHazeRange{ 1000.0f }; -const float HazeInit::initialHazeHeight{ 200.0f }; +const float Haze::INITIAL_HAZE_RANGE{ 1000.0f }; +const float Haze::INITIAL_HAZE_HEIGHT{ 200.0f }; -const float HazeInit::initialHazeKeyLightRange{ 1000.0f }; -const float HazeInit::initialHazeKeyLightAltitude{ 200.0f }; +const float Haze::INITIAL_KEY_LIGHT_RANGE{ 1000.0f }; +const float Haze::INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f }; -const float HazeInit::initialHazeBackgroundBlend{ 0.0f }; +const float Haze::INITIAL_HAZE_BACKGROUND_BLEND{ 0.0f }; -const glm::vec3 HazeInit::initialHazeColor{ 0.5f, 0.6f, 0.7f }; // Bluish +const glm::vec3 Haze::INITIAL_HAZE_COLOR{ 0.5f, 0.6f, 0.7f }; // Bluish -const float HazeInit::initialGlareAngle{ 20.0f }; +const float Haze::INITIAL_HAZE_GLARE_ANGLE{ 20.0f }; -const glm::vec3 HazeInit::initialHazeGlareColor{ 1.0f, 0.9f, 0.7f }; +const glm::vec3 Haze::INITIAL_HAZE_GLARE_COLOR{ 1.0f, 0.9f, 0.7f }; -const float HazeInit::initialHazeBaseReference{ 0.0f }; +const float Haze::INITIAL_HAZE_BASE_REFERENCE{ 0.0f }; + +const float Haze::LOG_P_005{ logf(0.05f)}; +const float Haze::LOG_P_05{ logf(0.5f) }; Haze::Haze() { Parameters parameters; diff --git a/libraries/model/src/model/Haze.h b/libraries/model/src/model/Haze.h index b02a044459..a0cc7c3bc7 100644 --- a/libraries/model/src/model/Haze.h +++ b/libraries/model/src/model/Haze.h @@ -17,63 +17,58 @@ #include "Transform.h" #include "NumericalConstants.h" -class HazeInit { -public: - // Initial values - static const float initialHazeRange; - static const float initialHazeHeight; - - static const float initialHazeKeyLightRange; - static const float initialHazeKeyLightAltitude; - - static const float initialHazeBackgroundBlend; - - static const glm::vec3 initialHazeColor; - - static const float initialGlareAngle; - - static const glm::vec3 initialHazeGlareColor; - - static const float initialHazeBaseReference; -}; - namespace model { - const float LOG_P_005 = logf(0.05f); - const float LOG_P_05 = logf(0.5f); - - // Derivation (d is distance, b is haze coefficient, f is attenuation, solve for f = 0.05 - // f = exp(-d * b) - // ln(f) = -d * b - // b = -ln(f)/d - inline glm::vec3 convertHazeRangeToHazeRangeFactor(const glm::vec3 hazeRange) { - return glm::vec3( - -LOG_P_005 / hazeRange.x, - -LOG_P_005 / hazeRange.y, - -LOG_P_005 / hazeRange.z); - } - - // limit range and altitude to no less than 1.0 metres - inline float convertHazeRangeToHazeRangeFactor(const float hazeRange) { return -LOG_P_005 / glm::max(hazeRange, 1.0f); } - - inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeHeight) { return -LOG_P_005 / glm::max(hazeHeight, 1.0f); } - - // Derivation (s is the proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5 - // s = dot(lookAngle, sunAngle) = cos(a) - // m = pow(s, p) - // log(m) = p * log(s) - // p = log(m) / log(s) - // limit to 0.1 degrees - inline float convertGlareAngleToPower(const float hazeGlareAngle) { - const float GLARE_ANGLE_LIMIT = 0.1f; - return LOG_P_05 / logf(cosf(RADIANS_PER_DEGREE * glm::max(GLARE_ANGLE_LIMIT, hazeGlareAngle))); - } - // Haze range is defined here as the range the visibility is reduced by 95% // Haze altitude is defined here as the altitude (above 0) that the haze is reduced by 95% class Haze { public: - using UniformBufferView = gpu::BufferView; + // Initial values + static const float INITIAL_HAZE_RANGE; + static const float INITIAL_HAZE_HEIGHT; + + static const float INITIAL_KEY_LIGHT_RANGE; + static const float INITIAL_KEY_LIGHT_ALTITUDE; + + static const float INITIAL_HAZE_BACKGROUND_BLEND; + + static const glm::vec3 INITIAL_HAZE_COLOR; + + static const float INITIAL_HAZE_GLARE_ANGLE; + + static const glm::vec3 INITIAL_HAZE_GLARE_COLOR; + + static const float INITIAL_HAZE_BASE_REFERENCE; + + static const float LOG_P_005; + static const float LOG_P_05; + + // Derivation (d is distance, b is haze coefficient, f is attenuation, solve for f = 0.05 + // f = exp(-d * b) + // ln(f) = -d * b + // b = -ln(f)/d + static inline glm::vec3 convertHazeRangeToHazeRangeFactor(const glm::vec3 hazeRange) { + return glm::vec3( + -LOG_P_005 / hazeRange.x, + -LOG_P_005 / hazeRange.y, + -LOG_P_005 / hazeRange.z); + } + + // limit range and altitude to no less than 1.0 metres + static inline float convertHazeRangeToHazeRangeFactor(const float hazeRange) { return -LOG_P_005 / glm::max(hazeRange, 1.0f); } + + static inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeHeight) { return -LOG_P_005 / glm::max(hazeHeight, 1.0f); } + + // Derivation (s is the proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5 + // s = dot(lookAngle, sunAngle) = cos(a) + // m = pow(s, p) + // log(m) = p * log(s) + // p = log(m) / log(s) + // limit to 0.1 degrees + static inline float convertGlareAngleToPower(const float hazeGlareAngle) { + const float GLARE_ANGLE_LIMIT = 0.1f; + return LOG_P_05 / logf(cosf(RADIANS_PER_DEGREE * glm::max(GLARE_ANGLE_LIMIT, hazeGlareAngle))); + } Haze(); @@ -99,17 +94,18 @@ namespace model { void setZoneTransform(const glm::mat4& zoneTransform); + using UniformBufferView = gpu::BufferView; UniformBufferView getHazeParametersBuffer() const { return _hazeParametersBuffer; } protected: class Parameters { public: // DO NOT CHANGE ORDER HERE WITHOUT UNDERSTANDING THE std140 LAYOUT - glm::vec3 hazeColor{ HazeInit::initialHazeColor }; - float hazeGlareBlend{ convertGlareAngleToPower(HazeInit::initialGlareAngle) }; + glm::vec3 hazeColor{ INITIAL_HAZE_COLOR }; + float hazeGlareBlend{ convertGlareAngleToPower(INITIAL_HAZE_GLARE_ANGLE) }; - glm::vec3 hazeGlareColor{ HazeInit::initialHazeGlareColor }; - float hazeBaseReference{ HazeInit::initialHazeBaseReference }; + glm::vec3 hazeGlareColor{ INITIAL_HAZE_GLARE_COLOR }; + float hazeBaseReference{ INITIAL_HAZE_BASE_REFERENCE }; glm::vec3 colorModulationFactor; int hazeMode{ 0 }; // bit 0 - set to activate haze attenuation of fragment color @@ -120,14 +116,14 @@ namespace model { glm::mat4 zoneTransform; // Amount of background (skybox) to display, overriding the haze effect for the background - float hazeBackgroundBlend{ HazeInit::initialHazeBackgroundBlend }; + float hazeBackgroundBlend{ INITIAL_HAZE_BACKGROUND_BLEND }; // The haze attenuation exponents used by both fragment and directional light attenuation - float hazeRangeFactor{ convertHazeRangeToHazeRangeFactor(HazeInit::initialHazeRange) }; - float hazeHeightFactor{ convertHazeAltitudeToHazeAltitudeFactor(HazeInit::initialHazeHeight) }; + float hazeRangeFactor{ convertHazeRangeToHazeRangeFactor(INITIAL_HAZE_RANGE) }; + float hazeHeightFactor{ convertHazeAltitudeToHazeAltitudeFactor(INITIAL_HAZE_HEIGHT) }; - float hazeKeyLightRangeFactor{ convertHazeRangeToHazeRangeFactor(HazeInit::initialHazeKeyLightRange) }; - float hazeKeyLightAltitudeFactor{ convertHazeAltitudeToHazeAltitudeFactor(HazeInit::initialHazeKeyLightAltitude) }; + float hazeKeyLightRangeFactor{ convertHazeRangeToHazeRangeFactor(INITIAL_KEY_LIGHT_RANGE) }; + float hazeKeyLightAltitudeFactor{ convertHazeAltitudeToHazeAltitudeFactor(INITIAL_KEY_LIGHT_ALTITUDE) }; Parameters() {} }; diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 09ee41b31d..9a98393fa1 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -30,7 +30,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::HasDynamicOwnershipTests); + return static_cast(EntityVersion::HazeEffect); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::JSONFilterWithFamilyTree); diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 049cb0f1a8..e00b4139c3 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -196,7 +196,8 @@ QDebug operator<<(QDebug debug, const PacketType& type); enum class EntityVersion : PacketVersion { StrokeColorProperty = 77, - HasDynamicOwnershipTests + HasDynamicOwnershipTests, + HazeEffect }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index 3be74da26a..7cf07d8f33 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -83,7 +83,7 @@ MakeHaze::MakeHaze() { void MakeHaze::configure(const Config& config) { _haze->setHazeColor(config.hazeColor); - _haze->setHazeGlareBlend(model::convertGlareAngleToPower(config.hazeGlareAngle)); + _haze->setHazeGlareBlend(model::Haze::convertGlareAngleToPower(config.hazeGlareAngle)); _haze->setHazeGlareColor(config.hazeGlareColor); _haze->setHazeBaseReference(config.hazeBaseReference); @@ -94,11 +94,11 @@ void MakeHaze::configure(const Config& config) { _haze->setModulateColorActive(config.isModulateColorActive); _haze->setHazeEnableGlare(config.isHazeEnableGlare); - _haze->setHazeRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeRange)); - _haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight)); + _haze->setHazeRangeFactor(model::Haze::convertHazeRangeToHazeRangeFactor(config.hazeRange)); + _haze->setHazeAltitudeFactor(model::Haze::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight)); - _haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange)); - _haze->setHazeKeyLightAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude)); + _haze->setHazeKeyLightRangeFactor(model::Haze::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange)); + _haze->setHazeKeyLightAltitudeFactor(model::Haze::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude)); _haze->setHazeBackgroundBlend(config.hazeBackgroundBlend); } diff --git a/libraries/render-utils/src/DrawHaze.h b/libraries/render-utils/src/DrawHaze.h index c460d38bf1..f158daa0c6 100644 --- a/libraries/render-utils/src/DrawHaze.h +++ b/libraries/render-utils/src/DrawHaze.h @@ -51,11 +51,11 @@ class MakeHazeConfig : public render::Job::Config { public: MakeHazeConfig() : render::Job::Config() {} - glm::vec3 hazeColor{ HazeInit::initialHazeColor }; - float hazeGlareAngle{ HazeInit::initialGlareAngle }; + glm::vec3 hazeColor{ model::Haze::INITIAL_HAZE_COLOR }; + float hazeGlareAngle{ model::Haze::INITIAL_HAZE_GLARE_ANGLE }; - glm::vec3 hazeGlareColor{ HazeInit::initialHazeGlareColor }; - float hazeBaseReference{ HazeInit::initialHazeBaseReference }; + glm::vec3 hazeGlareColor{ model::Haze::INITIAL_HAZE_GLARE_COLOR }; + float hazeBaseReference{ model::Haze::INITIAL_HAZE_BASE_REFERENCE }; bool isHazeActive{ false }; bool isAltitudeBased{ false }; @@ -63,13 +63,13 @@ public: bool isModulateColorActive{ false }; bool isHazeEnableGlare{ false }; - float hazeRange{ HazeInit::initialHazeRange }; - float hazeHeight{ HazeInit::initialHazeHeight }; + float hazeRange{ model::Haze::INITIAL_HAZE_RANGE }; + float hazeHeight{ model::Haze::INITIAL_HAZE_HEIGHT }; - float hazeKeyLightRange{ HazeInit::initialHazeKeyLightRange }; - float hazeKeyLightAltitude{ HazeInit::initialHazeKeyLightAltitude }; + float hazeKeyLightRange{ model::Haze::INITIAL_KEY_LIGHT_RANGE }; + float hazeKeyLightAltitude{ model::Haze::INITIAL_KEY_LIGHT_ALTITUDE }; - float hazeBackgroundBlend{ HazeInit::initialHazeBackgroundBlend }; + float hazeBackgroundBlend{ model::Haze::INITIAL_HAZE_BACKGROUND_BLEND }; public slots: void setHazeColor(const glm::vec3 value) { hazeColor = value; emit dirty(); } @@ -115,11 +115,11 @@ public: HazeConfig() : render::Job::Config(true) {} // attributes - glm::vec3 hazeColor{ HazeInit::initialHazeColor }; - float hazeGlareAngle{ HazeInit::initialGlareAngle }; + glm::vec3 hazeColor{ model::Haze::INITIAL_HAZE_COLOR }; + float hazeGlareAngle{ model::Haze::INITIAL_HAZE_GLARE_ANGLE }; - glm::vec3 hazeGlareColor{ HazeInit::initialHazeGlareColor }; - float hazeBaseReference{ HazeInit::initialHazeBaseReference }; + glm::vec3 hazeGlareColor{ model::Haze::INITIAL_HAZE_GLARE_COLOR }; + float hazeBaseReference{ model::Haze::INITIAL_HAZE_BASE_REFERENCE }; bool isHazeActive{ false }; // Setting this to true will set haze to on bool isAltitudeBased{ false }; @@ -127,13 +127,13 @@ public: bool isModulateColorActive{ false }; bool isHazeEnableGlare{ false }; - float hazeRange{ HazeInit::initialHazeRange }; - float hazeHeight{ HazeInit::initialHazeHeight }; + float hazeRange{ model::Haze::INITIAL_HAZE_RANGE }; + float hazeHeight{ model::Haze::INITIAL_HAZE_HEIGHT }; - float hazeKeyLightRange{ HazeInit::initialHazeKeyLightRange }; - float hazeKeyLightAltitude{ HazeInit::initialHazeKeyLightAltitude }; + float hazeKeyLightRange{ model::Haze::INITIAL_KEY_LIGHT_RANGE }; + float hazeKeyLightAltitude{ model::Haze::INITIAL_KEY_LIGHT_ALTITUDE }; - float hazeBackgroundBlend{ HazeInit::initialHazeBackgroundBlend }; + float hazeBackgroundBlend{ model::Haze::INITIAL_HAZE_BACKGROUND_BLEND }; // methods void setHazeColor(const glm::vec3 value); diff --git a/libraries/render-utils/src/HazeStage.cpp b/libraries/render-utils/src/HazeStage.cpp index c9e6ef90cb..7a12ee3c8a 100644 --- a/libraries/render-utils/src/HazeStage.cpp +++ b/libraries/render-utils/src/HazeStage.cpp @@ -21,7 +21,7 @@ FetchHazeStage::FetchHazeStage() { void FetchHazeStage::configure(const Config& config) { _haze->setHazeColor(config.hazeColor); - _haze->setHazeGlareBlend(model::convertGlareAngleToPower(config.hazeGlareAngle)); + _haze->setHazeGlareBlend(model::Haze::convertGlareAngleToPower(config.hazeGlareAngle)); _haze->setHazeGlareColor(config.hazeGlareColor); _haze->setHazeBaseReference(config.hazeBaseReference); @@ -32,11 +32,11 @@ void FetchHazeStage::configure(const Config& config) { _haze->setModulateColorActive(config.isModulateColorActive); _haze->setHazeEnableGlare(config.isHazeEnableGlare); - _haze->setHazeRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeRange)); - _haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight)); + _haze->setHazeRangeFactor(model::Haze::convertHazeRangeToHazeRangeFactor(config.hazeRange)); + _haze->setHazeAltitudeFactor(model::Haze::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight)); - _haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange)); - _haze->setHazeKeyLightAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude)); + _haze->setHazeKeyLightRangeFactor(model::Haze::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange)); + _haze->setHazeKeyLightAltitudeFactor(model::Haze::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude)); _haze->setHazeBackgroundBlend(config.hazeBackgroundBlend); } diff --git a/libraries/render-utils/src/HazeStage.h b/libraries/render-utils/src/HazeStage.h index ac5a8dd6f5..102f299d8f 100644 --- a/libraries/render-utils/src/HazeStage.h +++ b/libraries/render-utils/src/HazeStage.h @@ -106,11 +106,11 @@ class FetchHazeConfig : public render::Job::Config { public: FetchHazeConfig() : render::Job::Config() {} - glm::vec3 hazeColor{ HazeInit::initialHazeColor }; - float hazeGlareAngle{ HazeInit::initialGlareAngle }; + glm::vec3 hazeColor{ model::Haze::INITIAL_HAZE_COLOR }; + float hazeGlareAngle{ model::Haze::INITIAL_HAZE_GLARE_ANGLE }; - glm::vec3 hazeGlareColor{ HazeInit::initialHazeGlareColor }; - float hazeBaseReference{ HazeInit::initialHazeBaseReference }; + glm::vec3 hazeGlareColor{ model::Haze::INITIAL_HAZE_GLARE_COLOR }; + float hazeBaseReference{ model::Haze::INITIAL_HAZE_BASE_REFERENCE }; bool isHazeActive{ false }; bool isAltitudeBased{ false }; @@ -118,13 +118,13 @@ public: bool isModulateColorActive{ false }; bool isHazeEnableGlare{ false }; - float hazeRange{ HazeInit::initialHazeRange }; - float hazeHeight{ HazeInit::initialHazeHeight }; + float hazeRange{ model::Haze::INITIAL_HAZE_RANGE }; + float hazeHeight{ model::Haze::INITIAL_HAZE_HEIGHT }; - float hazeKeyLightRange{ HazeInit::initialHazeKeyLightRange }; - float hazeKeyLightAltitude{ HazeInit::initialHazeKeyLightAltitude }; + float hazeKeyLightRange{ model::Haze::INITIAL_KEY_LIGHT_RANGE }; + float hazeKeyLightAltitude{ model::Haze::INITIAL_KEY_LIGHT_ALTITUDE }; - float hazeBackgroundBlend{ HazeInit::initialHazeBackgroundBlend }; + float hazeBackgroundBlend{ model::Haze::INITIAL_HAZE_BACKGROUND_BLEND }; public slots: void setHazeColor(const glm::vec3 value) { hazeColor = value; emit dirty(); } From d49e281fabfffeb6fede7d7e0dff13d03f3981cf Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 31 Oct 2017 14:12:30 -0700 Subject: [PATCH 069/183] Add RSA error handling --- interface/src/commerce/Wallet.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 4414c7b206..acc0b08afb 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -740,6 +740,7 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack RSA* rsa = readKeys(keyFilePath().toStdString().c_str()); if (rsa) { + ERR_clear_error(); const int decryptionStatus = RSA_private_decrypt(encryptedTextByteArraySize, reinterpret_cast(encryptedText.constData()), decryptedText, @@ -784,6 +785,11 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack } } else { qCDebug(commerce) << "During entity ownership challenge, decrypting the encrypted text failed."; + long error = ERR_get_error(); + if (error != 0) { + const char* error_str = ERR_error_string(error, NULL); + qCWarning(entities) << "RSA error:" << error_str; + } } } else { qCDebug(commerce) << "During entity ownership challenge, creating the RSA object failed."; From f9a410de873679b5371ebe6d8f6039a6de6d62d9 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 31 Oct 2017 14:53:37 -0700 Subject: [PATCH 070/183] Change 'GET' to 'BUY' when hovering over costed items --- scripts/system/html/js/marketplacesInject.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 8deb5c0bbd..4b127baef8 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -290,11 +290,17 @@ } }); - // change pricing to GET on button hover + // change pricing to GET/BUY on button hover $('body').on('mouseenter', '#price-or-edit .price', function () { var $this = $(this); $this.data('initialHtml', $this.html()); - $this.text('GET'); + + var cost = $(this).parent().siblings().text(); + if (parseInt(cost) > 0) { + $this.text('BUY'); + } else { + $this.text('GET'); + } }); $('body').on('mouseleave', '#price-or-edit .price', function () { From 93308dfcd3c70e6799ff6fc482f9e661e1584c15 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 31 Oct 2017 15:59:18 -0700 Subject: [PATCH 071/183] Why did I think this would work before? --- interface/src/commerce/Wallet.cpp | 1 + .../ui/overlays/ContextOverlayInterface.cpp | 124 +++++++++--------- libraries/entities/src/EntityTree.cpp | 18 +-- libraries/entities/src/EntityTree.h | 2 +- 4 files changed, 73 insertions(+), 72 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index acc0b08afb..d0ef3fcaae 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -732,6 +732,7 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack QByteArray certID = packet->read(certIDByteArraySize); QByteArray encryptedText = packet->read(encryptedTextByteArraySize); + qDebug() << "ZRF encryptedText Inbound:" << QString(encryptedText); QByteArray senderNodeUUID; if (challengeOriginatedFromClient) { senderNodeUUID = packet->read(senderNodeUUIDByteArraySize); diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 85bdef22ca..eecf93745a 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -277,74 +277,78 @@ void ContextOverlayInterface::openInspectionCertificate() { // ZRF FIXME: Don't challenge ownership of avatar entities that I own if (entityProperties.getClientOnly()/* && nodeToChallenge != nodeList->getSessionUUID()*/) { - SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer); + // ZRF FIXME! + //if (entityProperties.verifyStaticCertificateProperties()) { + if (true) { + SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer); - if (entityServer) { - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkRequest networkRequest; - networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); - networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL; - requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer"); - QJsonObject request; - request["certificate_id"] = entityProperties.getCertificateID(); - networkRequest.setUrl(requestURL); + if (entityServer) { + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkRequest networkRequest; + networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL; + requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer"); + QJsonObject request; + request["certificate_id"] = entityProperties.getCertificateID(); + networkRequest.setUrl(requestURL); - QNetworkReply* networkReply = NULL; - networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson()); + QNetworkReply* networkReply = NULL; + networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson()); - connect(networkReply, &QNetworkReply::finished, [=]() { - QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object(); - jsonObject = jsonObject["data"].toObject(); + connect(networkReply, &QNetworkReply::finished, [=]() { + QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object(); + jsonObject = jsonObject["data"].toObject(); - if (networkReply->error() == QNetworkReply::NoError) { - if (!jsonObject["invalid_reason"].toString().isEmpty()) { - qCDebug(entities) << "invalid_reason not empty"; - } else if (jsonObject["transfer_status"].toArray().first().toString() == "failed") { - qCDebug(entities) << "'transfer_status' is 'failed'";; - } else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") { - qCDebug(entities) << "'transfer_status' is 'pending'";; + if (networkReply->error() == QNetworkReply::NoError) { + if (!jsonObject["invalid_reason"].toString().isEmpty()) { + qCDebug(entities) << "invalid_reason not empty"; + } else if (jsonObject["transfer_status"].toArray().first().toString() == "failed") { + qCDebug(entities) << "'transfer_status' is 'failed'";; + } else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") { + qCDebug(entities) << "'transfer_status' is 'pending'";; + } else { + QString ownerKey = jsonObject["transfer_recipient_key"].toString(); + + QByteArray certID = entityProperties.getCertificateID().toUtf8(); + QByteArray encryptedText = DependencyManager::get()->getTree()->computeEncryptedNonce(certID, ownerKey); + QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122(); + + int certIDByteArraySize = certID.length(); + int encryptedTextByteArraySize = encryptedText.length(); + int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length(); + + auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, + certIDByteArraySize + encryptedTextByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int), + true); + challengeOwnershipPacket->writePrimitive(certIDByteArraySize); + challengeOwnershipPacket->writePrimitive(encryptedTextByteArraySize); + challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize); + challengeOwnershipPacket->write(certID); + challengeOwnershipPacket->write(encryptedText); + challengeOwnershipPacket->write(nodeToChallengeByteArray); + nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer); + + // Kickoff a 10-second timeout timer that marks the cert if we don't get an ownership response in time + //if (thread() != QThread::currentThread()) { + // QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer", Q_ARG(const EntityItemID&, entityItemID)); + // return; + //} else { + // startChallengeOwnershipTimer(entityItemID); + //} + } } else { - QByteArray certID = entityProperties.getCertificateID().toUtf8(); - QByteArray ownerKey = jsonObject["transfer_recipient_key"].toString().toUtf8(); - QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122(); - QByteArray encryptedText = DependencyManager::get()->getTree()->computeEncryptedNonce(certID, ownerKey); - - int certIDByteArraySize = certID.length(); - int ownerKeyByteArraySize = ownerKey.length(); - int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length(); - int encryptedTextByteArraySize = encryptedText.length(); - - auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, - certIDByteArraySize + ownerKeyByteArraySize + nodeToChallengeByteArraySize + encryptedTextByteArraySize + 4 * sizeof(int), - true); - challengeOwnershipPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipPacket->writePrimitive(ownerKeyByteArraySize); - challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize); - challengeOwnershipPacket->writePrimitive(encryptedTextByteArraySize); - challengeOwnershipPacket->write(certID); - challengeOwnershipPacket->write(ownerKey); - challengeOwnershipPacket->write(nodeToChallengeByteArray); - challengeOwnershipPacket->write(encryptedText); - nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer); - - // Kickoff a 10-second timeout timer that marks the cert if we don't get an ownership response in time - //if (thread() != QThread::currentThread()) { - // QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer", Q_ARG(const EntityItemID&, entityItemID)); - // return; - //} else { - // startChallengeOwnershipTimer(entityItemID); - //} + qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << + "More info:" << networkReply->readAll(); } - } else { - qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << - "More info:" << networkReply->readAll(); - } - networkReply->deleteLater(); - }); + networkReply->deleteLater(); + }); + } else { + qCWarning(context_overlay) << "Couldn't get Entity Server!"; + } } else { - qCWarning(context_overlay) << "Couldn't get Entity Server!"; + qCDebug(context_overlay) << "Entity" << _currentEntityWithContextOverlay << "failed static certificate verification!"; } } } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index ba84c45311..1cf9fdfb26 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1153,8 +1153,8 @@ void EntityTree::startChallengeOwnershipTimer(const EntityItemID& entityItemID) _challengeOwnershipTimeoutTimer->deleteLater(); } }); -_challengeOwnershipTimeoutTimer->setSingleShot(true); -_challengeOwnershipTimeoutTimer->start(5000); + _challengeOwnershipTimeoutTimer->setSingleShot(true); + _challengeOwnershipTimeoutTimer->start(5000); } void EntityTree::startPendingTransferStatusTimer(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode) { @@ -1195,7 +1195,6 @@ QByteArray EntityTree::computeEncryptedNonce(const QString& certID, const QStrin QWriteLocker locker(&_certNonceMapLock); _certNonceMap.insert(certID, nonce); - qCDebug(entities) << "Challenging ownership of Cert ID" << certID << "by encrypting and sending nonce" << nonce << "to owner."; return encryptedText; } else { @@ -1232,21 +1231,18 @@ bool EntityTree::verifyDecryptedNonce(const QString& certID, const QString& decr void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { int certIDByteArraySize; - int ownerKeyByteArraySize; int encryptedTextByteArraySize; int nodeToChallengeByteArraySize; message.readPrimitive(&certIDByteArraySize); - message.readPrimitive(&ownerKeyByteArraySize); - message.readPrimitive(&nodeToChallengeByteArraySize); message.readPrimitive(&encryptedTextByteArraySize); + message.readPrimitive(&nodeToChallengeByteArraySize); QString certID(message.read(certIDByteArraySize)); - QString ownerKey(message.read(ownerKeyByteArraySize)); - QUuid nodeToChallenge = QUuid::fromRfc4122(message.read(nodeToChallengeByteArraySize)); QString encryptedText(message.read(encryptedTextByteArraySize)); + QUuid nodeToChallenge = QUuid::fromRfc4122(message.read(nodeToChallengeByteArraySize)); - sendChallengeOwnershipRequestPacket(certID, ownerKey, encryptedText, sourceNode, nodeToChallenge); + sendChallengeOwnershipRequestPacket(certID, encryptedText, sourceNode, nodeToChallenge); } void EntityTree::processChallengeOwnershipReplyPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { @@ -1285,6 +1281,7 @@ void EntityTree::sendChallengeOwnershipPacket(const QString& certID, const QStri qCDebug(entities) << "CRITICAL ERROR: Couldn't compute encrypted nonce. Deleting entity..."; deleteEntity(entityItemID, true); } else { + qCDebug(entities) << "Challenging ownership of Cert ID" << certID; // 2. Send the encrypted text to the rezzing avatar's node QByteArray certIDByteArray = certID.toUtf8(); int certIDByteArraySize = certIDByteArray.size(); @@ -1307,8 +1304,7 @@ void EntityTree::sendChallengeOwnershipPacket(const QString& certID, const QStri } } -void EntityTree::sendChallengeOwnershipRequestPacket(const QString& certID, const QString& ownerKey, const QString& encryptedText, const SharedNodePointer& senderNode, const QUuid& nodeToChallenge) { - // 1. Encrypt a nonce with the owner's public key +void EntityTree::sendChallengeOwnershipRequestPacket(const QString& certID, const QString& encryptedText, const SharedNodePointer& senderNode, const QUuid& nodeToChallenge) { auto nodeList = DependencyManager::get(); // In this case, Client A is challenging Client B. Client A is inspecting a certified entity that it wants diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 3048917a49..5eb5d5b569 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -381,7 +381,7 @@ protected: private: void sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode); - void sendChallengeOwnershipRequestPacket(const QString& certID, const QString& ownerKey, const QString& encryptedText, const SharedNodePointer& senderNode, const QUuid& nodeToChallenge); + void sendChallengeOwnershipRequestPacket(const QString& certID, const QString& encryptedText, const SharedNodePointer& senderNode, const QUuid& nodeToChallenge); void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); }; From 328fc29bc595faa62ef1ae69604d6fabebca7ece Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 1 Nov 2017 17:01:19 +1300 Subject: [PATCH 072/183] Fix serverScripts not being able to see entities in parent/child tree --- .../src/entities/EntityTreeSendThread.cpp | 14 +++++++++----- .../src/entities/EntityTreeSendThread.h | 3 ++- libraries/entities/src/DiffTraversal.cpp | 5 +++-- libraries/entities/src/DiffTraversal.h | 3 ++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index 03014bae6a..e96a9dc667 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -96,7 +96,7 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O nodeData->copyCurrentViewFrustum(viewFrustum); EntityTreeElementPointer root = std::dynamic_pointer_cast(_myServer->getOctree()->getRoot()); int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST); - startNewTraversal(viewFrustum, root, lodLevelOffset, nodeData->getUsesFrustum()); + startNewTraversal(viewFrustum, root, lodLevelOffset, nodeData->getUsesFrustum(), isFullScene); // When the viewFrustum changed the sort order may be incorrect, so we re-sort // and also use the opportunity to cull anything no longer in view @@ -175,7 +175,7 @@ bool EntityTreeSendThread::addAncestorsToExtraFlaggedEntities(const QUuid& filte return parentWasNew || ancestorsWereNew; } - // since we didn't have a parent niether of our parents or ancestors could be new additions + // since we didn't have a parent, neither of our parents or ancestors could be new additions return false; } @@ -204,8 +204,10 @@ bool EntityTreeSendThread::addDescendantsToExtraFlaggedEntities(const QUuid& fil return hasNewChild || hasNewDescendants; } -void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum) { - DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset, usesViewFrustum); +void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root, int32_t lodLevelOffset, + bool usesViewFrustum, bool isFullScene) { + + DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset, usesViewFrustum, isFullScene); // there are three types of traversal: // // (1) FirstTime = at login --> find everything in view @@ -423,12 +425,14 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream uint64_t sendTime = usecTimestampNow(); auto nodeData = static_cast(params.nodeData); nodeData->stats.encodeStarted(); + auto entityNodeData = static_cast(_node.toStrongRef()->getLinkedData()); while(!_sendQueue.empty()) { PrioritizedEntity queuedItem = _sendQueue.top(); EntityItemPointer entity = queuedItem.getEntity(); if (entity) { // Only send entities that match the jsonFilters, but keep track of everything we've tried to send so we don't try to send it again - if (entity->matchesJSONFilters(jsonFilters)) { + if (entity->matchesJSONFilters(jsonFilters) || entityNodeData->isEntityFlaggedAsExtra(entity->getID())) { + entityNodeData->insertSentFilteredEntity(entity->getID()); OctreeElement::AppendState appendEntityState = entity->appendEntityData(&_packetData, params, _extraEncodeData); if (appendEntityState != OctreeElement::COMPLETED) { diff --git a/assignment-client/src/entities/EntityTreeSendThread.h b/assignment-client/src/entities/EntityTreeSendThread.h index 49901491ff..1781de9890 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.h +++ b/assignment-client/src/entities/EntityTreeSendThread.h @@ -38,7 +38,8 @@ private: bool addAncestorsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData); bool addDescendantsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData); - void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum); + void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, + bool usesViewFrustum, bool isFullScene); bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override; void preDistributionProcessing() override; diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp index 2f9423daa3..9b16ee90bf 100644 --- a/libraries/entities/src/DiffTraversal.cpp +++ b/libraries/entities/src/DiffTraversal.cpp @@ -142,7 +142,8 @@ DiffTraversal::DiffTraversal() { _path.reserve(MIN_PATH_DEPTH); } -DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum) { +DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, + int32_t lodLevelOffset, bool usesViewFrustum, bool isFullScene) { assert(root); // there are three types of traversal: // @@ -163,7 +164,7 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFr Type type; // If usesViewFrustum changes, treat it as a First traversal - if (_completedView.startTime == 0 || _currentView.usesViewFrustum != _completedView.usesViewFrustum) { + if (_completedView.startTime == 0 || _currentView.usesViewFrustum != _completedView.usesViewFrustum || isFullScene) { type = Type::First; _currentView.viewFrustum = viewFrustum; _currentView.lodScaleFactor = lodScaleFactor; diff --git a/libraries/entities/src/DiffTraversal.h b/libraries/entities/src/DiffTraversal.h index c26e48ae5f..becf322fd5 100644 --- a/libraries/entities/src/DiffTraversal.h +++ b/libraries/entities/src/DiffTraversal.h @@ -57,7 +57,8 @@ public: DiffTraversal(); - Type prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum); + Type prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, + bool usesViewFrustum, bool isFullScene); const ViewFrustum& getCurrentView() const { return _currentView.viewFrustum; } const ViewFrustum& getCompletedView() const { return _completedView.viewFrustum; } From da63e85699c62271145962f7a1b1d95ab87a70f4 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 1 Nov 2017 09:17:04 -0700 Subject: [PATCH 073/183] Bug 8270 fixed --- libraries/animation/src/AnimClip.h | 1 + libraries/animation/src/Rig.cpp | 21 +++++++++++++++++++ libraries/animation/src/Rig.h | 2 ++ .../src/avatars-renderer/Avatar.cpp | 12 +++++++++++ .../src/avatars-renderer/Avatar.h | 3 +++ 5 files changed, 39 insertions(+) diff --git a/libraries/animation/src/AnimClip.h b/libraries/animation/src/AnimClip.h index c7e7ebf3ee..7121cff356 100644 --- a/libraries/animation/src/AnimClip.h +++ b/libraries/animation/src/AnimClip.h @@ -54,6 +54,7 @@ public: void setMirrorFlag(bool mirrorFlag) { _mirrorFlag = mirrorFlag; } void loadURL(const QString& url); + const QString& getURL() { return _url; } protected: virtual void setCurrentFrameInternal(float frame) override; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 0f2bce5ca4..8293cb91f4 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -144,6 +144,27 @@ QStringList Rig::getAnimationRoles() const { } } +QVector> Rig::getAnimationClips() const { + QVector> list; + if (_animNode) { + _animNode->traverse([&](AnimNode::Pointer node) { + // only report clip nodes as valid roles. + auto clipNode = std::dynamic_pointer_cast(node); + if (clipNode) { + // filter out the userAnims, they are for internal use only. + if (!clipNode->getID().startsWith("userAnim")) { + list.append(clipNode); + } + } + return true; + }); + return list; + } + else { + return list; + } +} + void Rig::overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame) { if (_animNode) { AnimNode::Pointer node = _animNode->findByName(role); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 18d49c5f1e..9290b41513 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -21,6 +21,7 @@ #include #include +#include "AnimClip.h" #include "AnimNode.h" #include "AnimNodeLoader.h" #include "SimpleMovingAverage.h" @@ -107,6 +108,7 @@ public: QStringList getAnimationRoles() const; void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame); void restoreRoleAnimation(const QString& role); + QVector> getAnimationClips() const; void initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset); void reset(const FBXGeometry& geometry); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 142e57c9e5..0d2e730a1a 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -139,6 +139,7 @@ Avatar::~Avatar() { void Avatar::init() { getHead()->init(); _skeletonModel->init(); + connect(&_skeletonModel->getRig(), &Rig::onLoadComplete, this, &Avatar::restoreAnimations); _initialized = true; } @@ -198,6 +199,16 @@ void Avatar::setTargetScale(float targetScale) { } } +void Avatar::restoreAnimations() { + for (int i = 0; i < _animationCache.size(); i++) { + auto clip = _animationCache[i]; + const float REFERENCE_FRAMES_PER_SECOND = 30.0f; + float fps = REFERENCE_FRAMES_PER_SECOND / clip->getTimeScale(); + qDebug() << clip->getID() << " " << clip->getURL() << " " << fps << " " << clip->getLoopFlag() << " " << clip->getStartFrame() << " " << clip->getEndFrame(); + _skeletonModel->getRig().overrideRoleAnimation(clip->getID(), clip->getURL(), fps, clip->getLoopFlag(), clip->getStartFrame(), clip->getEndFrame()); + } +} + void Avatar::updateAvatarEntities() { PerformanceTimer perfTimer("attachments"); // - if queueEditEntityMessage sees clientOnly flag it does _myAvatar->updateAvatarEntity() @@ -1177,6 +1188,7 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { } void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { + _animationCache = _skeletonModel->getRig().getAnimationClips(); AvatarData::setSkeletonModelURL(skeletonModelURL); if (QThread::currentThread() == thread()) { _skeletonModel->setURL(_skeletonModelURL); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index a5ec307c50..09e1451aa9 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -274,6 +274,7 @@ public slots: glm::vec3 getRightPalmPosition() const; glm::quat getRightPalmRotation() const; + void restoreAnimations(); void setModelURLFinished(bool success); protected: @@ -377,6 +378,8 @@ private: float _displayNameTargetAlpha { 1.0f }; float _displayNameAlpha { 1.0f }; + + QVector> _animationCache; }; #endif // hifi_Avatar_h From 8a6a744099ed41a56afd89f2628a6f2e4aa45300 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 1 Nov 2017 10:46:13 -0700 Subject: [PATCH 074/183] It's working --- .../src/entities/EntityServer.cpp | 3 +- interface/src/commerce/Ledger.h | 8 ++++++ interface/src/commerce/Wallet.cpp | 15 +++++----- .../ui/overlays/ContextOverlayInterface.cpp | 11 +++++++- libraries/entities/src/EntityTree.cpp | 28 +++++++++---------- libraries/entities/src/EntityTree.h | 2 +- 6 files changed, 41 insertions(+), 26 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 3a31b21f08..995a5bad27 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -46,7 +46,8 @@ EntityServer::EntityServer(ReceivedMessage& message) : PacketType::EntityErase, PacketType::EntityPhysics, PacketType::ChallengeOwnership, - PacketType::ChallengeOwnershipRequest }, + PacketType::ChallengeOwnershipRequest, + PacketType::ChallengeOwnershipReply }, this, "handleEntityPacket"); diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index ae001010f0..75f6fb1ba8 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -65,6 +65,14 @@ public slots: void certificateInfoSuccess(QNetworkReply& reply); void certificateInfoFailure(QNetworkReply& reply); + void updateCertificateStatus(const QString& certID, uint certStatus); + enum CertificateStatus { + CERTIFICATE_STATUS_UNKNOWN = 0, + CERTIFICATE_STATUS_VERIFICATION_SUCCESS, + CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED, + CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED, + }; + private: QJsonObject apiResponse(const QString& label, QNetworkReply& reply); QJsonObject failResponse(const QString& label, QNetworkReply& reply); diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index d0ef3fcaae..c31184eb56 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -722,20 +722,19 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack unsigned char decryptedText[64]; int certIDByteArraySize; int encryptedTextByteArraySize; - int senderNodeUUIDByteArraySize; + int challengingNodeUUIDByteArraySize; packet->readPrimitive(&certIDByteArraySize); packet->readPrimitive(&encryptedTextByteArraySize); if (challengeOriginatedFromClient) { - packet->readPrimitive(&senderNodeUUIDByteArraySize); + packet->readPrimitive(&challengingNodeUUIDByteArraySize); } QByteArray certID = packet->read(certIDByteArraySize); QByteArray encryptedText = packet->read(encryptedTextByteArraySize); - qDebug() << "ZRF encryptedText Inbound:" << QString(encryptedText); - QByteArray senderNodeUUID; + QByteArray challengingNodeUUID; if (challengeOriginatedFromClient) { - senderNodeUUID = packet->read(senderNodeUUIDByteArraySize); + challengingNodeUUID = packet->read(challengingNodeUUIDByteArraySize); } RSA* rsa = readKeys(keyFilePath().toStdString().c_str()); @@ -759,15 +758,15 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack // setup the packet if (challengeOriginatedFromClient) { auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, - certIDSize + decryptedTextByteArraySize + senderNodeUUIDByteArraySize + 3 * sizeof(int), + certIDSize + decryptedTextByteArraySize + challengingNodeUUIDByteArraySize + 3 * sizeof(int), true); decryptedTextPacket->writePrimitive(certIDSize); decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); - decryptedTextPacket->writePrimitive(senderNodeUUIDByteArraySize); + decryptedTextPacket->writePrimitive(challengingNodeUUIDByteArraySize); decryptedTextPacket->write(certID); decryptedTextPacket->write(decryptedTextByteArray); - decryptedTextPacket->write(senderNodeUUID); + decryptedTextPacket->write(challengingNodeUUID); qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index eecf93745a..48f2394ca3 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -348,6 +349,8 @@ void ContextOverlayInterface::openInspectionCertificate() { qCWarning(context_overlay) << "Couldn't get Entity Server!"; } } else { + auto ledger = DependencyManager::get(); + emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED)); qCDebug(context_overlay) << "Entity" << _currentEntityWithContextOverlay << "failed static certificate verification!"; } } @@ -386,6 +389,8 @@ void ContextOverlayInterface::deletingEntity(const EntityItemID& entityID) { } void ContextOverlayInterface::handleChallengeOwnershipReplyPacket(QSharedPointer packet, SharedNodePointer sendingNode) { + auto ledger = DependencyManager::get(); + int certIDByteArraySize; int decryptedTextByteArraySize; @@ -398,5 +403,9 @@ void ContextOverlayInterface::handleChallengeOwnershipReplyPacket(QSharedPointer EntityItemID id; bool verificationSuccess = DependencyManager::get()->getTree()->verifyDecryptedNonce(certID, decryptedText, id); - qDebug() << "ZRF VERIFICATION STATUS:" << verificationSuccess; + if (verificationSuccess) { + emit ledger->updateCertificateStatus(certID, (uint)(ledger->CERTIFICATE_STATUS_VERIFICATION_SUCCESS)); + } else { + emit ledger->updateCertificateStatus(certID, (uint)(ledger->CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED)); + } } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 1cf9fdfb26..f748291077 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1238,11 +1238,11 @@ void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message message.readPrimitive(&encryptedTextByteArraySize); message.readPrimitive(&nodeToChallengeByteArraySize); - QString certID(message.read(certIDByteArraySize)); - QString encryptedText(message.read(encryptedTextByteArraySize)); - QUuid nodeToChallenge = QUuid::fromRfc4122(message.read(nodeToChallengeByteArraySize)); + QByteArray certID(message.read(certIDByteArraySize)); + QByteArray encryptedText(message.read(encryptedTextByteArraySize)); + QByteArray nodeToChallenge(message.read(nodeToChallengeByteArraySize)); - sendChallengeOwnershipRequestPacket(certID, encryptedText, sourceNode, nodeToChallenge); + sendChallengeOwnershipRequestPacket(certID, encryptedText, nodeToChallenge, sourceNode); } void EntityTree::processChallengeOwnershipReplyPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { @@ -1250,15 +1250,15 @@ void EntityTree::processChallengeOwnershipReplyPacket(ReceivedMessage& message, int certIDByteArraySize; int decryptedTextByteArraySize; - int senderNodeUUIDByteArraySize; + int challengingNodeUUIDByteArraySize; message.readPrimitive(&certIDByteArraySize); message.readPrimitive(&decryptedTextByteArraySize); - message.readPrimitive(&senderNodeUUIDByteArraySize); + message.readPrimitive(&challengingNodeUUIDByteArraySize); QByteArray certID(message.read(certIDByteArraySize)); QByteArray decryptedText(message.read(decryptedTextByteArraySize)); - QUuid challengingNode = QUuid::fromRfc4122(message.read(senderNodeUUIDByteArraySize)); + QUuid challengingNode = QUuid::fromRfc4122(message.read(challengingNodeUUIDByteArraySize)); auto challengeOwnershipReplyPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, certIDByteArraySize + decryptedText.length() + 2 * sizeof(int), @@ -1304,17 +1304,15 @@ void EntityTree::sendChallengeOwnershipPacket(const QString& certID, const QStri } } -void EntityTree::sendChallengeOwnershipRequestPacket(const QString& certID, const QString& encryptedText, const SharedNodePointer& senderNode, const QUuid& nodeToChallenge) { +void EntityTree::sendChallengeOwnershipRequestPacket(const QByteArray& certID, const QByteArray& encryptedText, const QByteArray& nodeToChallenge, const SharedNodePointer& senderNode) { auto nodeList = DependencyManager::get(); // In this case, Client A is challenging Client B. Client A is inspecting a certified entity that it wants // to make sure belongs to Avatar B. - QByteArray certIDByteArray = certID.toUtf8(); - QByteArray encryptedTextByteArray = encryptedText.toUtf8(); QByteArray senderNodeUUID = senderNode->getUUID().toRfc4122(); - int certIDByteArraySize = certIDByteArray.length(); - int encryptedTextByteArraySize = encryptedTextByteArray.length(); + int certIDByteArraySize = certID.length(); + int encryptedTextByteArraySize = encryptedText.length(); int senderNodeUUIDSize = senderNodeUUID.length(); auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, @@ -1323,11 +1321,11 @@ void EntityTree::sendChallengeOwnershipRequestPacket(const QString& certID, cons challengeOwnershipPacket->writePrimitive(certIDByteArraySize); challengeOwnershipPacket->writePrimitive(encryptedTextByteArraySize); challengeOwnershipPacket->writePrimitive(senderNodeUUIDSize); - challengeOwnershipPacket->write(certIDByteArray); - challengeOwnershipPacket->write(encryptedTextByteArray); + challengeOwnershipPacket->write(certID); + challengeOwnershipPacket->write(encryptedText); challengeOwnershipPacket->write(senderNodeUUID); - nodeList->sendPacket(std::move(challengeOwnershipPacket), *(nodeList->nodeWithUUID(nodeToChallenge))); + nodeList->sendPacket(std::move(challengeOwnershipPacket), *(nodeList->nodeWithUUID(QUuid::fromRfc4122(nodeToChallenge)))); } void EntityTree::validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation) { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 5eb5d5b569..86bfe984f6 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -381,7 +381,7 @@ protected: private: void sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode); - void sendChallengeOwnershipRequestPacket(const QString& certID, const QString& encryptedText, const SharedNodePointer& senderNode, const QUuid& nodeToChallenge); + void sendChallengeOwnershipRequestPacket(const QByteArray& certID, const QByteArray& encryptedText, const QByteArray& nodeToChallenge, const SharedNodePointer& senderNode); void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); }; From b335ba9a75f92c50a2fdde765201f5203b16da66 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 1 Nov 2017 11:34:29 -0700 Subject: [PATCH 075/183] Timeout timer --- .../InspectionCertificate.qml | 25 ++++++++ interface/src/commerce/Ledger.h | 18 +++--- interface/src/commerce/QmlCommerce.cpp | 1 + interface/src/commerce/QmlCommerce.h | 2 + interface/src/commerce/Wallet.cpp | 62 +++++++++---------- .../ui/overlays/ContextOverlayInterface.cpp | 40 ++++++++---- .../src/ui/overlays/ContextOverlayInterface.h | 5 ++ libraries/entities/src/EntityTree.cpp | 4 +- 8 files changed, 105 insertions(+), 52 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml index aa1372494f..06e04d6929 100644 --- a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml +++ b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml @@ -65,6 +65,31 @@ Rectangle { } } } + + onUpdateCertificateStatus: { + if (root.certificateId === certID) { + if (certStatus === 1) { // CERTIFICATE_STATUS_VERIFICATION_SUCCESS + + } else if (certStatus === 2) { // CERTIFICATE_STATUS_VERIFICATION_TIMEOUT + errorText.text = "Verification of this certificate timed out."; + errorText.color = hifi.colors.redHighlight; + } else if (certStatus === 3) { // CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED + titleBarText.text = "Invalid Certificate"; + titleBarText.color = hifi.colors.redHighlight; + root.itemEdition = "Uncertified Copy"; + errorText.text = "The certificate associated with this entity is invalid."; + errorText.color = hifi.colors.redHighlight; + } else if (certStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED + titleBarText.text = "Invalid Certificate"; + titleBarText.color = hifi.colors.redHighlight; + root.itemEdition = "Uncertified Copy"; + errorText.text = "The certificate associated with this entity is invalid."; + errorText.color = hifi.colors.redHighlight; + } else { + console.log("Unknown certificate status received from ledger signal!"); + } + } + } } onCertificateIdChanged: { diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 75f6fb1ba8..42eb0ffc49 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -35,6 +35,14 @@ public: void updateLocation(const QString& asset_id, const QString location, const bool controlledFailure = false); void certificateInfo(const QString& certificateId); + enum CertificateStatus { + CERTIFICATE_STATUS_UNKNOWN = 0, + CERTIFICATE_STATUS_VERIFICATION_SUCCESS, + CERTIFICATE_STATUS_VERIFICATION_TIMEOUT, + CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED, + CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED, + }; + signals: void buyResult(QJsonObject result); void receiveAtResult(QJsonObject result); @@ -45,6 +53,8 @@ signals: void locationUpdateResult(QJsonObject result); void certificateInfoResult(QJsonObject result); + void updateCertificateStatus(const QString& certID, uint certStatus); + public slots: void buySuccess(QNetworkReply& reply); void buyFailure(QNetworkReply& reply); @@ -65,14 +75,6 @@ public slots: void certificateInfoSuccess(QNetworkReply& reply); void certificateInfoFailure(QNetworkReply& reply); - void updateCertificateStatus(const QString& certID, uint certStatus); - enum CertificateStatus { - CERTIFICATE_STATUS_UNKNOWN = 0, - CERTIFICATE_STATUS_VERIFICATION_SUCCESS, - CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED, - CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED, - }; - private: QJsonObject apiResponse(const QString& label, QNetworkReply& reply); QJsonObject failResponse(const QString& label, QNetworkReply& reply); diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 803264fa9f..ac5d0e6a2d 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -30,6 +30,7 @@ QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) { connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult); connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult); connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult); + connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus); } void QmlCommerce::getWalletStatus() { diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index ae63133425..d4f4aa35d2 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -45,6 +45,8 @@ signals: void accountResult(QJsonObject result); void certificateInfoResult(QJsonObject result); + void updateCertificateStatus(const QString& certID, uint certStatus); + protected: Q_INVOKABLE void getWalletStatus(); diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index c31184eb56..c6d77982b8 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -740,6 +740,8 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack RSA* rsa = readKeys(keyFilePath().toStdString().c_str()); if (rsa) { + auto nodeList = DependencyManager::get(); + ERR_clear_error(); const int decryptionStatus = RSA_private_decrypt(encryptedTextByteArraySize, reinterpret_cast(encryptedText.constData()), @@ -749,41 +751,39 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack RSA_free(rsa); - if (decryptionStatus != -1) { - auto nodeList = DependencyManager::get(); + QByteArray decryptedTextByteArray = QByteArray(reinterpret_cast(decryptedText), decryptionStatus); + int decryptedTextByteArraySize = decryptedTextByteArray.size(); + int certIDSize = certID.size(); + // setup the packet + if (challengeOriginatedFromClient) { + auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, + certIDSize + decryptedTextByteArraySize + challengingNodeUUIDByteArraySize + 3 * sizeof(int), + true); - QByteArray decryptedTextByteArray = QByteArray(reinterpret_cast(decryptedText), decryptionStatus); - int decryptedTextByteArraySize = decryptedTextByteArray.size(); - int certIDSize = certID.size(); - // setup the packet - if (challengeOriginatedFromClient) { - auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, - certIDSize + decryptedTextByteArraySize + challengingNodeUUIDByteArraySize + 3 * sizeof(int), - true); + decryptedTextPacket->writePrimitive(certIDSize); + decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); + decryptedTextPacket->writePrimitive(challengingNodeUUIDByteArraySize); + decryptedTextPacket->write(certID); + decryptedTextPacket->write(decryptedTextByteArray); + decryptedTextPacket->write(challengingNodeUUID); - decryptedTextPacket->writePrimitive(certIDSize); - decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); - decryptedTextPacket->writePrimitive(challengingNodeUUIDByteArraySize); - decryptedTextPacket->write(certID); - decryptedTextPacket->write(decryptedTextByteArray); - decryptedTextPacket->write(challengingNodeUUID); + qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; - qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; - - nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); - } else { - auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnership, certIDSize + decryptedTextByteArraySize + 2 * sizeof(int), true); - - decryptedTextPacket->writePrimitive(certIDSize); - decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); - decryptedTextPacket->write(certID); - decryptedTextPacket->write(decryptedTextByteArray); - - qCDebug(commerce) << "Sending ChallengeOwnership Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; - - nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); - } + nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); } else { + auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnership, certIDSize + decryptedTextByteArraySize + 2 * sizeof(int), true); + + decryptedTextPacket->writePrimitive(certIDSize); + decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); + decryptedTextPacket->write(certID); + decryptedTextPacket->write(decryptedTextByteArray); + + qCDebug(commerce) << "Sending ChallengeOwnership Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; + + nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); + } + + if (decryptionStatus == -1) { qCDebug(commerce) << "During entity ownership challenge, decrypting the encrypted text failed."; long error = ERR_get_error(); if (error != 0) { diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 48f2394ca3..75aefdc585 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -76,6 +76,7 @@ ContextOverlayInterface::ContextOverlayInterface() { auto nodeList = DependencyManager::get(); auto& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::ChallengeOwnershipReply, this, "handleChallengeOwnershipReplyPacket"); + _challengeOwnershipTimeoutTimer.setSingleShot(true); } static const uint32_t MOUSE_HW_ID = 0; @@ -271,16 +272,16 @@ void ContextOverlayInterface::openInspectionCertificate() { tablet->loadQMLSource(INSPECTION_CERTIFICATE_QML_PATH); _hmdScriptingInterface->openTablet(); - EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_currentEntityWithContextOverlay, _entityPropertyFlags); + setLastInspectedEntity(_currentEntityWithContextOverlay); + + EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_lastInspectedEntity, _entityPropertyFlags); QUuid nodeToChallenge = entityProperties.getOwningAvatarID(); auto nodeList = DependencyManager::get(); // ZRF FIXME: Don't challenge ownership of avatar entities that I own if (entityProperties.getClientOnly()/* && nodeToChallenge != nodeList->getSessionUUID()*/) { - // ZRF FIXME! - //if (entityProperties.verifyStaticCertificateProperties()) { - if (true) { + if (entityProperties.verifyStaticCertificateProperties()) { SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer); if (entityServer) { @@ -331,12 +332,12 @@ void ContextOverlayInterface::openInspectionCertificate() { nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer); // Kickoff a 10-second timeout timer that marks the cert if we don't get an ownership response in time - //if (thread() != QThread::currentThread()) { - // QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer", Q_ARG(const EntityItemID&, entityItemID)); - // return; - //} else { - // startChallengeOwnershipTimer(entityItemID); - //} + if (thread() != QThread::currentThread()) { + QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer"); + return; + } else { + startChallengeOwnershipTimer(); + } } } else { qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << @@ -350,8 +351,9 @@ void ContextOverlayInterface::openInspectionCertificate() { } } else { auto ledger = DependencyManager::get(); + _challengeOwnershipTimeoutTimer.stop(); emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED)); - qCDebug(context_overlay) << "Entity" << _currentEntityWithContextOverlay << "failed static certificate verification!"; + qCDebug(context_overlay) << "Entity" << _lastInspectedEntity << "failed static certificate verification!"; } } } @@ -388,9 +390,23 @@ void ContextOverlayInterface::deletingEntity(const EntityItemID& entityID) { } } +void ContextOverlayInterface::startChallengeOwnershipTimer() { + auto ledger = DependencyManager::get(); + EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_lastInspectedEntity, _entityPropertyFlags); + + connect(&_challengeOwnershipTimeoutTimer, &QTimer::timeout, this, [=]() { + qCDebug(entities) << "Ownership challenge timed out for" << _lastInspectedEntity; + emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_VERIFICATION_TIMEOUT)); + }); + + _challengeOwnershipTimeoutTimer.start(5000); +} + void ContextOverlayInterface::handleChallengeOwnershipReplyPacket(QSharedPointer packet, SharedNodePointer sendingNode) { auto ledger = DependencyManager::get(); + _challengeOwnershipTimeoutTimer.stop(); + int certIDByteArraySize; int decryptedTextByteArraySize; @@ -403,6 +419,8 @@ void ContextOverlayInterface::handleChallengeOwnershipReplyPacket(QSharedPointer EntityItemID id; bool verificationSuccess = DependencyManager::get()->getTree()->verifyDecryptedNonce(certID, decryptedText, id); + qDebug() << "ZRF" << verificationSuccess; + if (verificationSuccess) { emit ledger->updateCertificateStatus(certID, (uint)(ledger->CERTIFICATE_STATUS_VERIFICATION_SUCCESS)); } else { diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index eedc1790d3..8f0a40ef8e 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -51,6 +51,7 @@ public: Q_INVOKABLE QUuid getCurrentEntityWithContextOverlay() { return _currentEntityWithContextOverlay; } void setCurrentEntityWithContextOverlay(const QUuid& entityID) { _currentEntityWithContextOverlay = entityID; } + void setLastInspectedEntity(const QUuid& entityID) { _challengeOwnershipTimeoutTimer.stop(); _lastInspectedEntity = entityID; } void setEnabled(bool enabled); bool getEnabled() { return _enabled; } bool getIsInMarketplaceInspectionMode() { return _isInMarketplaceInspectionMode; } @@ -77,6 +78,7 @@ private: bool _verboseLogging { true }; bool _enabled { true }; EntityItemID _currentEntityWithContextOverlay{}; + EntityItemID _lastInspectedEntity{}; QString _entityMarketplaceID; bool _contextOverlayJustClicked { false }; @@ -90,6 +92,9 @@ private: void deletingEntity(const EntityItemID& entityItemID); SelectionToSceneHandler _selectionToSceneHandler; + + Q_INVOKABLE void startChallengeOwnershipTimer(); + QTimer _challengeOwnershipTimeoutTimer; }; #endif // hifi_ContextOverlayInterface_h diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index f748291077..333a514377 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1220,9 +1220,9 @@ bool EntityTree::verifyDecryptedNonce(const QString& certID, const QString& decr bool verificationSuccess = (actualNonce == decryptedNonce); if (verificationSuccess) { - qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "succeeded for entity" << id; + qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "succeeded."; } else { - qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed for entity" << id + qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed." << "\nActual nonce:" << actualNonce << "\nDecrypted nonce:" << decryptedNonce; } From 56cb98d96f64f9f3f4458ae072c3507a4db0b268 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 1 Nov 2017 12:02:09 -0700 Subject: [PATCH 076/183] Make inspection cert work --- .../InspectionCertificate.qml | 40 +++++++++---------- .../ui/overlays/ContextOverlayInterface.cpp | 3 +- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml index 06e04d6929..bd8808f05f 100644 --- a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml +++ b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml @@ -67,27 +67,25 @@ Rectangle { } onUpdateCertificateStatus: { - if (root.certificateId === certID) { - if (certStatus === 1) { // CERTIFICATE_STATUS_VERIFICATION_SUCCESS - - } else if (certStatus === 2) { // CERTIFICATE_STATUS_VERIFICATION_TIMEOUT - errorText.text = "Verification of this certificate timed out."; - errorText.color = hifi.colors.redHighlight; - } else if (certStatus === 3) { // CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED - titleBarText.text = "Invalid Certificate"; - titleBarText.color = hifi.colors.redHighlight; - root.itemEdition = "Uncertified Copy"; - errorText.text = "The certificate associated with this entity is invalid."; - errorText.color = hifi.colors.redHighlight; - } else if (certStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED - titleBarText.text = "Invalid Certificate"; - titleBarText.color = hifi.colors.redHighlight; - root.itemEdition = "Uncertified Copy"; - errorText.text = "The certificate associated with this entity is invalid."; - errorText.color = hifi.colors.redHighlight; - } else { - console.log("Unknown certificate status received from ledger signal!"); - } + if (certStatus === 1) { // CERTIFICATE_STATUS_VERIFICATION_SUCCESS + // NOP + } else if (certStatus === 2) { // CERTIFICATE_STATUS_VERIFICATION_TIMEOUT + errorText.text = "Verification of this certificate timed out."; + errorText.color = hifi.colors.redHighlight; + } else if (certStatus === 3) { // CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED + titleBarText.text = "Invalid Certificate"; + titleBarText.color = hifi.colors.redHighlight; + root.itemEdition = "Uncertified Copy"; + errorText.text = "The certificate associated with this entity is invalid."; + errorText.color = hifi.colors.redHighlight; + } else if (certStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED + titleBarText.text = "Invalid Certificate"; + titleBarText.color = hifi.colors.redHighlight; + root.itemEdition = "Uncertified Copy"; + errorText.text = "The certificate associated with this entity is invalid."; + errorText.color = hifi.colors.redHighlight; + } else { + console.log("Unknown certificate status received from ledger signal!"); } } } diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 75aefdc585..5990c710ad 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -279,8 +279,7 @@ void ContextOverlayInterface::openInspectionCertificate() { QUuid nodeToChallenge = entityProperties.getOwningAvatarID(); auto nodeList = DependencyManager::get(); - // ZRF FIXME: Don't challenge ownership of avatar entities that I own - if (entityProperties.getClientOnly()/* && nodeToChallenge != nodeList->getSessionUUID()*/) { + if (entityProperties.getClientOnly()) { if (entityProperties.verifyStaticCertificateProperties()) { SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer); From 72d61f1825c83023029936930b1437c626c12715 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 1 Nov 2017 12:03:44 -0700 Subject: [PATCH 077/183] Remove unnecessary log - static verif isn't working --- interface/src/ui/overlays/ContextOverlayInterface.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 5990c710ad..e6568b56dd 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -418,8 +418,6 @@ void ContextOverlayInterface::handleChallengeOwnershipReplyPacket(QSharedPointer EntityItemID id; bool verificationSuccess = DependencyManager::get()->getTree()->verifyDecryptedNonce(certID, decryptedText, id); - qDebug() << "ZRF" << verificationSuccess; - if (verificationSuccess) { emit ledger->updateCertificateStatus(certID, (uint)(ledger->CERTIFICATE_STATUS_VERIFICATION_SUCCESS)); } else { From edc7b91a425353b47f38a98ad94ad8ced981229d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 1 Nov 2017 12:57:07 -0700 Subject: [PATCH 078/183] Fix comment in NetworkingConstants referencing shared.js location --- libraries/networking/src/NetworkingConstants.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index 0bb0cee5d2..0c210e4360 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -16,8 +16,8 @@ namespace NetworkingConstants { // If you want to use STAGING instead of STABLE, - // don't forget to ALSO change the Domain Server Metaverse Server URL, which is at the top of: - // \domain-server\resources\web\settings\js\settings.js + // don't forget to ALSO change the Domain Server Metaverse Server URL inside of: + // \domain-server\resources\web\js\shared.js const QUrl METAVERSE_SERVER_URL_STABLE("https://metaverse.highfidelity.com"); const QUrl METAVERSE_SERVER_URL_STAGING("https://staging.highfidelity.com"); const QUrl METAVERSE_SERVER_URL = METAVERSE_SERVER_URL_STABLE; From 76e06a62143c24f510d8474c960ecda323ef7194 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 1 Nov 2017 15:28:28 -0700 Subject: [PATCH 079/183] Update to stable-v-staging metaverse switching, to handle marketplace injection. --- scripts/system/html/js/marketplacesInject.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 4b127baef8..dc0c610ace 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -89,7 +89,7 @@ window.location = "https://clara.io/library?gameCheck=true&public=true"; }); $('#exploreHifiMarketplace').on('click', function () { - window.location = "http://www.highfidelity.com/marketplace"; + window.location = metaverseServerURL + "/marketplace"; }); } @@ -612,9 +612,9 @@ var HIFI_ITEM_PAGE = 3; var pageType = DIRECTORY; - if (location.href.indexOf("highfidelity.com/") !== -1) { pageType = HIFI; } + if (location.href.indexOf(metaverseServerURL + "/") !== -1) { pageType = HIFI; } if (location.href.indexOf("clara.io/") !== -1) { pageType = CLARA; } - if (location.href.indexOf("highfidelity.com/marketplace/items/") !== -1) { pageType = HIFI_ITEM_PAGE; } + if (location.href.indexOf(metaverseServerURL + "/marketplace/items/") !== -1) { pageType = HIFI_ITEM_PAGE; } injectCommonCode(pageType === DIRECTORY); switch (pageType) { From 12792c3821730a8f271d2f802cf57606c02c1ca3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Nov 2017 17:26:00 -0700 Subject: [PATCH 080/183] stop drawing ignored avatars, even if PAL is still open --- interface/src/avatar/AvatarManager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index e8b800db69..4cf8ba6d4e 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -179,6 +179,12 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { const AvatarPriority& sortData = sortedAvatars.top(); const auto& avatar = std::static_pointer_cast(sortData.avatar); + bool ignoring = DependencyManager::get()->isPersonalMutingNode(avatar->getID()); + if (ignoring) { + sortedAvatars.pop(); + continue; + } + // for ALL avatars... if (_shouldRender) { avatar->ensureInScene(avatar, qApp->getMain3DScene()); From 67552d2b7de3ae8ec71db3bb3563d77a2b82da5d Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 1 Nov 2017 17:39:37 -0700 Subject: [PATCH 081/183] Change stencil mask used with Haze. --- libraries/render-utils/src/DrawHaze.cpp | 2 +- libraries/render-utils/src/StencilMaskPass.cpp | 5 +++++ libraries/render-utils/src/StencilMaskPass.h | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index 7cf07d8f33..dba35cbb3c 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -140,7 +140,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu gpu::StatePointer state = gpu::StatePointer(new gpu::State()); // Mask out haze on the tablet - PrepareStencil::testNoAA(*state); + PrepareStencil::testMaskNoAA(*state); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), HazeEffect_ParamsSlot)); diff --git a/libraries/render-utils/src/StencilMaskPass.cpp b/libraries/render-utils/src/StencilMaskPass.cpp index 0e0d8b56b3..f9305d8268 100644 --- a/libraries/render-utils/src/StencilMaskPass.cpp +++ b/libraries/render-utils/src/StencilMaskPass.cpp @@ -128,6 +128,11 @@ void PrepareStencil::testNoAA(gpu::State& state) { gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } +void PrepareStencil::testMaskNoAA(gpu::State& state) { + state.setStencilTest(true, 0x00, gpu::State::StencilTest(0, STENCIL_MASK | STENCIL_NO_AA, gpu::EQUAL, + gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); +} + // Pass if this area WAS marked as BACKGROUND // (see: model/src/Skybox.cpp, procedural/src/ProceduralSkybox.cpp) void PrepareStencil::testBackground(gpu::State& state) { diff --git a/libraries/render-utils/src/StencilMaskPass.h b/libraries/render-utils/src/StencilMaskPass.h index ddbf4a7ac0..18ec104ff5 100644 --- a/libraries/render-utils/src/StencilMaskPass.h +++ b/libraries/render-utils/src/StencilMaskPass.h @@ -49,8 +49,9 @@ public: static void drawMask(gpu::State& state); static void drawBackground(gpu::State& state); - static void testNoAA(gpu::State& state); static void testMask(gpu::State& state); + static void testNoAA(gpu::State& state); + static void testMaskNoAA(gpu::State& state); static void testBackground(gpu::State& state); static void testShape(gpu::State& state); static void testMaskDrawShape(gpu::State& state); From 455f2ad2776d50d84c83ac5e1f92ccd271e39ca9 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 1 Nov 2017 18:14:36 -0700 Subject: [PATCH 082/183] trying to change the root transorm update --- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 142e57c9e5..f9f2fd868a 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -728,8 +728,9 @@ void Avatar::simulateAttachments(float deltaTime) { glm::quat jointRotation; if (attachment.isSoft) { // soft attachments do not have transform offsets - model->setTranslation(getPosition()); - model->setRotation(getOrientation() * Quaternions::Y_180); + // model->setTranslation(getPosition()); + // model->setRotation(getOrientation() * Quaternions::Y_180); + model->setTransformNoUpdateRenderItems(Transform(getOrientation() * Quaternions::Y_180, glm::vec3(1.0), getPosition()); model->simulate(deltaTime); } else { if (_skeletonModel->getJointPositionInWorldFrame(jointIndex, jointPosition) && From 6a2dc38fdd402e42b648a74b2254387f85ae1665 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 1 Nov 2017 19:38:37 -0700 Subject: [PATCH 083/183] restoring previous roles --- libraries/animation/src/Rig.cpp | 30 +++++-------------- libraries/animation/src/Rig.h | 17 +++++++++-- .../src/avatars-renderer/Avatar.cpp | 12 -------- .../src/avatars-renderer/Avatar.h | 4 +-- 4 files changed, 24 insertions(+), 39 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 8293cb91f4..e16afc65c2 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -144,27 +144,6 @@ QStringList Rig::getAnimationRoles() const { } } -QVector> Rig::getAnimationClips() const { - QVector> list; - if (_animNode) { - _animNode->traverse([&](AnimNode::Pointer node) { - // only report clip nodes as valid roles. - auto clipNode = std::dynamic_pointer_cast(node); - if (clipNode) { - // filter out the userAnims, they are for internal use only. - if (!clipNode->getID().startsWith("userAnim")) { - list.append(clipNode); - } - } - return true; - }); - return list; - } - else { - return list; - } -} - void Rig::overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame) { if (_animNode) { AnimNode::Pointer node = _animNode->findByName(role); @@ -173,6 +152,7 @@ void Rig::overrideRoleAnimation(const QString& role, const QString& url, float f const float REFERENCE_FRAMES_PER_SECOND = 30.0f; float timeScale = fps / REFERENCE_FRAMES_PER_SECOND; auto clipNode = std::make_shared(role, url, firstFrame, lastFrame, timeScale, loop, false); + _roleAnimState[role] = { role, url, fps, loop, firstFrame, lastFrame }; AnimNode::Pointer parent = node->getParent(); parent->replaceChild(node, clipNode); } else { @@ -1659,8 +1639,14 @@ void Rig::initAnimGraph(const QUrl& url) { _userAnimState = { UserAnimState::None, "", 30.0f, false, 0.0f, 0.0f }; overrideAnimation(origState.url, origState.fps, origState.loop, origState.firstFrame, origState.lastFrame); } + // restore the role animations we had before reset. + for (auto ite = _roleAnimState.begin(); ite != _roleAnimState.end(); ite++) { + auto role = ite->first; + auto roleState = _roleAnimState[role]; + overrideRoleAnimation(roleState.role, roleState.url, roleState.fps, roleState.loop, roleState.firstFrame, roleState.lastFrame); + } _animLoading = false; - + emit onLoadComplete(); }); connect(_animLoader.get(), &AnimNodeLoader::error, [url](int error, QString str) { diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 9290b41513..a63d5eb0a5 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -21,7 +21,6 @@ #include #include -#include "AnimClip.h" #include "AnimNode.h" #include "AnimNodeLoader.h" #include "SimpleMovingAverage.h" @@ -108,7 +107,7 @@ public: QStringList getAnimationRoles() const; void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame); void restoreRoleAnimation(const QString& role); - QVector> getAnimationClips() const; + //QVector> getAnimationClips() const; void initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset); void reset(const FBXGeometry& geometry); @@ -337,8 +336,22 @@ protected: float firstFrame; float lastFrame; }; + + struct RoleAnimState { + RoleAnimState() {} + RoleAnimState(const QString& roleId, const QString& urlIn, float fpsIn, bool loopIn, float firstFrameIn, float lastFrameIn) : + role(roleId), url(urlIn), fps(fpsIn), loop(loopIn), firstFrame(firstFrameIn), lastFrame(lastFrameIn) {} + + QString role; + QString url; + float fps; + bool loop; + float firstFrame; + float lastFrame; + }; UserAnimState _userAnimState; + std::map _roleAnimState; float _leftHandOverlayAlpha { 0.0f }; float _rightHandOverlayAlpha { 0.0f }; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 0d2e730a1a..142e57c9e5 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -139,7 +139,6 @@ Avatar::~Avatar() { void Avatar::init() { getHead()->init(); _skeletonModel->init(); - connect(&_skeletonModel->getRig(), &Rig::onLoadComplete, this, &Avatar::restoreAnimations); _initialized = true; } @@ -199,16 +198,6 @@ void Avatar::setTargetScale(float targetScale) { } } -void Avatar::restoreAnimations() { - for (int i = 0; i < _animationCache.size(); i++) { - auto clip = _animationCache[i]; - const float REFERENCE_FRAMES_PER_SECOND = 30.0f; - float fps = REFERENCE_FRAMES_PER_SECOND / clip->getTimeScale(); - qDebug() << clip->getID() << " " << clip->getURL() << " " << fps << " " << clip->getLoopFlag() << " " << clip->getStartFrame() << " " << clip->getEndFrame(); - _skeletonModel->getRig().overrideRoleAnimation(clip->getID(), clip->getURL(), fps, clip->getLoopFlag(), clip->getStartFrame(), clip->getEndFrame()); - } -} - void Avatar::updateAvatarEntities() { PerformanceTimer perfTimer("attachments"); // - if queueEditEntityMessage sees clientOnly flag it does _myAvatar->updateAvatarEntity() @@ -1188,7 +1177,6 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { } void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { - _animationCache = _skeletonModel->getRig().getAnimationClips(); AvatarData::setSkeletonModelURL(skeletonModelURL); if (QThread::currentThread() == thread()) { _skeletonModel->setURL(_skeletonModelURL); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 09e1451aa9..a06ba0fb82 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -274,7 +274,7 @@ public slots: glm::vec3 getRightPalmPosition() const; glm::quat getRightPalmRotation() const; - void restoreAnimations(); + //void restoreAnimations(); void setModelURLFinished(bool success); protected: @@ -378,8 +378,6 @@ private: float _displayNameTargetAlpha { 1.0f }; float _displayNameAlpha { 1.0f }; - - QVector> _animationCache; }; #endif // hifi_Avatar_h From e201e82ec26aa0ce28b63a1bf36b6c0828e9e6fd Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 1 Nov 2017 19:45:56 -0700 Subject: [PATCH 084/183] formatting --- libraries/animation/src/AnimClip.h | 1 - libraries/animation/src/Rig.cpp | 2 +- libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/animation/src/AnimClip.h b/libraries/animation/src/AnimClip.h index 7121cff356..c7e7ebf3ee 100644 --- a/libraries/animation/src/AnimClip.h +++ b/libraries/animation/src/AnimClip.h @@ -54,7 +54,6 @@ public: void setMirrorFlag(bool mirrorFlag) { _mirrorFlag = mirrorFlag; } void loadURL(const QString& url); - const QString& getURL() { return _url; } protected: virtual void setCurrentFrameInternal(float frame) override; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index e16afc65c2..9df12de540 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1646,7 +1646,7 @@ void Rig::initAnimGraph(const QUrl& url) { overrideRoleAnimation(roleState.role, roleState.url, roleState.fps, roleState.loop, roleState.firstFrame, roleState.lastFrame); } _animLoading = false; - + emit onLoadComplete(); }); connect(_animLoader.get(), &AnimNodeLoader::error, [url](int error, QString str) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index a06ba0fb82..a5ec307c50 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -274,7 +274,6 @@ public slots: glm::vec3 getRightPalmPosition() const; glm::quat getRightPalmRotation() const; - //void restoreAnimations(); void setModelURLFinished(bool success); protected: From 9e0e1ab5a54c85f3721a629aee5e2e9e67e3dae4 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 1 Nov 2017 19:56:16 -0700 Subject: [PATCH 085/183] erase comment --- libraries/animation/src/Rig.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index a63d5eb0a5..8ca701ec2d 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -107,7 +107,6 @@ public: QStringList getAnimationRoles() const; void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame); void restoreRoleAnimation(const QString& role); - //QVector> getAnimationClips() const; void initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset); void reset(const FBXGeometry& geometry); From 2e6c849b63f55f453c08a9da64271dfcbbc1857c Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 1 Nov 2017 20:31:44 -0700 Subject: [PATCH 086/183] Added comment. --- libraries/render-utils/src/StencilMaskPass.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/render-utils/src/StencilMaskPass.cpp b/libraries/render-utils/src/StencilMaskPass.cpp index f9305d8268..79833795e9 100644 --- a/libraries/render-utils/src/StencilMaskPass.cpp +++ b/libraries/render-utils/src/StencilMaskPass.cpp @@ -128,6 +128,7 @@ void PrepareStencil::testNoAA(gpu::State& state) { gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } +// Pass if this area has been marked as MASK or NO_AA void PrepareStencil::testMaskNoAA(gpu::State& state) { state.setStencilTest(true, 0x00, gpu::State::StencilTest(0, STENCIL_MASK | STENCIL_NO_AA, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); From e9743d4c950a1e4591ec2690b12d9aa1de70561a Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 2 Nov 2017 10:00:30 +0100 Subject: [PATCH 087/183] Added jsdoc to SelectionScriptingInterface --- .../scripting/SelectionScriptingInterface.h | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h index 28c1713050..d9003c2c32 100644 --- a/interface/src/scripting/SelectionScriptingInterface.h +++ b/interface/src/scripting/SelectionScriptingInterface.h @@ -56,11 +56,44 @@ public: GameplayObjects getList(const QString& listName); + /**jsdoc + * Prints out the list of avatars, entities and overlays stored in a particular selection. + * @function Selection.printList + * @param listName {string} name of the selection + */ Q_INVOKABLE void printList(const QString& listName); + /**jsdoc + * Removes a named selection from the list of selections. + * @function Selection.removeListFromMap + * @param listName {string} name of the selection + * @returns {bool} true if the selection existed and was successfully removed. + */ Q_INVOKABLE bool removeListFromMap(const QString& listName); + /**jsdoc + * Add an item in a selection. + * @function Selection.addToSelectedItemsList + * @param listName {string} name of the selection + * @param itemType {string} the type of the item (one of "avatar", "entity" or "overlay") + * @param id {EntityID} the Id of the item to add to the selection + * @returns {bool} true if the item was successfully added. + */ Q_INVOKABLE bool addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id); + /**jsdoc + * Remove an item from a selection. + * @function Selection.removeFromSelectedItemsList + * @param listName {string} name of the selection + * @param itemType {string} the type of the item (one of "avatar", "entity" or "overlay") + * @param id {EntityID} the Id of the item to remove + * @returns {bool} true if the item was successfully removed. + */ Q_INVOKABLE bool removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id); + /**jsdoc + * Remove all items from a selection. + * @function Selection.clearSelectedItemsList + * @param listName {string} name of the selection + * @returns {bool} true if the item was successfully cleared. + */ Q_INVOKABLE bool clearSelectedItemsList(const QString& listName); signals: From 56510abd1ebadf399ffb58a5aec1dba6622b1fcd Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 2 Nov 2017 03:45:27 -0700 Subject: [PATCH 088/183] Trying to set the ClusterBuffer in the render loop instead of the game loop --- .../src/avatars-renderer/Avatar.cpp | 3 +- .../src/CauterizedMeshPartPayload.cpp | 27 +++++++++- .../src/CauterizedMeshPartPayload.h | 2 + .../render-utils/src/CauterizedModel.cpp | 49 ++++++++++++++----- .../render-utils/src/MeshPartPayload.cpp | 17 ++++++- libraries/render-utils/src/MeshPartPayload.h | 1 + libraries/render-utils/src/Model.cpp | 35 +++++++++---- .../render-utils/src/SoftAttachmentModel.cpp | 4 +- 8 files changed, 112 insertions(+), 26 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index f9f2fd868a..bbd0110c11 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -730,8 +730,9 @@ void Avatar::simulateAttachments(float deltaTime) { // soft attachments do not have transform offsets // model->setTranslation(getPosition()); // model->setRotation(getOrientation() * Quaternions::Y_180); - model->setTransformNoUpdateRenderItems(Transform(getOrientation() * Quaternions::Y_180, glm::vec3(1.0), getPosition()); + model->setTransformNoUpdateRenderItems(Transform(getOrientation() * Quaternions::Y_180, glm::vec3(1.0), getPosition())); model->simulate(deltaTime); + model->updateRenderItems(); } else { if (_skeletonModel->getJointPositionInWorldFrame(jointIndex, jointPosition) && _skeletonModel->getJointRotationInWorldFrame(jointIndex, jointRotation)) { diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp index 07628904f1..068eb03378 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp @@ -20,11 +20,36 @@ using namespace render; CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform) {} +void CauterizedMeshPartPayload::updateClusterBuffer(const QVector& clusterMatrices, const QVector& cauterizedClusterMatrices) { + + // Once computed the cluster matrices, update the buffer(s) + if (clusterMatrices.size() > 1) { + if (!_clusterBuffer) { + _clusterBuffer = std::make_shared(clusterMatrices.size() * sizeof(glm::mat4), + (const gpu::Byte*) clusterMatrices.constData()); + } else { + _clusterBuffer->setSubData(0, clusterMatrices.size() * sizeof(glm::mat4), + (const gpu::Byte*) clusterMatrices.constData()); + } + } + + if (cauterizedClusterMatrices.size() > 1) { + if (!_cauterizedClusterBuffer) { + _cauterizedClusterBuffer = std::make_shared(cauterizedClusterMatrices.size() * sizeof(glm::mat4), + (const gpu::Byte*) cauterizedClusterMatrices.constData()); + } + else { + _cauterizedClusterBuffer->setSubData(0, clusterMatrices.size() * sizeof(glm::mat4), + (const gpu::Byte*) clusterMatrices.constData()); + } + } +} + void CauterizedMeshPartPayload::updateTransformForCauterizedMesh( const Transform& renderTransform, const gpu::BufferPointer& buffer) { _cauterizedTransform = renderTransform; - _cauterizedClusterBuffer = buffer; + // _cauterizedClusterBuffer = buffer; } void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.h b/libraries/render-utils/src/CauterizedMeshPartPayload.h index 5e3135ea84..4bd20461eb 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.h +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.h @@ -15,6 +15,8 @@ class CauterizedMeshPartPayload : public ModelMeshPartPayload { public: CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform); + void updateClusterBuffer(const QVector& clusterMatrices, const QVector& cauterizedClusterMatrices); + void updateTransformForCauterizedMesh(const Transform& renderTransform, const gpu::BufferPointer& buffer); void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override; diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 47ada457a0..28993dd4f0 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -111,6 +111,7 @@ void CauterizedModel::updateClusterMatrices() { glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); } + /* // Once computed the cluster matrices, update the buffer(s) if (mesh.clusters.size() > 1) { if (!state.clusterBuffer) { @@ -121,6 +122,7 @@ void CauterizedModel::updateClusterMatrices() { (const gpu::Byte*) state.clusterMatrices.constData()); } } + */ } // as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty. @@ -143,7 +145,7 @@ void CauterizedModel::updateClusterMatrices() { } glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); } - +/* if (!_cauterizeBoneSet.empty() && (state.clusterMatrices.size() > 1)) { if (!state.clusterBuffer) { state.clusterBuffer = @@ -153,7 +155,7 @@ void CauterizedModel::updateClusterMatrices() { state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.clusterMatrices.constData()); } - } + }*/ } } @@ -181,7 +183,7 @@ void CauterizedModel::updateRenderItems() { // queue up this work for later processing, at the end of update and just before rendering. // the application will ensure only the last lambda is actually invoked. void* key = (void*)this; - std::weak_ptr weakSelf = shared_from_this(); + std::weak_ptr weakSelf = std::dynamic_pointer_cast(shared_from_this()); AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [weakSelf, scale]() { // do nothing, if the model has already been destroyed. auto self = weakSelf.lock(); @@ -203,33 +205,58 @@ void CauterizedModel::updateRenderItems() { uint32_t deleteGeometryCounter = self->getGeometryCounter(); + if (!self->isLoaded()) { + return; + } render::Transaction transaction; QList keys = self->getRenderItems().keys(); + int meshIndex{ 0 }; foreach (auto itemID, keys) { - transaction.updateItem(itemID, [modelTransform, deleteGeometryCounter](CauterizedMeshPartPayload& data) { - ModelPointer model = data._model.lock(); - if (model && model->isLoaded()) { + const Model::MeshState& state = self->getMeshState(meshIndex); + auto clusterMatrices(state.clusterMatrices); + const Model::MeshState& cState = self->getCauterizeMeshState(meshIndex); + auto clusterMatricesCauterized(cState.clusterMatrices); + + transaction.updateItem(itemID, [modelTransform, deleteGeometryCounter, clusterMatrices, clusterMatricesCauterized](CauterizedMeshPartPayload& data) { + // ModelPointer model = data._model.lock(); + // if (model && model->isLoaded()) { // Ensure the model geometry was not reset between frames - if (deleteGeometryCounter == model->getGeometryCounter()) { + // if (deleteGeometryCounter == model->getGeometryCounter()) { + data.updateClusterBuffer(clusterMatrices, clusterMatricesCauterized); + // this stuff identical to what happens in regular Model - const Model::MeshState& state = model->getMeshState(data._meshIndex); + /*const Model::MeshState& state = model->getMeshState(data._meshIndex); Transform renderTransform = modelTransform; if (state.clusterMatrices.size() == 1) { renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); } data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); + */ + Transform renderTransform = modelTransform; + if (clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); + } + data.updateTransformForSkinnedMesh(renderTransform, modelTransform, nullptr); + // this stuff for cauterized mesh - CauterizedModel* cModel = static_cast(model.get()); + /*CauterizedModel* cModel = static_cast(model.get()); const Model::MeshState& cState = cModel->getCauterizeMeshState(data._meshIndex); renderTransform = modelTransform; if (cState.clusterMatrices.size() == 1) { renderTransform = modelTransform.worldTransform(Transform(cState.clusterMatrices[0])); } data.updateTransformForCauterizedMesh(renderTransform, cState.clusterBuffer); - } - } + */ + renderTransform = modelTransform; + if (clusterMatricesCauterized.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(clusterMatricesCauterized[0])); + } + data.updateTransformForCauterizedMesh(renderTransform, nullptr); + // } + // } }); + meshIndex++; } scene->enqueueTransaction(transaction); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 8b65c9f7ce..abb0d299e1 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -367,12 +367,27 @@ void ModelMeshPartPayload::notifyLocationChanged() { } + +void ModelMeshPartPayload::updateClusterBuffer(const QVector& clusterMatrices) { + // Once computed the cluster matrices, update the buffer(s) + if (clusterMatrices.size() > 1) { + if (!_clusterBuffer) { + _clusterBuffer = std::make_shared(clusterMatrices.size() * sizeof(glm::mat4), + (const gpu::Byte*) clusterMatrices.constData()); + } + else { + _clusterBuffer->setSubData(0, clusterMatrices.size() * sizeof(glm::mat4), + (const gpu::Byte*) clusterMatrices.constData()); + } + } +} + void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform, const gpu::BufferPointer& buffer) { _transform = renderTransform; _worldBound = _adjustedLocalBound; _worldBound.transform(boundTransform); - _clusterBuffer = buffer; + // _clusterBuffer = buffer; } ItemKey ModelMeshPartPayload::getKey() const { diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 99c14510b5..0e8464f873 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -87,6 +87,7 @@ public: typedef Payload::DataPointer Pointer; void notifyLocationChanged() override; + void updateClusterBuffer(const QVector& clusterMatrices); void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform, const gpu::BufferPointer& buffer); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 97f62a3ce0..cbb27f0498 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -240,22 +240,37 @@ void Model::updateRenderItems() { uint32_t deleteGeometryCounter = self->_deleteGeometryCounter; render::Transaction transaction; + int meshIndex{ 0 }; foreach (auto itemID, self->_modelMeshRenderItemsMap.keys()) { - transaction.updateItem(itemID, [deleteGeometryCounter, modelTransform](ModelMeshPartPayload& data) { - ModelPointer model = data._model.lock(); - if (model && model->isLoaded()) { - // Ensure the model geometry was not reset between frames - if (deleteGeometryCounter == model->_deleteGeometryCounter) { + const Model::MeshState& state = self->getMeshState(meshIndex); + auto clusterMatrices(state.clusterMatrices); - const Model::MeshState& state = model->getMeshState(data._meshIndex); + transaction.updateItem(itemID, [deleteGeometryCounter, modelTransform, clusterMatrices](ModelMeshPartPayload& data) { + // ModelPointer model = data._model.lock(); + // if (model && model->isLoaded()) { + // Ensure the model geometry was not reset between frames + // if (deleteGeometryCounter == model->_deleteGeometryCounter) { + + /*const Model::MeshState& state = model->getMeshState(data._meshIndex); Transform renderTransform = modelTransform; if (state.clusterMatrices.size() == 1) { renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); } data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); - } - } + */ + + data.updateClusterBuffer(clusterMatrices); + + Transform renderTransform = modelTransform; + if (clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); + } + data.updateTransformForSkinnedMesh(renderTransform, modelTransform, nullptr); + + // } + // } }); + meshIndex++; } Transform collisionMeshOffset; @@ -1136,7 +1151,7 @@ void Model::updateClusterMatrices() { glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); } - // Once computed the cluster matrices, update the buffer(s) + /* // Once computed the cluster matrices, update the buffer(s) if (mesh.clusters.size() > 1) { if (!state.clusterBuffer) { state.clusterBuffer = std::make_shared(state.clusterMatrices.size() * sizeof(glm::mat4), @@ -1145,7 +1160,7 @@ void Model::updateClusterMatrices() { state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.clusterMatrices.constData()); } - } + }*/ } // post the blender if we're not currently waiting for one to finish diff --git a/libraries/render-utils/src/SoftAttachmentModel.cpp b/libraries/render-utils/src/SoftAttachmentModel.cpp index 63b18d49b8..975d099ac3 100644 --- a/libraries/render-utils/src/SoftAttachmentModel.cpp +++ b/libraries/render-utils/src/SoftAttachmentModel.cpp @@ -62,7 +62,7 @@ void SoftAttachmentModel::updateClusterMatrices() { } // Once computed the cluster matrices, update the buffer(s) - if (mesh.clusters.size() > 1) { + /* if (mesh.clusters.size() > 1) { if (!state.clusterBuffer) { state.clusterBuffer = std::make_shared(state.clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.clusterMatrices.constData()); @@ -70,7 +70,7 @@ void SoftAttachmentModel::updateClusterMatrices() { state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.clusterMatrices.constData()); } - } + }*/ } // post the blender if we're not currently waiting for one to finish From f8718efe25dbeb5e6f3a8162e3bdaa5be19e4cd3 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 2 Nov 2017 09:42:33 -0700 Subject: [PATCH 089/183] Fix warnings --- interface/src/ui/overlays/ContextOverlayInterface.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index e6568b56dd..f83427a1a1 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -276,7 +276,6 @@ void ContextOverlayInterface::openInspectionCertificate() { EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_lastInspectedEntity, _entityPropertyFlags); - QUuid nodeToChallenge = entityProperties.getOwningAvatarID(); auto nodeList = DependencyManager::get(); if (entityProperties.getClientOnly()) { From 19945c5991425745be0355d953f6537248837dd3 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 2 Nov 2017 10:22:00 -0700 Subject: [PATCH 090/183] Update cert UI --- .../InspectionCertificate.qml | 31 ++++++++++++++----- .../ui/overlays/ContextOverlayInterface.cpp | 4 +-- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml index bd8808f05f..6a7a181b92 100644 --- a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml +++ b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml @@ -33,6 +33,7 @@ Rectangle { property string dateOfPurchase: "--"; property bool isLightbox: false; property bool isMyCert: false; + property bool isCertificateInvalid: false; // Style color: hifi.colors.faintGray; Hifi.QmlCommerce { @@ -44,10 +45,11 @@ Rectangle { } else { root.marketplaceUrl = result.data.marketplace_item_url; root.isMyCert = result.isMyCert ? result.isMyCert : false; - root.itemOwner = root.isMyCert ? Account.username : - "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"; - root.itemEdition = result.data.edition_number + "/" + (result.data.limited_run === -1 ? "\u221e" : result.data.limited_run); - root.dateOfPurchase = getFormattedDate(result.data.transfer_created_at * 1000); + root.itemOwner = root.isCertificateInvalid ? "--" : (root.isMyCert ? Account.username : + "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"); + root.itemEdition = root.isCertificateInvalid ? "Uncertified Copy" : + (result.data.edition_number + "/" + (result.data.limited_run === -1 ? "\u221e" : result.data.limited_run)); + root.dateOfPurchase = root.isCertificateInvalid ? "" : getFormattedDate(result.data.transfer_created_at * 1000); root.itemName = result.data.marketplace_item_name; if (result.data.invalid_reason || result.data.transfer_status[0] === "failed") { @@ -70,20 +72,35 @@ Rectangle { if (certStatus === 1) { // CERTIFICATE_STATUS_VERIFICATION_SUCCESS // NOP } else if (certStatus === 2) { // CERTIFICATE_STATUS_VERIFICATION_TIMEOUT + root.isCertificateInvalid = true; errorText.text = "Verification of this certificate timed out."; errorText.color = hifi.colors.redHighlight; } else if (certStatus === 3) { // CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED + root.isCertificateInvalid = true; titleBarText.text = "Invalid Certificate"; titleBarText.color = hifi.colors.redHighlight; + + popText.text = ""; + root.itemOwner = ""; + dateOfPurchaseHeader.text = ""; + root.dateOfPurchase = ""; root.itemEdition = "Uncertified Copy"; + errorText.text = "The certificate associated with this entity is invalid."; - errorText.color = hifi.colors.redHighlight; + errorText.color = hifi.colors.baseGray; } else if (certStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED + root.isCertificateInvalid = true; titleBarText.text = "Invalid Certificate"; titleBarText.color = hifi.colors.redHighlight; + + popText.text = ""; + root.itemOwner = ""; + dateOfPurchaseHeader.text = ""; + root.dateOfPurchase = ""; root.itemEdition = "Uncertified Copy"; + errorText.text = "The certificate associated with this entity is invalid."; - errorText.color = hifi.colors.redHighlight; + errorText.color = hifi.colors.baseGray; } else { console.log("Unknown certificate status received from ledger signal!"); } @@ -239,7 +256,7 @@ Rectangle { } AnonymousProRegular { id: isMyCertText; - visible: root.isMyCert; + visible: root.isMyCert && !root.isCertificateInvalid; text: "(Private)"; size: 18; // Anchors diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index f83427a1a1..b5af529f2b 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -304,9 +304,9 @@ void ContextOverlayInterface::openInspectionCertificate() { if (!jsonObject["invalid_reason"].toString().isEmpty()) { qCDebug(entities) << "invalid_reason not empty"; } else if (jsonObject["transfer_status"].toArray().first().toString() == "failed") { - qCDebug(entities) << "'transfer_status' is 'failed'";; + qCDebug(entities) << "'transfer_status' is 'failed'"; } else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") { - qCDebug(entities) << "'transfer_status' is 'pending'";; + qCDebug(entities) << "'transfer_status' is 'pending'"; } else { QString ownerKey = jsonObject["transfer_recipient_key"].toString(); From 81509b3e92e4a13b3129a97a6ef71e5fcc15869e Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 2 Nov 2017 10:34:57 -0700 Subject: [PATCH 091/183] coding standard --- libraries/animation/src/Rig.cpp | 7 +++---- libraries/animation/src/Rig.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 9df12de540..acf7bf81d8 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -152,7 +152,7 @@ void Rig::overrideRoleAnimation(const QString& role, const QString& url, float f const float REFERENCE_FRAMES_PER_SECOND = 30.0f; float timeScale = fps / REFERENCE_FRAMES_PER_SECOND; auto clipNode = std::make_shared(role, url, firstFrame, lastFrame, timeScale, loop, false); - _roleAnimState[role] = { role, url, fps, loop, firstFrame, lastFrame }; + _roleAnimStates[role] = { role, url, fps, loop, firstFrame, lastFrame }; AnimNode::Pointer parent = node->getParent(); parent->replaceChild(node, clipNode); } else { @@ -1640,9 +1640,8 @@ void Rig::initAnimGraph(const QUrl& url) { overrideAnimation(origState.url, origState.fps, origState.loop, origState.firstFrame, origState.lastFrame); } // restore the role animations we had before reset. - for (auto ite = _roleAnimState.begin(); ite != _roleAnimState.end(); ite++) { - auto role = ite->first; - auto roleState = _roleAnimState[role]; + for (auto& roleAnimState : _roleAnimStates) { + auto roleState = roleAnimState.second; overrideRoleAnimation(roleState.role, roleState.url, roleState.fps, roleState.loop, roleState.firstFrame, roleState.lastFrame); } _animLoading = false; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 8ca701ec2d..e9cc444bd4 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -350,7 +350,7 @@ protected: }; UserAnimState _userAnimState; - std::map _roleAnimState; + std::map _roleAnimStates; float _leftHandOverlayAlpha { 0.0f }; float _rightHandOverlayAlpha { 0.0f }; From db9c3cc103ef37f9a40c4e404fd03de0b0e865f8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 2 Nov 2017 12:31:36 -0700 Subject: [PATCH 092/183] make Model::scaleToFit() public not protected --- libraries/render-utils/src/Model.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 8bce976b4e..3abf7e2758 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -262,6 +262,8 @@ public: Q_INVOKABLE MeshProxyList getMeshes() const; + void scaleToFit(); + public slots: void loadURLFinished(bool success); @@ -320,7 +322,6 @@ protected: virtual void initJointStates(); void setScaleInternal(const glm::vec3& scale); - void scaleToFit(); void snapToRegistrationPoint(); void computeMeshPartLocalBounds(); From 490483fde889e31ddee4c2697e4716eccc4bb792 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 2 Nov 2017 12:32:51 -0700 Subject: [PATCH 093/183] call Model::scaleToFit() before update render items --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 7db19704b4..03380ad321 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -215,6 +215,7 @@ void RenderableModelEntityItem::updateModelBounds() { model->setScaleToFit(true, getDimensions()); model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); updateRenderItems = true; + model->scaleToFit(); } bool success; From d8191e3bd2122f8e45f1ce70d2c4fce98a9f5503 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 2 Nov 2017 12:45:18 -0700 Subject: [PATCH 094/183] Fixed Mask test. --- libraries/render-utils/src/DrawHaze.cpp | 2 +- libraries/render-utils/src/StencilMaskPass.cpp | 10 ++-------- libraries/render-utils/src/StencilMaskPass.h | 1 - 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index dba35cbb3c..f694a93033 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -140,7 +140,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu gpu::StatePointer state = gpu::StatePointer(new gpu::State()); // Mask out haze on the tablet - PrepareStencil::testMaskNoAA(*state); + PrepareStencil::testMask(*state); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), HazeEffect_ParamsSlot)); diff --git a/libraries/render-utils/src/StencilMaskPass.cpp b/libraries/render-utils/src/StencilMaskPass.cpp index 79833795e9..f71111b64e 100644 --- a/libraries/render-utils/src/StencilMaskPass.cpp +++ b/libraries/render-utils/src/StencilMaskPass.cpp @@ -116,9 +116,9 @@ void PrepareStencil::drawBackground(gpu::State& state) { gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP)); } -// Pass if this area has NOT been marked as MASK +// Pass if this area has NOT been marked as MASK or anything containing MASK void PrepareStencil::testMask(gpu::State& state) { - state.setStencilTest(true, 0x00, gpu::State::StencilTest(STENCIL_MASK, 0xFF, gpu::NOT_EQUAL, + state.setStencilTest(true, 0x00, gpu::State::StencilTest(STENCIL_MASK, STENCIL_MASK, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } @@ -128,12 +128,6 @@ void PrepareStencil::testNoAA(gpu::State& state) { gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } -// Pass if this area has been marked as MASK or NO_AA -void PrepareStencil::testMaskNoAA(gpu::State& state) { - state.setStencilTest(true, 0x00, gpu::State::StencilTest(0, STENCIL_MASK | STENCIL_NO_AA, gpu::EQUAL, - gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); -} - // Pass if this area WAS marked as BACKGROUND // (see: model/src/Skybox.cpp, procedural/src/ProceduralSkybox.cpp) void PrepareStencil::testBackground(gpu::State& state) { diff --git a/libraries/render-utils/src/StencilMaskPass.h b/libraries/render-utils/src/StencilMaskPass.h index 18ec104ff5..fc258b607a 100644 --- a/libraries/render-utils/src/StencilMaskPass.h +++ b/libraries/render-utils/src/StencilMaskPass.h @@ -51,7 +51,6 @@ public: static void drawBackground(gpu::State& state); static void testMask(gpu::State& state); static void testNoAA(gpu::State& state); - static void testMaskNoAA(gpu::State& state); static void testBackground(gpu::State& state); static void testShape(gpu::State& state); static void testMaskDrawShape(gpu::State& state); From 23e627a46f740cb3f4e5ccb2384cde0876c6799f Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 2 Nov 2017 13:46:24 -0700 Subject: [PATCH 095/183] Send empty decrypted text if impossible to decrypt --- interface/src/commerce/Wallet.cpp | 92 ++++++++++++++++--------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index c6d77982b8..85632ff8f1 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -718,6 +718,8 @@ bool Wallet::changePassphrase(const QString& newPassphrase) { } void Wallet::handleChallengeOwnershipPacket(QSharedPointer packet, SharedNodePointer sendingNode) { + auto nodeList = DependencyManager::get(); + bool challengeOriginatedFromClient = packet->getType() == PacketType::ChallengeOwnershipRequest; unsigned char decryptedText[64]; int certIDByteArraySize; @@ -738,62 +740,64 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack } RSA* rsa = readKeys(keyFilePath().toStdString().c_str()); + int decryptionStatus = -1; if (rsa) { - auto nodeList = DependencyManager::get(); - ERR_clear_error(); - const int decryptionStatus = RSA_private_decrypt(encryptedTextByteArraySize, + decryptionStatus = RSA_private_decrypt(encryptedTextByteArraySize, reinterpret_cast(encryptedText.constData()), decryptedText, rsa, RSA_PKCS1_OAEP_PADDING); RSA_free(rsa); - - QByteArray decryptedTextByteArray = QByteArray(reinterpret_cast(decryptedText), decryptionStatus); - int decryptedTextByteArraySize = decryptedTextByteArray.size(); - int certIDSize = certID.size(); - // setup the packet - if (challengeOriginatedFromClient) { - auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, - certIDSize + decryptedTextByteArraySize + challengingNodeUUIDByteArraySize + 3 * sizeof(int), - true); - - decryptedTextPacket->writePrimitive(certIDSize); - decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); - decryptedTextPacket->writePrimitive(challengingNodeUUIDByteArraySize); - decryptedTextPacket->write(certID); - decryptedTextPacket->write(decryptedTextByteArray); - decryptedTextPacket->write(challengingNodeUUID); - - qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; - - nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); - } else { - auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnership, certIDSize + decryptedTextByteArraySize + 2 * sizeof(int), true); - - decryptedTextPacket->writePrimitive(certIDSize); - decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); - decryptedTextPacket->write(certID); - decryptedTextPacket->write(decryptedTextByteArray); - - qCDebug(commerce) << "Sending ChallengeOwnership Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; - - nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); - } - - if (decryptionStatus == -1) { - qCDebug(commerce) << "During entity ownership challenge, decrypting the encrypted text failed."; - long error = ERR_get_error(); - if (error != 0) { - const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "RSA error:" << error_str; - } - } } else { qCDebug(commerce) << "During entity ownership challenge, creating the RSA object failed."; } + + QByteArray decryptedTextByteArray; + if (decryptionStatus > -1) { + decryptedTextByteArray = QByteArray(reinterpret_cast(decryptedText), decryptionStatus); + } + int decryptedTextByteArraySize = decryptedTextByteArray.size(); + int certIDSize = certID.size(); + // setup the packet + if (challengeOriginatedFromClient) { + auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, + certIDSize + decryptedTextByteArraySize + challengingNodeUUIDByteArraySize + 3 * sizeof(int), + true); + + decryptedTextPacket->writePrimitive(certIDSize); + decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); + decryptedTextPacket->writePrimitive(challengingNodeUUIDByteArraySize); + decryptedTextPacket->write(certID); + decryptedTextPacket->write(decryptedTextByteArray); + decryptedTextPacket->write(challengingNodeUUID); + + qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; + + nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); + } else { + auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnership, certIDSize + decryptedTextByteArraySize + 2 * sizeof(int), true); + + decryptedTextPacket->writePrimitive(certIDSize); + decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); + decryptedTextPacket->write(certID); + decryptedTextPacket->write(decryptedTextByteArray); + + qCDebug(commerce) << "Sending ChallengeOwnership Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; + + nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); + } + + if (decryptionStatus == -1) { + qCDebug(commerce) << "During entity ownership challenge, decrypting the encrypted text failed."; + long error = ERR_get_error(); + if (error != 0) { + const char* error_str = ERR_error_string(error, NULL); + qCWarning(entities) << "RSA error:" << error_str; + } + } } void Wallet::account() { From 56b1c7d0eeb03bc6ba1504ac71dd1ebbc26b2bec Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 2 Nov 2017 14:51:40 -0700 Subject: [PATCH 096/183] Fix finding the SSL binary path --- cmake/modules/FindOpenSSL.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/FindOpenSSL.cmake b/cmake/modules/FindOpenSSL.cmake index 338dee7bc8..0619c4d587 100644 --- a/cmake/modules/FindOpenSSL.cmake +++ b/cmake/modules/FindOpenSSL.cmake @@ -60,7 +60,7 @@ if (WIN32 AND NOT CYGWIN) select_library_configurations(LIB_EAY) select_library_configurations(SSL_EAY) set(OPENSSL_LIBRARIES ${SSL_EAY_LIBRARY} ${LIB_EAY_LIBRARY}) - find_path(OPENSSL_DLL_PATH NAMES ssleay32.dll PATH_SUFFIXES "bin" ${_OPENSSL_ROOT_HINTS_AND_PATHS}) + find_path(OPENSSL_DLL_PATH NAMES ssleay32.dll PATH_SUFFIXES "bin" HINTS ${_OPENSSL_ROOT_HINTS_AND_PATHS} NO_DEFAULT_PATH) endif() else() From 6173ad810b3c9207d649734a741c062459f99a53 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 2 Nov 2017 15:48:59 -0700 Subject: [PATCH 097/183] Reset wallet passphrase when login username changes --- interface/src/commerce/QmlCommerce.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index ac5d0e6a2d..9d07ddb4ab 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -31,6 +31,11 @@ QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) { connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult); connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult); connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus); + + auto accountManager = DependencyManager::get(); + connect(accountManager.data(), &AccountManager::usernameChanged, [&]() { + setPassphrase(""); + }); } void QmlCommerce::getWalletStatus() { From 83bfa1c5f26805291bdd60bdf61ea07d1f3307b1 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 2 Nov 2017 17:57:46 -0700 Subject: [PATCH 098/183] Progressing on the cluster updates --- .../render-utils/src/CauterizedModel.cpp | 3 +- libraries/render-utils/src/Model.cpp | 58 ++++++++++--------- libraries/render-utils/src/Model.h | 1 - 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 28993dd4f0..71f161038c 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -211,7 +211,8 @@ void CauterizedModel::updateRenderItems() { render::Transaction transaction; QList keys = self->getRenderItems().keys(); int meshIndex{ 0 }; - foreach (auto itemID, keys) { + //foreach (auto itemID, keys) { + for (auto itemID : self->_modelMeshRenderItemIDs) { const Model::MeshState& state = self->getMeshState(meshIndex); auto clusterMatrices(state.clusterMatrices); const Model::MeshState& cState = self->getCauterizeMeshState(meshIndex); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index cbb27f0498..b999283fad 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -218,6 +218,10 @@ void Model::updateRenderItems() { _needsUpdateClusterMatrices = true; _renderItemsNeedUpdate = false; + if (_modelMeshRenderItemIDs.size() != _meshStates.size()) { + return; + } + // queue up this work for later processing, at the end of update and just before rendering. // the application will ensure only the last lambda is actually invoked. void* key = (void*)this; @@ -240,37 +244,39 @@ void Model::updateRenderItems() { uint32_t deleteGeometryCounter = self->_deleteGeometryCounter; render::Transaction transaction; - int meshIndex{ 0 }; foreach (auto itemID, self->_modelMeshRenderItemsMap.keys()) { - const Model::MeshState& state = self->getMeshState(meshIndex); - auto clusterMatrices(state.clusterMatrices); + // for (auto itemID : self->_modelMeshRenderItemIDs) { + if (self && self->isLoaded()) { + int meshIndex = std::dynamic_pointer_cast(self->_modelMeshRenderItemsMap[itemID])->_meshIndex; + const Model::MeshState& state = self->getMeshState(meshIndex); + auto clusterMatrices(state.clusterMatrices); - transaction.updateItem(itemID, [deleteGeometryCounter, modelTransform, clusterMatrices](ModelMeshPartPayload& data) { - // ModelPointer model = data._model.lock(); - // if (model && model->isLoaded()) { - // Ensure the model geometry was not reset between frames - // if (deleteGeometryCounter == model->_deleteGeometryCounter) { + transaction.updateItem(itemID, [deleteGeometryCounter, modelTransform, clusterMatrices](ModelMeshPartPayload& data) { + // ModelPointer model = data._model.lock(); + // if (model && model->isLoaded()) { + // Ensure the model geometry was not reset between frames + // if (deleteGeometryCounter == model->_deleteGeometryCounter) { - /*const Model::MeshState& state = model->getMeshState(data._meshIndex); - Transform renderTransform = modelTransform; - if (state.clusterMatrices.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); - } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); - */ - - data.updateClusterBuffer(clusterMatrices); + /*const Model::MeshState& state = model->getMeshState(data._meshIndex); + Transform renderTransform = modelTransform; + if (state.clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); + } + data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); + */ - Transform renderTransform = modelTransform; - if (clusterMatrices.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); - } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform, nullptr); + data.updateClusterBuffer(clusterMatrices); - // } - // } - }); - meshIndex++; + Transform renderTransform = modelTransform; + if (clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); + } + data.updateTransformForSkinnedMesh(renderTransform, modelTransform, nullptr); + + // } + // } + }); + } } Transform collisionMeshOffset; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 8bce976b4e..2854f1b1b0 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -387,7 +387,6 @@ protected: QVector> _modelMeshRenderItems; QMap _modelMeshRenderItemsMap; - render::ItemIDs _modelMeshRenderItemIDs; bool _addedToScene { false }; // has been added to scene From 6f3c61c4e0314baa448cc09a8ff31470f21bdae6 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 2 Nov 2017 17:57:52 -0700 Subject: [PATCH 099/183] Slightly modify invalid cert language --- .../commerce/inspectionCertificate/InspectionCertificate.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml index 6a7a181b92..b6c29a1fad 100644 --- a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml +++ b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml @@ -86,7 +86,7 @@ Rectangle { root.dateOfPurchase = ""; root.itemEdition = "Uncertified Copy"; - errorText.text = "The certificate associated with this entity is invalid."; + errorText.text = "The information associated with this item has been modified and it no longer matches the original certified item."; errorText.color = hifi.colors.baseGray; } else if (certStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED root.isCertificateInvalid = true; @@ -99,7 +99,7 @@ Rectangle { root.dateOfPurchase = ""; root.itemEdition = "Uncertified Copy"; - errorText.text = "The certificate associated with this entity is invalid."; + errorText.text = "The avatar who rezzed this item doesn't own it."; errorText.color = hifi.colors.baseGray; } else { console.log("Unknown certificate status received from ledger signal!"); From d33c75865eb24af29ccb1dccf01cacf332debb90 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 2 Nov 2017 18:11:13 -0700 Subject: [PATCH 100/183] Removing unecessary test --- libraries/render-utils/src/Model.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index b999283fad..1f53ed731a 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -218,9 +218,6 @@ void Model::updateRenderItems() { _needsUpdateClusterMatrices = true; _renderItemsNeedUpdate = false; - if (_modelMeshRenderItemIDs.size() != _meshStates.size()) { - return; - } // queue up this work for later processing, at the end of update and just before rendering. // the application will ensure only the last lambda is actually invoked. From f097d66721f971b8c71c9eeda4b1c9e1da977f8a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 2 Nov 2017 19:49:01 -0700 Subject: [PATCH 101/183] YEp it s working --- libraries/render-utils/src/CauterizedModel.cpp | 8 +++++++- libraries/render-utils/src/Model.cpp | 11 +++++++++-- libraries/render-utils/src/Model.h | 2 ++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 71f161038c..01e6a830eb 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -57,6 +57,7 @@ void CauterizedModel::createVisibleRenderItemSet() { Q_ASSERT(_modelMeshRenderItems.isEmpty()); _modelMeshRenderItems.clear(); + _modelMeshRenderItemShapes.clear(); Transform transform; transform.setTranslation(_translation); @@ -80,6 +81,7 @@ void CauterizedModel::createVisibleRenderItemSet() { for (int partIndex = 0; partIndex < numParts; partIndex++) { auto ptr = std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset); _modelMeshRenderItems << std::static_pointer_cast(ptr); + _modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i }); shapeID++; } } @@ -212,7 +214,11 @@ void CauterizedModel::updateRenderItems() { QList keys = self->getRenderItems().keys(); int meshIndex{ 0 }; //foreach (auto itemID, keys) { - for (auto itemID : self->_modelMeshRenderItemIDs) { + // for (auto itemID : self->_modelMeshRenderItemIDs) { + for (int i = 0; i < self->_modelMeshRenderItemIDs.size(); i++) { + auto itemID = self->_modelMeshRenderItemIDs[i]; + auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; + const Model::MeshState& state = self->getMeshState(meshIndex); auto clusterMatrices(state.clusterMatrices); const Model::MeshState& cState = self->getCauterizeMeshState(meshIndex); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 1f53ed731a..9b337b3662 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -241,10 +241,14 @@ void Model::updateRenderItems() { uint32_t deleteGeometryCounter = self->_deleteGeometryCounter; render::Transaction transaction; - foreach (auto itemID, self->_modelMeshRenderItemsMap.keys()) { + // foreach (auto itemID, self->_modelMeshRenderItemsMap.keys()) { // for (auto itemID : self->_modelMeshRenderItemIDs) { + for (int i = 0; i < self->_modelMeshRenderItemIDs.size(); i++) { + auto itemID = self->_modelMeshRenderItemIDs[i]; + auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; if (self && self->isLoaded()) { - int meshIndex = std::dynamic_pointer_cast(self->_modelMeshRenderItemsMap[itemID])->_meshIndex; + //int meshIndex = std::dynamic_pointer_cast(self->_modelMeshRenderItemsMap[itemID])->_meshIndex; + // int meshIndex = std::dynamic_pointer_cast(self->_modelMeshRenderItemsMap[itemID])->_meshIndex; const Model::MeshState& state = self->getMeshState(meshIndex); auto clusterMatrices(state.clusterMatrices); @@ -704,6 +708,7 @@ void Model::removeFromScene(const render::ScenePointer& scene, render::Transacti _modelMeshRenderItemIDs.clear(); _modelMeshRenderItemsMap.clear(); _modelMeshRenderItems.clear(); + _modelMeshRenderItemShapes.clear(); foreach(auto item, _collisionRenderItemsMap.keys()) { transaction.removeItem(item); @@ -1282,6 +1287,7 @@ void Model::createVisibleRenderItemSet() { Q_ASSERT(_modelMeshRenderItems.isEmpty()); _modelMeshRenderItems.clear(); + _modelMeshRenderItemShapes.clear(); Transform transform; transform.setTranslation(_translation); @@ -1304,6 +1310,7 @@ void Model::createVisibleRenderItemSet() { int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { _modelMeshRenderItems << std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset); + _modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i }); shapeID++; } } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 2854f1b1b0..aed647e714 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -388,6 +388,8 @@ protected: QVector> _modelMeshRenderItems; QMap _modelMeshRenderItemsMap; render::ItemIDs _modelMeshRenderItemIDs; + using ShapeInfo = struct { int meshIndex; }; + std::vector _modelMeshRenderItemShapes; bool _addedToScene { false }; // has been added to scene bool _needsFixupInScene { true }; // needs to be removed/re-added to scene From 421aacd8ebb96e0125fa3837cce6c26263fef030 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 2 Nov 2017 22:45:19 -0700 Subject: [PATCH 102/183] Yes --- .../render-utils/src/CauterizedModel.cpp | 63 +++++-------------- libraries/render-utils/src/Model.cpp | 20 ------ .../render-utils/src/SoftAttachmentModel.cpp | 11 ---- 3 files changed, 16 insertions(+), 78 deletions(-) diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 01e6a830eb..b2cf5093d5 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -186,7 +186,7 @@ void CauterizedModel::updateRenderItems() { // the application will ensure only the last lambda is actually invoked. void* key = (void*)this; std::weak_ptr weakSelf = std::dynamic_pointer_cast(shared_from_this()); - AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [weakSelf, scale]() { + AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [weakSelf]() { // do nothing, if the model has already been destroyed. auto self = weakSelf.lock(); if (!self) { @@ -202,19 +202,12 @@ void CauterizedModel::updateRenderItems() { modelTransform.setTranslation(self->getTranslation()); modelTransform.setRotation(self->getRotation()); - Transform scaledModelTransform(modelTransform); - scaledModelTransform.setScale(scale); - - uint32_t deleteGeometryCounter = self->getGeometryCounter(); - - if (!self->isLoaded()) { + /* if (!self->isLoaded()) { return; - } + }*/ render::Transaction transaction; QList keys = self->getRenderItems().keys(); int meshIndex{ 0 }; - //foreach (auto itemID, keys) { - // for (auto itemID : self->_modelMeshRenderItemIDs) { for (int i = 0; i < self->_modelMeshRenderItemIDs.size(); i++) { auto itemID = self->_modelMeshRenderItemIDs[i]; auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; @@ -224,46 +217,22 @@ void CauterizedModel::updateRenderItems() { const Model::MeshState& cState = self->getCauterizeMeshState(meshIndex); auto clusterMatricesCauterized(cState.clusterMatrices); - transaction.updateItem(itemID, [modelTransform, deleteGeometryCounter, clusterMatrices, clusterMatricesCauterized](CauterizedMeshPartPayload& data) { - // ModelPointer model = data._model.lock(); - // if (model && model->isLoaded()) { - // Ensure the model geometry was not reset between frames - // if (deleteGeometryCounter == model->getGeometryCounter()) { - data.updateClusterBuffer(clusterMatrices, clusterMatricesCauterized); + transaction.updateItem(itemID, + [modelTransform, clusterMatrices, clusterMatricesCauterized](CauterizedMeshPartPayload& data) { + data.updateClusterBuffer(clusterMatrices, clusterMatricesCauterized); - // this stuff identical to what happens in regular Model - /*const Model::MeshState& state = model->getMeshState(data._meshIndex); - Transform renderTransform = modelTransform; - if (state.clusterMatrices.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); - } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); - */ - Transform renderTransform = modelTransform; - if (clusterMatrices.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); - } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform, nullptr); + Transform renderTransform = modelTransform; + if (clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); + } + data.updateTransformForSkinnedMesh(renderTransform, modelTransform, nullptr); - - // this stuff for cauterized mesh - /*CauterizedModel* cModel = static_cast(model.get()); - const Model::MeshState& cState = cModel->getCauterizeMeshState(data._meshIndex); - renderTransform = modelTransform; - if (cState.clusterMatrices.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(cState.clusterMatrices[0])); - } - data.updateTransformForCauterizedMesh(renderTransform, cState.clusterBuffer); - */ - renderTransform = modelTransform; - if (clusterMatricesCauterized.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(clusterMatricesCauterized[0])); - } - data.updateTransformForCauterizedMesh(renderTransform, nullptr); - // } - // } + renderTransform = modelTransform; + if (clusterMatricesCauterized.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(clusterMatricesCauterized[0])); + } + data.updateTransformForCauterizedMesh(renderTransform, nullptr); }); - meshIndex++; } scene->enqueueTransaction(transaction); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 9b337b3662..4add6fb5ba 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -241,31 +241,14 @@ void Model::updateRenderItems() { uint32_t deleteGeometryCounter = self->_deleteGeometryCounter; render::Transaction transaction; - // foreach (auto itemID, self->_modelMeshRenderItemsMap.keys()) { - // for (auto itemID : self->_modelMeshRenderItemIDs) { for (int i = 0; i < self->_modelMeshRenderItemIDs.size(); i++) { auto itemID = self->_modelMeshRenderItemIDs[i]; auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; if (self && self->isLoaded()) { - //int meshIndex = std::dynamic_pointer_cast(self->_modelMeshRenderItemsMap[itemID])->_meshIndex; - // int meshIndex = std::dynamic_pointer_cast(self->_modelMeshRenderItemsMap[itemID])->_meshIndex; const Model::MeshState& state = self->getMeshState(meshIndex); auto clusterMatrices(state.clusterMatrices); transaction.updateItem(itemID, [deleteGeometryCounter, modelTransform, clusterMatrices](ModelMeshPartPayload& data) { - // ModelPointer model = data._model.lock(); - // if (model && model->isLoaded()) { - // Ensure the model geometry was not reset between frames - // if (deleteGeometryCounter == model->_deleteGeometryCounter) { - - /*const Model::MeshState& state = model->getMeshState(data._meshIndex); - Transform renderTransform = modelTransform; - if (state.clusterMatrices.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); - } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); - */ - data.updateClusterBuffer(clusterMatrices); Transform renderTransform = modelTransform; @@ -273,9 +256,6 @@ void Model::updateRenderItems() { renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); } data.updateTransformForSkinnedMesh(renderTransform, modelTransform, nullptr); - - // } - // } }); } } diff --git a/libraries/render-utils/src/SoftAttachmentModel.cpp b/libraries/render-utils/src/SoftAttachmentModel.cpp index 975d099ac3..f364e9c037 100644 --- a/libraries/render-utils/src/SoftAttachmentModel.cpp +++ b/libraries/render-utils/src/SoftAttachmentModel.cpp @@ -60,17 +60,6 @@ void SoftAttachmentModel::updateClusterMatrices() { } glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); } - - // Once computed the cluster matrices, update the buffer(s) - /* if (mesh.clusters.size() > 1) { - if (!state.clusterBuffer) { - state.clusterBuffer = std::make_shared(state.clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) state.clusterMatrices.constData()); - } else { - state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) state.clusterMatrices.constData()); - } - }*/ } // post the blender if we're not currently waiting for one to finish From c11f46a8d3fdf01ad5d5b78bb5db8b7978360b98 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 2 Nov 2017 23:35:18 -0700 Subject: [PATCH 103/183] cleaning more code --- .../src/CauterizedMeshPartPayload.cpp | 15 ++++----- .../src/CauterizedMeshPartPayload.h | 4 +-- .../render-utils/src/CauterizedModel.cpp | 31 ++----------------- .../render-utils/src/MeshPartPayload.cpp | 15 ++++----- libraries/render-utils/src/MeshPartPayload.h | 8 ++--- libraries/render-utils/src/Model.cpp | 17 ++-------- libraries/render-utils/src/Model.h | 5 ++- 7 files changed, 24 insertions(+), 71 deletions(-) diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp index 068eb03378..a54a072b75 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp @@ -20,36 +20,33 @@ using namespace render; CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform) {} -void CauterizedMeshPartPayload::updateClusterBuffer(const QVector& clusterMatrices, const QVector& cauterizedClusterMatrices) { +void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices, const std::vector& cauterizedClusterMatrices) { // Once computed the cluster matrices, update the buffer(s) if (clusterMatrices.size() > 1) { if (!_clusterBuffer) { _clusterBuffer = std::make_shared(clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) clusterMatrices.constData()); + (const gpu::Byte*) clusterMatrices.data()); } else { _clusterBuffer->setSubData(0, clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) clusterMatrices.constData()); + (const gpu::Byte*) clusterMatrices.data()); } } if (cauterizedClusterMatrices.size() > 1) { if (!_cauterizedClusterBuffer) { _cauterizedClusterBuffer = std::make_shared(cauterizedClusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) cauterizedClusterMatrices.constData()); + (const gpu::Byte*) cauterizedClusterMatrices.data()); } else { _cauterizedClusterBuffer->setSubData(0, clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) clusterMatrices.constData()); + (const gpu::Byte*) clusterMatrices.data()); } } } -void CauterizedMeshPartPayload::updateTransformForCauterizedMesh( - const Transform& renderTransform, - const gpu::BufferPointer& buffer) { +void CauterizedMeshPartPayload::updateTransformForCauterizedMesh(const Transform& renderTransform) { _cauterizedTransform = renderTransform; - // _cauterizedClusterBuffer = buffer; } void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.h b/libraries/render-utils/src/CauterizedMeshPartPayload.h index 4bd20461eb..1c98f5abf3 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.h +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.h @@ -15,9 +15,9 @@ class CauterizedMeshPartPayload : public ModelMeshPartPayload { public: CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform); - void updateClusterBuffer(const QVector& clusterMatrices, const QVector& cauterizedClusterMatrices); + void updateClusterBuffer(const std::vector& clusterMatrices, const std::vector& cauterizedClusterMatrices); - void updateTransformForCauterizedMesh(const Transform& renderTransform, const gpu::BufferPointer& buffer); + void updateTransformForCauterizedMesh(const Transform& renderTransform); void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override; diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index b2cf5093d5..776de727b4 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -112,19 +112,6 @@ void CauterizedModel::updateClusterMatrices() { auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); } - - /* - // Once computed the cluster matrices, update the buffer(s) - if (mesh.clusters.size() > 1) { - if (!state.clusterBuffer) { - state.clusterBuffer = std::make_shared(state.clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) state.clusterMatrices.constData()); - } else { - state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) state.clusterMatrices.constData()); - } - } - */ } // as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty. @@ -147,17 +134,6 @@ void CauterizedModel::updateClusterMatrices() { } glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); } -/* - if (!_cauterizeBoneSet.empty() && (state.clusterMatrices.size() > 1)) { - if (!state.clusterBuffer) { - state.clusterBuffer = - std::make_shared(state.clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) state.clusterMatrices.constData()); - } else { - state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) state.clusterMatrices.constData()); - } - }*/ } } @@ -202,9 +178,6 @@ void CauterizedModel::updateRenderItems() { modelTransform.setTranslation(self->getTranslation()); modelTransform.setRotation(self->getRotation()); - /* if (!self->isLoaded()) { - return; - }*/ render::Transaction transaction; QList keys = self->getRenderItems().keys(); int meshIndex{ 0 }; @@ -225,13 +198,13 @@ void CauterizedModel::updateRenderItems() { if (clusterMatrices.size() == 1) { renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform, nullptr); + data.updateTransformForSkinnedMesh(renderTransform, modelTransform); renderTransform = modelTransform; if (clusterMatricesCauterized.size() == 1) { renderTransform = modelTransform.worldTransform(Transform(clusterMatricesCauterized[0])); } - data.updateTransformForCauterizedMesh(renderTransform, nullptr); + data.updateTransformForCauterizedMesh(renderTransform); }); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index abb0d299e1..5426ed0ea6 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -337,7 +337,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in if (state.clusterMatrices.size() == 1) { renderTransform = transform.worldTransform(Transform(state.clusterMatrices[0])); } - updateTransformForSkinnedMesh(renderTransform, transform, state.clusterBuffer); + updateTransformForSkinnedMesh(renderTransform, transform); initCache(); } @@ -368,26 +368,24 @@ void ModelMeshPartPayload::notifyLocationChanged() { } -void ModelMeshPartPayload::updateClusterBuffer(const QVector& clusterMatrices) { +void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices) { // Once computed the cluster matrices, update the buffer(s) if (clusterMatrices.size() > 1) { if (!_clusterBuffer) { _clusterBuffer = std::make_shared(clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) clusterMatrices.constData()); + (const gpu::Byte*) clusterMatrices.data()); } else { _clusterBuffer->setSubData(0, clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) clusterMatrices.constData()); + (const gpu::Byte*) clusterMatrices.data()); } } } -void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform, - const gpu::BufferPointer& buffer) { +void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform) { _transform = renderTransform; _worldBound = _adjustedLocalBound; _worldBound.transform(boundTransform); - // _clusterBuffer = buffer; } ItemKey ModelMeshPartPayload::getKey() const { @@ -431,7 +429,6 @@ int ModelMeshPartPayload::getLayer() const { } ShapeKey ModelMeshPartPayload::getShapeKey() const { - // guard against partially loaded meshes ModelPointer model = _model.lock(); if (!model || !model->isLoaded() || !model->getGeometry()) { @@ -597,7 +594,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; } -void ModelMeshPartPayload::computeAdjustedLocalBound(const QVector& clusterMatrices) { +void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterMatrices) { _adjustedLocalBound = _localBound; if (clusterMatrices.size() > 0) { _adjustedLocalBound.transform(clusterMatrices[0]); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 0e8464f873..971c6fe90b 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -87,10 +87,8 @@ public: typedef Payload::DataPointer Pointer; void notifyLocationChanged() override; - void updateClusterBuffer(const QVector& clusterMatrices); - void updateTransformForSkinnedMesh(const Transform& renderTransform, - const Transform& boundTransform, - const gpu::BufferPointer& buffer); + void updateClusterBuffer(const std::vector& clusterMatrices); + void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform); // Render Item interface render::ItemKey getKey() const override; @@ -104,7 +102,7 @@ public: void initCache(); - void computeAdjustedLocalBound(const QVector& clusterMatrices); + void computeAdjustedLocalBound(const std::vector& clusterMatrices); gpu::BufferPointer _clusterBuffer; ModelWeakPointer _model; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 4add6fb5ba..79b968ffb7 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -255,7 +255,7 @@ void Model::updateRenderItems() { if (clusterMatrices.size() == 1) { renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform, nullptr); + data.updateTransformForSkinnedMesh(renderTransform, modelTransform); }); } } @@ -313,7 +313,7 @@ bool Model::updateGeometry() { foreach (const FBXMesh& mesh, fbxGeometry.meshes) { MeshState state; state.clusterMatrices.resize(mesh.clusters.size()); - _meshStates.append(state); + _meshStates.push_back(state); // Note: we add empty buffers for meshes that lack blendshapes so we can access the buffers by index // later in ModelMeshPayload, however the vast majority of meshes will not have them. @@ -1138,17 +1138,6 @@ void Model::updateClusterMatrices() { auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); } - - /* // Once computed the cluster matrices, update the buffer(s) - if (mesh.clusters.size() > 1) { - if (!state.clusterBuffer) { - state.clusterBuffer = std::make_shared(state.clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) state.clusterMatrices.constData()); - } else { - state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) state.clusterMatrices.constData()); - } - }*/ } // post the blender if we're not currently waiting for one to finish @@ -1332,7 +1321,7 @@ void Model::createCollisionRenderItemSet() { } bool Model::isRenderable() const { - return !_meshStates.isEmpty() || (isLoaded() && _renderGeometry->getMeshes().empty()); + return !_meshStates.empty() || (isLoaded() && _renderGeometry->getMeshes().empty()); } class CollisionRenderGeometry : public Geometry { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 58ed143062..c537a928b3 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -246,8 +246,7 @@ public: class MeshState { public: - QVector clusterMatrices; - gpu::BufferPointer clusterBuffer; + std::vector clusterMatrices; }; const MeshState& getMeshState(int index) { return _meshStates.at(index); } @@ -317,7 +316,7 @@ protected: bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point glm::vec3 _registrationPoint = glm::vec3(0.5f); /// the point in model space our center is snapped to - QVector _meshStates; + std::vector _meshStates; virtual void initJointStates(); From 390f5b53caeaab609bddebefc0eb8a54de6ea9d5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 2 Nov 2017 23:55:44 -0700 Subject: [PATCH 104/183] cleaning more code --- .../render-utils/src/CauterizedModel.cpp | 37 ++++++++----------- libraries/render-utils/src/Model.cpp | 28 ++++++-------- 2 files changed, 27 insertions(+), 38 deletions(-) diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 776de727b4..2105806134 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -165,7 +165,7 @@ void CauterizedModel::updateRenderItems() { AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [weakSelf]() { // do nothing, if the model has already been destroyed. auto self = weakSelf.lock(); - if (!self) { + if (!self || !self->isLoaded()) { return; } @@ -179,32 +179,27 @@ void CauterizedModel::updateRenderItems() { modelTransform.setRotation(self->getRotation()); render::Transaction transaction; - QList keys = self->getRenderItems().keys(); - int meshIndex{ 0 }; for (int i = 0; i < self->_modelMeshRenderItemIDs.size(); i++) { + auto itemID = self->_modelMeshRenderItemIDs[i]; auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; + auto clusterMatrices(self->getMeshState(meshIndex).clusterMatrices); + auto clusterMatricesCauterized(self->getCauterizeMeshState(meshIndex).clusterMatrices); - const Model::MeshState& state = self->getMeshState(meshIndex); - auto clusterMatrices(state.clusterMatrices); - const Model::MeshState& cState = self->getCauterizeMeshState(meshIndex); - auto clusterMatricesCauterized(cState.clusterMatrices); + transaction.updateItem(itemID, [modelTransform, clusterMatrices, clusterMatricesCauterized](CauterizedMeshPartPayload& data) { + data.updateClusterBuffer(clusterMatrices, clusterMatricesCauterized); - transaction.updateItem(itemID, - [modelTransform, clusterMatrices, clusterMatricesCauterized](CauterizedMeshPartPayload& data) { - data.updateClusterBuffer(clusterMatrices, clusterMatricesCauterized); + Transform renderTransform = modelTransform; + if (clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); + } + data.updateTransformForSkinnedMesh(renderTransform, modelTransform); - Transform renderTransform = modelTransform; - if (clusterMatrices.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); - } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform); - - renderTransform = modelTransform; - if (clusterMatricesCauterized.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(clusterMatricesCauterized[0])); - } - data.updateTransformForCauterizedMesh(renderTransform); + renderTransform = modelTransform; + if (clusterMatricesCauterized.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(clusterMatricesCauterized[0])); + } + data.updateTransformForCauterizedMesh(renderTransform); }); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 79b968ffb7..f27aa284be 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -218,7 +218,6 @@ void Model::updateRenderItems() { _needsUpdateClusterMatrices = true; _renderItemsNeedUpdate = false; - // queue up this work for later processing, at the end of update and just before rendering. // the application will ensure only the last lambda is actually invoked. void* key = (void*)this; @@ -227,7 +226,7 @@ void Model::updateRenderItems() { // do nothing, if the model has already been destroyed. auto self = weakSelf.lock(); - if (!self) { + if (!self || !self->isLoaded()) { return; } @@ -238,26 +237,21 @@ void Model::updateRenderItems() { Transform modelTransform = self->getTransform(); modelTransform.setScale(glm::vec3(1.0f)); - uint32_t deleteGeometryCounter = self->_deleteGeometryCounter; - render::Transaction transaction; for (int i = 0; i < self->_modelMeshRenderItemIDs.size(); i++) { + auto itemID = self->_modelMeshRenderItemIDs[i]; auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; - if (self && self->isLoaded()) { - const Model::MeshState& state = self->getMeshState(meshIndex); - auto clusterMatrices(state.clusterMatrices); + auto clusterMatrices(self->getMeshState(meshIndex).clusterMatrices); - transaction.updateItem(itemID, [deleteGeometryCounter, modelTransform, clusterMatrices](ModelMeshPartPayload& data) { - data.updateClusterBuffer(clusterMatrices); - - Transform renderTransform = modelTransform; - if (clusterMatrices.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); - } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform); - }); - } + transaction.updateItem(itemID, [modelTransform, clusterMatrices](ModelMeshPartPayload& data) { + data.updateClusterBuffer(clusterMatrices); + Transform renderTransform = modelTransform; + if (clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); + } + data.updateTransformForSkinnedMesh(renderTransform, modelTransform); + }); } Transform collisionMeshOffset; From babaef8399012346342f2fb5651d7ac7a1aa223c Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Fri, 3 Nov 2017 05:59:59 -0700 Subject: [PATCH 105/183] Fix the audio input device peak meters --- interface/resources/qml/hifi/audio/Audio.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index 12c2ec1835..87ddce49ca 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -213,8 +213,8 @@ Rectangle { anchors.right: parent.right peak: model.peak; anchors.verticalCenter: parent.verticalCenter - visible: (bar.currentIndex === 1 && selectedHMD && isVR) || - (bar.currentIndex === 0 && selectedDesktop && !isVR) && + visible: ((bar.currentIndex === 1 && isVR) || + (bar.currentIndex === 0 && !isVR)) && Audio.devices.input.peakValuesAvailable; } } From 4b598a6e241e35edaa622856e4a04fade4dfbce5 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 3 Nov 2017 14:26:36 +0100 Subject: [PATCH 106/183] Working stencil mask with object bounding boxes --- libraries/render-utils/src/OutlineEffect.cpp | 189 ++++++++---------- libraries/render-utils/src/OutlineEffect.h | 10 +- libraries/render-utils/src/Outline_aabox.slv | 103 ++++++++++ libraries/render-utils/src/Outline_shared.slh | 16 +- .../render-utils/src/RenderDeferredTask.cpp | 2 + libraries/render/src/render/SortTask.cpp | 8 +- .../developer/utilities/render/outline.qml | 57 +++--- .../render/outlinePage/OutlinePage.qml | 143 ++++++------- 8 files changed, 305 insertions(+), 223 deletions(-) create mode 100644 libraries/render-utils/src/Outline_aabox.slv diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index ad4c59b35a..a42cbfe358 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -11,7 +11,6 @@ #include "OutlineEffect.h" #include "GeometryCache.h" -#include "RenderUtilsLogging.h" #include "CubeProjectedPolygon.h" @@ -28,10 +27,11 @@ #include "debug_deferred_buffer_frag.h" #include "Outline_frag.h" #include "Outline_filled_frag.h" +#include "Outline_aabox_vert.h" using namespace render; -#define OUTLINE_USE_SCISSOR false +#define OUTLINE_STENCIL_MASK 1 OutlineRessources::OutlineRessources() { } @@ -56,15 +56,16 @@ void OutlineRessources::update(const gpu::FramebufferPointer& primaryFrameBuffer } void OutlineRessources::allocateColorBuffer(const gpu::FramebufferPointer& primaryFrameBuffer) { - _colorFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithoutDepth")); + _colorFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithStencil")); _colorFrameBuffer->setRenderBuffer(0, primaryFrameBuffer->getRenderBuffer(0)); + _colorFrameBuffer->setDepthStencilBuffer(_depthStencilTexture, _depthStencilTexture->getTexelFormat()); } void OutlineRessources::allocateDepthBuffer(const gpu::FramebufferPointer& primaryFrameBuffer) { - auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); - auto depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(depthFormat, _frameSize.x, _frameSize.y)); + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); + _depthStencilTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(depthFormat, _frameSize.x, _frameSize.y)); _depthFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); - _depthFrameBuffer->setDepthStencilBuffer(depthTexture, depthFormat); + _depthFrameBuffer->setDepthStencilBuffer(_depthStencilTexture, depthFormat); } gpu::FramebufferPointer OutlineRessources::getDepthFramebuffer() { @@ -73,10 +74,10 @@ gpu::FramebufferPointer OutlineRessources::getDepthFramebuffer() { } gpu::TexturePointer OutlineRessources::getDepthTexture() { - return getDepthFramebuffer()->getDepthStencilBuffer(); + return _depthStencilTexture; } -gpu::FramebufferPointer OutlineRessources::getColorFramebuffer() { +gpu::FramebufferPointer OutlineRessources::getColorFramebuffer() { assert(_colorFrameBuffer); return _colorFrameBuffer; } @@ -96,6 +97,10 @@ void PrepareDrawOutline::run(const render::RenderContextPointer& renderContext, outputs = _ressources; } +gpu::PipelinePointer DrawOutlineMask::_stencilMaskPipeline; +gpu::PipelinePointer DrawOutlineMask::_stencilMaskFillPipeline; +gpu::BufferPointer DrawOutlineMask::_boundsBuffer; + DrawOutlineMask::DrawOutlineMask(unsigned int outlineIndex, render::ShapePlumberPointer shapePlumber, OutlineSharedParametersPointer parameters) : _outlineIndex{ outlineIndex }, @@ -108,26 +113,42 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con assert(renderContext->args->hasViewFrustum()); auto& inShapes = inputs.get0(); + if (!_stencilMaskPipeline || !_stencilMaskFillPipeline) { + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(OUTLINE_STENCIL_MASK, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_ZERO, gpu::State::STENCIL_OP_REPLACE)); + state->setColorWriteMask(false, false, false, false); + state->setCullMode(gpu::State::CULL_FRONT); + + gpu::StatePointer fillState = gpu::StatePointer(new gpu::State()); + fillState->setDepthTest(false, false, gpu::LESS_EQUAL); + fillState->setStencilTest(true, 0xFF, gpu::State::StencilTest(OUTLINE_STENCIL_MASK, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_REPLACE)); + fillState->setColorWriteMask(false, false, false, false); + fillState->setCullMode(gpu::State::CULL_FRONT); + + auto vs = gpu::Shader::createVertex(std::string(Outline_aabox_vert)); + auto ps = gpu::StandardShaderLib::getDrawWhitePS(); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + _stencilMaskPipeline = gpu::Pipeline::create(program, state); + _stencilMaskFillPipeline = gpu::Pipeline::create(program, fillState); + } + + if (!_boundsBuffer) { + _boundsBuffer = std::make_shared(sizeof(render::ItemBound)); + } + if (!inShapes.empty()) { auto ressources = inputs.get1(); RenderArgs* args = renderContext->args; ShapeKey::Builder defaultKeyBuilder; -#if OUTLINE_USE_SCISSOR - auto framebufferSize = ressources->getSourceFrameSize(); - // First thing we do is determine the projected bounding rect of all the outlined items - auto outlinedRect = computeOutlineRect(inShapes, args->getViewFrustum(), framebufferSize); - auto blurPixelWidth = _sharedParameters->_blurPixelWidths[_outlineIndex]; - //qCDebug(renderutils) << "Outline rect is " << outlinedRect.x << ' ' << outlinedRect.y << ' ' << outlinedRect.z << ' ' << outlinedRect.w; - - // Add 1 pixel of extra margin to be on the safe side - outputs = expandRect(outlinedRect, blurPixelWidth+1, framebufferSize); - outlinedRect = expandRect(outputs, blurPixelWidth+1, framebufferSize); -#else // Render full screen outputs = args->_viewport; -#endif // Clear the framebuffer without stereo // Needs to be distinct from the other batch because using the clear call @@ -135,25 +156,22 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); batch.setFramebuffer(ressources->getDepthFramebuffer()); - batch.clearDepthFramebuffer(1.0f); + batch.clearDepthStencilFramebuffer(1.0f, 0); }); + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + + render::ItemBounds itemBounds; + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); - glm::mat4 projMat; - Transform viewMat; - args->getViewFrustum().evalProjectionMatrix(projMat); - args->getViewFrustum().evalViewTransform(viewMat); - -#if OUTLINE_USE_SCISSOR - batch.setStateScissorRect(outlinedRect); -#endif - batch.setFramebuffer(ressources->getDepthFramebuffer()); - // Setup camera, projection and viewport for all items batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(projMat); @@ -164,7 +182,8 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con // Iterate through all inShapes and render the unskinned args->_shapePipeline = maskPipeline; batch.setPipeline(maskPipeline->pipeline); - for (auto items : inShapes) { + for (const auto& items : inShapes) { + itemBounds.insert(itemBounds.end(), items.second.begin(), items.second.end()); if (items.first.isSkinned()) { skinnedShapeKeys.push_back(items.first); } else { @@ -182,72 +201,34 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con args->_shapePipeline = nullptr; args->_batch = nullptr; }); + + _boundsBuffer->setData(itemBounds.size() * sizeof(render::ItemBound), (const gpu::Byte*) itemBounds.data()); + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + // Setup camera, projection and viewport for all items + batch.setViewportTransform(args->_viewport); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + + // Draw stencil mask with object bounding boxes + const auto outlineWidthLoc = _stencilMaskPipeline->getProgram()->getUniforms().findLocation("outlineWidth"); + const auto sqrt3 = 1.74f; + const float blurPixelWidth = 2.0f * sqrt3 *_sharedParameters->_blurPixelWidths[_outlineIndex]; + const auto framebufferSize = ressources->getSourceFrameSize(); + + auto stencilPipeline = _sharedParameters->_isFilled.test(_outlineIndex) ? _stencilMaskFillPipeline : _stencilMaskPipeline; + batch.setPipeline(stencilPipeline); + batch.setResourceBuffer(0, _boundsBuffer); + batch._glUniform2f(outlineWidthLoc, blurPixelWidth / framebufferSize.x, blurPixelWidth / framebufferSize.y); + static const int NUM_VERTICES_PER_CUBE = 36; + batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_CUBE * (gpu::uint32) itemBounds.size(), 0); + }); } else { // Outline rect should be null as there are no outlined shapes outputs = glm::ivec4(0, 0, 0, 0); } } -glm::ivec4 DrawOutlineMask::computeOutlineRect(const render::ShapeBounds& shapes, - const ViewFrustum& viewFrustum, glm::ivec2 frameSize) { - glm::vec4 minMaxBounds{ - std::numeric_limits::max(), - std::numeric_limits::max(), - -std::numeric_limits::max(), - -std::numeric_limits::max(), - }; - - for (const auto& keyShapes : shapes) { - const auto& items = keyShapes.second; - - for (const auto& item : items) { - const auto& aabb = item.bound; - glm::vec2 bottomLeft; - glm::vec2 topRight; - - if (viewFrustum.getProjectedRect(aabb, bottomLeft, topRight)) { - minMaxBounds.x = std::min(minMaxBounds.x, bottomLeft.x); - minMaxBounds.y = std::min(minMaxBounds.y, bottomLeft.y); - minMaxBounds.z = std::max(minMaxBounds.z, topRight.x); - minMaxBounds.w = std::max(minMaxBounds.w, topRight.y); - } - } - } - - if (minMaxBounds.x != std::numeric_limits::max()) { - const glm::vec2 halfFrameSize{ frameSize.x*0.5f, frameSize.y*0.5f }; - glm::ivec4 rect; - - minMaxBounds += 1.0f; - rect.x = glm::clamp((int)floorf(minMaxBounds.x * halfFrameSize.x), 0, frameSize.x); - rect.y = glm::clamp((int)floorf(minMaxBounds.y * halfFrameSize.y), 0, frameSize.y); - rect.z = glm::clamp((int)ceilf(minMaxBounds.z * halfFrameSize.x), 0, frameSize.x); - rect.w = glm::clamp((int)ceilf(minMaxBounds.w * halfFrameSize.y), 0, frameSize.y); - - rect.z -= rect.x; - rect.w -= rect.y; - return rect; - } else { - return glm::ivec4(0, 0, 0, 0); - } -} - -glm::ivec4 DrawOutlineMask::expandRect(glm::ivec4 rect, int amount, glm::ivec2 frameSize) { - // Go bo back to min max values - rect.z += rect.x; - rect.w += rect.y; - - rect.x = std::max(0, rect.x - amount); - rect.y = std::max(0, rect.y - amount); - rect.z = std::min(frameSize.x, rect.z + amount); - rect.w = std::min(frameSize.y, rect.w + amount); - - // Back to width height - rect.z -= rect.x; - rect.w -= rect.y; - return rect; -} - gpu::PipelinePointer DrawOutline::_pipeline; gpu::PipelinePointer DrawOutline::_pipelineFilled; @@ -270,7 +251,7 @@ void DrawOutline::configure(const Config& config) { _parameters._size.x = (_size * _framebufferSize.y) / _framebufferSize.x; _parameters._size.y = _size; _sharedParameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y); - _isFilled = (config.unoccludedFillOpacity > OPACITY_EPSILON || config.occludedFillOpacity > OPACITY_EPSILON); + _sharedParameters->_isFilled.set(_outlineIndex, (config.unoccludedFillOpacity > OPACITY_EPSILON || config.occludedFillOpacity > OPACITY_EPSILON)); _configuration.edit() = _parameters; } @@ -278,9 +259,6 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I auto outlineFrameBuffer = inputs.get1(); auto outlineRect = inputs.get3(); - // TODO : If scissor isn't possible in stereo, send the AABox in the shader - // and do a raycasting per pixel to determine if we need to do the outline - // This should improve performance. if (outlineFrameBuffer && outlineRect.z>0 && outlineRect.w>0) { auto sceneDepthBuffer = inputs.get2(); const auto frameTransform = inputs.get0(); @@ -302,9 +280,7 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { -#if !OUTLINE_USE_SCISSOR batch.enableStereo(false); -#endif batch.setFramebuffer(destinationFrameBuffer); batch.setViewportTransform(args->_viewport); @@ -312,9 +288,6 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I batch.resetViewTransform(); batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); batch.setPipeline(pipeline); -#if OUTLINE_USE_SCISSOR - batch.setStateScissorRect(outlineRect); -#endif batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer()); @@ -331,7 +304,7 @@ const gpu::PipelinePointer& DrawOutline::getPipeline() { gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setDepthTest(gpu::State::DepthTest(false, false)); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); - state->setScissorEnable(OUTLINE_USE_SCISSOR); + state->setStencilTest(true, 0, gpu::State::StencilTest(OUTLINE_STENCIL_MASK, 0xFF, gpu::EQUAL)); auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); auto ps = gpu::Shader::createPixel(std::string(Outline_frag)); @@ -351,7 +324,7 @@ const gpu::PipelinePointer& DrawOutline::getPipeline() { gpu::Shader::makeProgram(*program, slotBindings); _pipelineFilled = gpu::Pipeline::create(program, state); } - return _isFilled ? _pipelineFilled : _pipeline; + return _sharedParameters->_isFilled.test(_outlineIndex) ? _pipelineFilled : _pipeline; } DebugOutline::DebugOutline() { @@ -380,9 +353,7 @@ void DebugOutline::run(const render::RenderContextPointer& renderContext, const gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.setViewportTransform(args->_viewport); -#if OUTLINE_USE_SCISSOR - batch.setStateScissorRect(outlineRect); -#endif + batch.setFramebuffer(outlineRessources->getColorFramebuffer()); const auto geometryBuffer = DependencyManager::get(); @@ -416,8 +387,8 @@ void DebugOutline::initializePipelines() { "Could not find source placeholder"); auto state = std::make_shared(); - state->setDepthTest(gpu::State::DepthTest(false)); - state->setScissorEnable(OUTLINE_USE_SCISSOR); + state->setDepthTest(gpu::State::DepthTest(false, false)); + state->setStencilTest(true, 0, gpu::State::StencilTest(OUTLINE_STENCIL_MASK, 0xFF, gpu::EQUAL)); const auto vs = gpu::Shader::createVertex(VERTEX_SHADER); @@ -473,7 +444,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende auto state = std::make_shared(); state->setDepthTest(true, true, gpu::LESS_EQUAL); state->setColorWriteMask(false, false, false, false); - state->setScissorEnable(OUTLINE_USE_SCISSOR); + initMaskPipelines(*shapePlumber, state); } auto sharedParameters = std::make_shared(); diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index ee5e503de9..a2bfc88c81 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -33,6 +33,7 @@ protected: gpu::FramebufferPointer _depthFrameBuffer; gpu::FramebufferPointer _colorFrameBuffer; + gpu::TexturePointer _depthStencilTexture; glm::ivec2 _frameSize; @@ -48,6 +49,7 @@ public: OutlineSharedParameters(); std::array _blurPixelWidths; + std::bitset _isFilled; }; using OutlineSharedParametersPointer = std::shared_ptr; @@ -84,9 +86,10 @@ protected: unsigned int _outlineIndex; render::ShapePlumberPointer _shapePlumber; OutlineSharedParametersPointer _sharedParameters; - - static glm::ivec4 computeOutlineRect(const render::ShapeBounds& shapes, const ViewFrustum& viewFrustum, glm::ivec2 frameSize); - static glm::ivec4 expandRect(glm::ivec4 rect, int amount, glm::ivec2 frameSize); + + static gpu::BufferPointer _boundsBuffer; + static gpu::PipelinePointer _stencilMaskPipeline; + static gpu::PipelinePointer _stencilMaskFillPipeline; }; class DrawOutlineConfig : public render::Job::Config { @@ -158,7 +161,6 @@ private: OutlineSharedParametersPointer _sharedParameters; OutlineConfigurationBuffer _configuration; glm::ivec2 _framebufferSize{ 0,0 }; - bool _isFilled{ false }; float _size; }; diff --git a/libraries/render-utils/src/Outline_aabox.slv b/libraries/render-utils/src/Outline_aabox.slv new file mode 100644 index 0000000000..1a46ccd9c7 --- /dev/null +++ b/libraries/render-utils/src/Outline_aabox.slv @@ -0,0 +1,103 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// Draw and transform the fed vertex position with the standard MVP stack +// and offset the vertices by a certain amount in the vertex direction +// +// Created by Olivier Prat on 11/02/2017 +// Copyright 2017 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 gpu/Transform.slh@> + +<$declareStandardTransform()$> + +struct ItemBound { + vec4 id_boundPos; + vec4 boundDim_s; +}; + +#if defined(GPU_GL410) +uniform samplerBuffer ssbo0Buffer; +ItemBound getItemBound(int i) { + int offset = 2 * i; + ItemBound bound; + bound.id_boundPos = texelFetch(ssbo0Buffer, offset); + bound.boundDim_s = texelFetch(ssbo0Buffer, offset + 1); + return bound; +} +#else +layout(std140) buffer ssbo0Buffer { + ItemBound bounds[]; +}; +ItemBound getItemBound(int i) { + ItemBound bound = bounds[i]; + return bound; +} +#endif + +uniform vec2 outlineWidth; + +void main(void) { + const vec3 UNIT_BOX_VERTICES[8] = vec3[8]( + vec3(0.0, 1.0, 0.0), + vec3(1.0, 1.0, 0.0), + vec3(1.0, 0.0, 0.0), + vec3(0.0, 0.0, 0.0), + vec3(0.0, 1.0, 1.0), + vec3(1.0, 1.0, 1.0), + vec3(1.0, 0.0, 1.0), + vec3(0.0, 0.0, 1.0) + ); + const vec3 UNIT_BOX_NORMALS[8] = vec3[8]( + vec3(-1.0, 1.0, -1.0), + vec3(1.0, 1.0, -1.0), + vec3(1.0, -1.0, -1.0), + vec3(-1.0, -1.0, -1.0), + vec3(-1.0, 1.0, 1.0), + vec3(1.0, 1.0, 1.0), + vec3(1.0, -1.0, 1.0), + vec3(-1.0, -1.0, 1.0) + ); + const int NUM_VERTICES_PER_CUBE = 36; + const int UNIT_BOX_TRIANGLE_INDICES[NUM_VERTICES_PER_CUBE] = int[NUM_VERTICES_PER_CUBE]( + 0, 1, 2, + 0, 2, 3, + 3, 2, 6, + 3, 6, 7, + 7, 6, 5, + 7, 5, 4, + 4, 5, 1, + 4, 1, 0, + 1, 5, 6, + 1, 6, 2, + 4, 0, 3, + 4, 3, 7 + ); + + int boundID = gl_VertexID / NUM_VERTICES_PER_CUBE; + int vertexID = gl_VertexID - boundID * NUM_VERTICES_PER_CUBE; + int triangleIndex = UNIT_BOX_TRIANGLE_INDICES[vertexID]; + vec3 cubeVec = UNIT_BOX_VERTICES[triangleIndex]; + + ItemBound bound = getItemBound(boundID); + vec3 boundPos = bound.id_boundPos.yzw; + vec3 boundDim = bound.boundDim_s.xyz; + + vec4 pos = vec4(boundPos + boundDim * cubeVec.xyz, 1.0); + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, pos, gl_Position)$> + + // Offset the vertex to take into account the outline width + pos.xyz += UNIT_BOX_NORMALS[triangleIndex]; + vec4 offsetPosition; + <$transformModelToClipPos(cam, obj, pos, offsetPosition)$> + gl_Position.xy += normalize(offsetPosition.xy-gl_Position.xy) * outlineWidth * gl_Position.w; +} diff --git a/libraries/render-utils/src/Outline_shared.slh b/libraries/render-utils/src/Outline_shared.slh index 2ebece8903..3fd089e2fc 100644 --- a/libraries/render-utils/src/Outline_shared.slh +++ b/libraries/render-utils/src/Outline_shared.slh @@ -1,20 +1,20 @@ // glsl / C++ compatible source as interface for Outline #ifdef __cplusplus -# define VEC2 glm::vec2 -# define VEC3 glm::vec3 -# define VEC4 glm::vec4 +# define TVEC2 glm::vec2 +# define TVEC3 glm::vec3 +# define TVEC4 glm::vec4 #else -# define VEC2 vec2 -# define VEC3 vec3 -# define VEC4 vec4 +# define TVEC2 vec2 +# define TVEC3 vec3 +# define TVEC4 vec4 #endif struct OutlineParameters { - VEC3 _color; + TVEC3 _color; float _intensity; - VEC2 _size; + TVEC2 _size; float _unoccludedFillOpacity; float _occludedFillOpacity; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 63936b0809..16db1281f5 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -35,6 +35,7 @@ #include "TextureCache.h" #include "ZoneRenderer.h" #include "FadeEffect.h" +#include "RenderUtilsLogging.h" #include "AmbientOcclusionEffect.h" #include "AntialiasingEffect.h" @@ -471,6 +472,7 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer auto blitFbo = renderArgs->_blitFramebuffer; if (!blitFbo) { + qCWarning(renderutils) << "Blit::run - no blit frame buffer."; return; } diff --git a/libraries/render/src/render/SortTask.cpp b/libraries/render/src/render/SortTask.cpp index 5b7ead4b6a..00146e393d 100644 --- a/libraries/render/src/render/SortTask.cpp +++ b/libraries/render/src/render/SortTask.cpp @@ -74,9 +74,13 @@ void render::depthSortItems(const RenderContextPointer& renderContext, bool fron std::sort(itemBoundSorts.begin(), itemBoundSorts.end(), backToFrontSort); } - // Finally once sorted result to a list of itemID + // Finally once sorted result to a list of itemID and keep uniques + render::ItemID previousID = Item::INVALID_ITEM_ID; for (auto& item : itemBoundSorts) { - outItems.emplace_back(ItemBound(item._id, item._bounds)); + if (item._id != previousID) { + outItems.emplace_back(ItemBound(item._id, item._bounds)); + previousID = item._id; + } } } diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index 39acd854ac..8269ea830e 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -8,22 +8,34 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html // -import QtQuick 2.5 +import QtQuick 2.7 import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 import "outlinePage" +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls -Item { +Rectangle { id: root + HifiConstants { id: hifi;} + color: hifi.colors.baseGray; + anchors.margins: hifi.dimensions.contentMargin.x + property var debugConfig: Render.getConfig("RenderMainView.OutlineDebug") signal sendToScript(var message); Column { - spacing: 8 - anchors.fill: parent + spacing: 5 + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: hifi.dimensions.contentMargin.x Row { - spacing: 8 - CheckBox { + spacing: 10 + anchors.left: parent.left + anchors.right: parent.right + + HifiControls.CheckBox { id: debug text: "View Mask" checked: root.debugConfig["viewMask"] @@ -31,14 +43,14 @@ Item { root.debugConfig["viewMask"] = checked; } } - CheckBox { + HifiControls.CheckBox { text: "Hover select" checked: false onCheckedChanged: { sendToScript("pick "+checked.toString()) } } - CheckBox { + HifiControls.CheckBox { text: "Add to selection" checked: false onCheckedChanged: { @@ -56,28 +68,13 @@ Item { sendToScript("outline "+currentIndex) } - Tab { - title: "Outl.0" - OutlinePage { - outlineIndex: 0 - } - } - Tab { - title: "Outl.1" - OutlinePage { - outlineIndex: 1 - } - } - Tab { - title: "Outl.2" - OutlinePage { - outlineIndex: 2 - } - } - Tab { - title: "Outl.3" - OutlinePage { - outlineIndex: 3 + Repeater { + model: [ 0, 1, 2, 3 ] + Tab { + title: "Outl."+modelData + OutlinePage { + outlineIndex: modelData + } } } } diff --git a/scripts/developer/utilities/render/outlinePage/OutlinePage.qml b/scripts/developer/utilities/render/outlinePage/OutlinePage.qml index a78bf02d3e..ff1d7fa23b 100644 --- a/scripts/developer/utilities/render/outlinePage/OutlinePage.qml +++ b/scripts/developer/utilities/render/outlinePage/OutlinePage.qml @@ -8,19 +8,28 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html // -import QtQuick 2.5 +import QtQuick 2.7 import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 import "../configSlider" +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls -Item { +Rectangle { id: root property var outlineIndex: 0 property var drawConfig: Render.getConfig("RenderMainView.OutlineEffect"+outlineIndex) - Column { - spacing: 8 + HifiConstants { id: hifi;} + anchors.margins: hifi.dimensions.contentMargin.x - CheckBox { + Column { + spacing: 5 + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: hifi.dimensions.contentMargin.x + + HifiControls.CheckBox { id: glow text: "Glow" checked: root.drawConfig["glow"] @@ -28,84 +37,78 @@ Item { root.drawConfig["glow"] = checked; } } - ConfigSlider { - label: "Width" - integral: false - config: root.drawConfig - property: "width" - max: 5.0 - min: 0.0 - width: 280 - } - ConfigSlider { - label: "Intensity" - integral: false - config: root.drawConfig - property: "intensity" - max: 1.0 - min: 0.0 - width: 280 - } + Repeater { + model: ["Width:width:5.0:0.0", + "Intensity:intensity:1.0:0.0" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: false + config: root.drawConfig + property: modelData.split(":")[1] + max: modelData.split(":")[2] + min: modelData.split(":")[3] + + anchors.left: parent.left + anchors.right: parent.right + } + } GroupBox { title: "Color" - width: 280 + anchors.left: parent.left + anchors.right: parent.right Column { - spacing: 8 + spacing: 10 + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: hifi.dimensions.contentMargin.x - ConfigSlider { - label: "Red" - integral: false - config: root.drawConfig - property: "colorR" - max: 1.0 - min: 0.0 - width: 270 - } - ConfigSlider { - label: "Green" - integral: false - config: root.drawConfig - property: "colorG" - max: 1.0 - min: 0.0 - width: 270 - } - ConfigSlider { - label: "Blue" - integral: false - config: root.drawConfig - property: "colorB" - max: 1.0 - min: 0.0 - width: 270 + Repeater { + model: ["Red:colorR:1.0:0.0", + "Green:colorG:1.0:0.0", + "Blue:colorB:1.0:0.0" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: false + config: root.drawConfig + property: modelData.split(":")[1] + max: modelData.split(":")[2] + min: modelData.split(":")[3] + + anchors.left: parent.left + anchors.right: parent.right + } } } } GroupBox { title: "Fill Opacity" - width: 280 + anchors.left: parent.left + anchors.right: parent.right Column { - spacing: 8 + spacing: 10 + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: hifi.dimensions.contentMargin.x - ConfigSlider { - label: "Unoccluded" - integral: false - config: root.drawConfig - property: "unoccludedFillOpacity" - max: 1.0 - min: 0.0 - width: 270 - } - ConfigSlider { - label: "Occluded" - integral: false - config: root.drawConfig - property: "occludedFillOpacity" - max: 1.0 - min: 0.0 - width: 270 + Repeater { + model: ["Unoccluded:unoccludedFillOpacity:1.0:0.0", + "Occluded:occludedFillOpacity:1.0:0.0" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: false + config: root.drawConfig + property: modelData.split(":")[1] + max: modelData.split(":")[2] + min: modelData.split(":")[3] + + anchors.left: parent.left + anchors.right: parent.right + } } } } From 317141817317668cfaa652c08a909aab0018694b Mon Sep 17 00:00:00 2001 From: Nex-Pro Date: Fri, 3 Nov 2017 17:21:35 +0000 Subject: [PATCH 107/183] Update NameCard.qml --- interface/resources/qml/hifi/NameCard.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index b122f71760..f16b8de337 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -433,7 +433,7 @@ Item { anchors.verticalCenter: nameCardRemoveConnectionImage.verticalCenter x: 240 onClicked: { - console.log("Vist user button clicked."); // Remove after debugging. + console.log("Vist user button clicked."); // Remove after debugging. AddressManager.goToUser(thisNameCard.userName, false); UserActivityLogger.palAction("go_to_user", thisNameCard.userName); } From c496429a85cad2616f6c9f696ccbae19dbad3d25 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 3 Nov 2017 10:40:25 -0700 Subject: [PATCH 108/183] Add Machine Fingerprint to receive_at endpoint txn' --- interface/src/commerce/Ledger.cpp | 10 ++++++++-- interface/src/commerce/Ledger.h | 2 +- interface/src/commerce/Wallet.cpp | 4 +++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 904847cb5f..f607c923ee 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -90,7 +90,7 @@ void Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, cons signedSend("transaction", transactionString, hfc_key, "buy", "buySuccess", "buyFailure", controlled_failure); } -bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key) { +bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key, const QString& machine_fingerprint) { auto accountManager = DependencyManager::get(); if (!accountManager->isLoggedIn()) { qCWarning(commerce) << "Cannot set receiveAt when not logged in."; @@ -99,7 +99,13 @@ bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key) { return false; // We know right away that we will fail, so tell the caller. } - signedSend("public_key", hfc_key.toUtf8(), old_key, "receive_at", "receiveAtSuccess", "receiveAtFailure"); + QJsonObject transaction; + transaction["hfc_key"] = hfc_key; + transaction["machine_fingerprint"] = machine_fingerprint; + QJsonDocument transactionDoc{ transaction }; + auto transactionString = transactionDoc.toJson(QJsonDocument::Compact); + + signedSend("transaction", transactionString, old_key, "receive_at", "receiveAtSuccess", "receiveAtFailure"); return true; // Note that there may still be an asynchronous signal of failure that callers might be interested in. } diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 42eb0ffc49..54f3f780f3 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -26,7 +26,7 @@ class Ledger : public QObject, public Dependency { public: void buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const bool controlled_failure = false); - bool receiveAt(const QString& hfc_key, const QString& old_key); + bool receiveAt(const QString& hfc_key, const QString& old_key, const QString& machine_fingerprint); void balance(const QStringList& keys); void inventory(const QStringList& keys); void history(const QStringList& keys); diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 85632ff8f1..9bc8dc9e43 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -16,6 +16,7 @@ #include "ui/ImageProvider.h" #include "scripting/HMDScriptingInterface.h" +#include #include #include #include @@ -541,7 +542,8 @@ bool Wallet::generateKeyPair() { // 2. It is maximally private, and we can step back from that later if desired. // 3. It maximally exercises all the machinery, so we are most likely to surface issues now. auto ledger = DependencyManager::get(); - return ledger->receiveAt(key, oldKey); + QString machineFingerprint = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); + return ledger->receiveAt(key, oldKey, machineFingerprint); } QStringList Wallet::listPublicKeys() { From 053052a95db484cb48a55a4584d6c939bbb8b2e2 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 3 Nov 2017 13:28:20 -0700 Subject: [PATCH 109/183] removing warnings --- libraries/render-utils/src/CauterizedModel.cpp | 6 +++--- libraries/render-utils/src/MeshPartPayload.cpp | 2 +- libraries/render-utils/src/Model.cpp | 6 +++--- libraries/render-utils/src/SoftAttachmentModel.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 2105806134..30121a232d 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -48,7 +48,7 @@ void CauterizedModel::createVisibleRenderItemSet() { const auto& meshes = _renderGeometry->getMeshes(); // all of our mesh vectors must match in size - if ((int)meshes.size() != _meshStates.size()) { + if (meshes.size() != _meshStates.size()) { qCDebug(renderutils) << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; return; } @@ -104,7 +104,7 @@ void CauterizedModel::updateClusterMatrices() { _needsUpdateClusterMatrices = false; const FBXGeometry& geometry = getFBXGeometry(); - for (int i = 0; i < _meshStates.size(); i++) { + for (int i = 0; i < (int)_meshStates.size(); i++) { Model::MeshState& state = _meshStates[i]; const FBXMesh& mesh = geometry.meshes.at(i); for (int j = 0; j < mesh.clusters.size(); j++) { @@ -179,7 +179,7 @@ void CauterizedModel::updateRenderItems() { modelTransform.setRotation(self->getRotation()); render::Transaction transaction; - for (int i = 0; i < self->_modelMeshRenderItemIDs.size(); i++) { + for (int i = 0; i < (int)self->_modelMeshRenderItemIDs.size(); i++) { auto itemID = self->_modelMeshRenderItemIDs[i]; auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 5426ed0ea6..1ea3e1a705 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -598,7 +598,7 @@ void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector 0) { _adjustedLocalBound.transform(clusterMatrices[0]); - for (int i = 1; i < clusterMatrices.size(); ++i) { + for (int i = 1; i < (int)clusterMatrices.size(); ++i) { AABox clusterBound = _localBound; clusterBound.transform(clusterMatrices[i]); _adjustedLocalBound += clusterBound; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f27aa284be..428fcc7a54 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -238,7 +238,7 @@ void Model::updateRenderItems() { modelTransform.setScale(glm::vec3(1.0f)); render::Transaction transaction; - for (int i = 0; i < self->_modelMeshRenderItemIDs.size(); i++) { + for (int i = 0; i < (int) self->_modelMeshRenderItemIDs.size(); i++) { auto itemID = self->_modelMeshRenderItemIDs[i]; auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; @@ -1124,7 +1124,7 @@ void Model::updateClusterMatrices() { } _needsUpdateClusterMatrices = false; const FBXGeometry& geometry = getFBXGeometry(); - for (int i = 0; i < _meshStates.size(); i++) { + for (int i = 0; i < (int) _meshStates.size(); i++) { MeshState& state = _meshStates[i]; const FBXMesh& mesh = geometry.meshes.at(i); for (int j = 0; j < mesh.clusters.size(); j++) { @@ -1241,7 +1241,7 @@ void Model::createVisibleRenderItemSet() { const auto& meshes = _renderGeometry->getMeshes(); // all of our mesh vectors must match in size - if ((int)meshes.size() != _meshStates.size()) { + if (meshes.size() != _meshStates.size()) { qCDebug(renderutils) << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; return; } diff --git a/libraries/render-utils/src/SoftAttachmentModel.cpp b/libraries/render-utils/src/SoftAttachmentModel.cpp index f364e9c037..63991f9422 100644 --- a/libraries/render-utils/src/SoftAttachmentModel.cpp +++ b/libraries/render-utils/src/SoftAttachmentModel.cpp @@ -43,7 +43,7 @@ void SoftAttachmentModel::updateClusterMatrices() { const FBXGeometry& geometry = getFBXGeometry(); - for (int i = 0; i < _meshStates.size(); i++) { + for (int i = 0; i < (int) _meshStates.size(); i++) { MeshState& state = _meshStates[i]; const FBXMesh& mesh = geometry.meshes.at(i); From 539cf35f30970c031ea0ccc48aa8cadf206b2fd3 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 3 Nov 2017 17:14:27 -0700 Subject: [PATCH 110/183] saving work --- interface/src/raypick/LaserPointer.cpp | 2 +- interface/src/raypick/LaserPointer.h | 2 +- .../controllerModules/farActionGrabEntity.js | 44 ++++++++++++++++++- .../libraries/controllerDispatcherUtils.js | 29 ++++++++++++ 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 75b43a251b..9da8ff34ac 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -233,7 +233,7 @@ void LaserPointer::setLaserLength(const float laserLength) { }); } -void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay) { +void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offset) { withWriteLock([&] { _objectLockEnd = std::pair(objectID, isOverlay); }); diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index f2350c7199..a80f9d447d 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -74,7 +74,7 @@ public: void setPrecisionPicking(const bool precisionPicking); void setLaserLength(const float laserLength); - void setLockEndUUID(QUuid objectID, const bool isOverlay); + void setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offset = glm::mat4()); void setIgnoreItems(const QVector& ignoreItems) const; void setIncludeItems(const QVector& includeItems) const; diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index e34855d521..e63d7c7c35 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -19,6 +19,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); +Script.include("/~/system/libraries/Xform.hs"); (function() { var PICK_WITH_HAND_RAY = true; @@ -113,10 +114,42 @@ Script.include("/~/system/libraries/controllers.js"); ]; var MARGIN = 25; + + function TargetObject(entityID) { + this.entityID = entityID; + this.entityProps = null; + this.parentID = null; + this.parentProps = []; + this.childrenProps = []; + this.parentsCollisionStatus = []; + this.childrenCollisionStatus = []; + this.madeDynamic = null; + this.parentEntityProps = null; + + this.makeDynamic = function() { + }; + + this.saveCollisionStatus = function() { + }; + + this.restoreEntitiesProperties = function() { + }; + + this.getTargetEntity = function() { + var parentPropsLength = this.parentProps.length; + if (parentPropsLength !== 0) { + return this.parentProps[parentPropsLength].id; + } + return this.entityID; + }; + } + function FarActionGrabEntity(hand) { this.hand = hand; this.grabbedThingID = null; + this.targetObject = null; this.actionID = null; // action this script created... + this.entityToLockOnto = null; this.entityWithContextOverlay = false; this.contextOverlayTimer = false; this.previousCollisionStatus = false; @@ -158,7 +191,8 @@ Script.include("/~/system/libraries/controllers.js"); LaserPointers.enableLaserPointer(laserPointerID); LaserPointers.setRenderState(laserPointerID, mode); if (this.distanceHolding || this.distanceRotating) { - LaserPointers.setLockEndUUID(laserPointerID, this.grabbedThingID, this.grabbedIsOverlay); + // calculate offset + LaserPointers.setLockEndUUID(laserPointerID, this.entityToLockOnto, this.grabbedIsOverlay); } else { LaserPointers.setLockEndUUID(laserPointerID, null, false); } @@ -351,6 +385,7 @@ Script.include("/~/system/libraries/controllers.js"); } this.actionID = null; this.grabbedThingID = null; + this.entityToLockOnto = null; }; this.updateRecommendedArea = function() { @@ -497,17 +532,24 @@ Script.include("/~/system/libraries/controllers.js"); if (rayPickInfo.type === RayPick.INTERSECTED_ENTITY) { if (controllerData.triggerClicks[this.hand]) { var entityID = rayPickInfo.objectID; + this.entityToLockOnto = entityID; var targetProps = Entities.getEntityProperties(entityID, [ "dynamic", "shapeType", "position", "rotation", "dimensions", "density", "userData", "locked", "type" ]); + this.targetObject = new TargetObject(entityID); if (entityID !== this.entityWithContextOverlay) { this.destroyContextOverlay(); } if (entityIsGrabbable(targetProps)) { + var groupRootProps = findGroupParent(controllerData, targetProps); + if (entityIsGrabbable(groupRootProps)) { + targetProps = groupRootProps; + entityID = targetProps.id; + } if (!entityIsDistanceGrabbable(targetProps)) { targetProps.dynamic = true; this.previousCollisionStatus = targetProps.collisionless; diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index cd3f1a711f..148530c5ec 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -35,12 +35,14 @@ propsArePhysical:true, controllerDispatcherPluginsNeedSort:true, projectOntoXYPlane:true, + getChildrenProps:true, projectOntoEntityXYPlane:true, projectOntoOverlayXYPlane:true, entityHasActions:true, ensureDynamic:true, findGroupParent:true, BUMPER_ON_VALUE:true, + getEntityParents:true, findHandChildEntities:true, TEAR_AWAY_DISTANCE:true, TEAR_AWAY_COUNT:true, @@ -306,6 +308,33 @@ findGroupParent = function (controllerData, targetProps) { return targetProps; }; +getChildrenProps = function(entityID) { + var childrenProps = []; + var childrenIDs = Entities.getChildrenIDs(entityID); + for (var index = 0; index < childrenIDs.length; index++) { + var childProps = Entities.getEntityProperties(childrenIDs[index]); + childrenProps.push(childProps); + } + return childrenProps; +}; + +getEntityParents = function(targetProps) { + var parentProperties = []; + while (targetProps.parentID && + targetProps.parentID !== Uuid.NULL && + Entities.getNestableType(targetProps.parentID) == "entity") { + var parentProps = Entities.getEntityProperties(targetProps.parentID, DISPATCHER_PROPERTIES); + if (!parentProps) { + break; + } + parentProps.id = targetProps.parentID; + targetProps = parentProps; + parentProperties.push(parentProps); + } + + return parentProperties; +}; + findHandChildEntities = function(hand) { // find children of avatar's hand joint From 6ca9cc02399f30d1034f7d945b47992573a2e99c Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Fri, 3 Nov 2017 18:40:55 -0700 Subject: [PATCH 111/183] Update WASAPI audio plugin --- cmake/externals/wasapi/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/wasapi/CMakeLists.txt b/cmake/externals/wasapi/CMakeLists.txt index 4437024962..4c0ffaf88f 100644 --- a/cmake/externals/wasapi/CMakeLists.txt +++ b/cmake/externals/wasapi/CMakeLists.txt @@ -6,8 +6,8 @@ if (WIN32) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi9.zip - URL_MD5 94f4765bdbcd53cd099f349ae031e769 + URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi10.zip + URL_MD5 4f40e49715a420fb67b45b9cee19052c CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From d4b4d188ed28bdf6875dd66ef34598aa0ad2005b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 4 Nov 2017 13:40:41 -0700 Subject: [PATCH 112/183] allow splitting of edit or add entity packets across multiple edit packets when property list is larger than MTU --- .../entities/src/EntityEditPacketSender.cpp | 42 ++++++++++++------- libraries/entities/src/EntityItem.cpp | 4 +- .../entities/src/EntityItemProperties.cpp | 34 ++++++--------- libraries/entities/src/EntityItemProperties.h | 4 +- libraries/entities/src/EntityPropertyFlags.h | 29 +++++++------ libraries/octree/src/OctreePacketData.cpp | 12 +++++- libraries/octree/src/OctreePacketData.h | 1 + tests/octree/src/OctreeTests.cpp | 2 +- 8 files changed, 71 insertions(+), 57 deletions(-) diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index e82ed82093..168b0cd446 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -93,27 +93,41 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, QByteArray bufferOut(NLPacket::maxPayloadSize(type), 0); - bool success; + OctreeElement::AppendState encodeResult = OctreeElement::PARTIAL; // start the loop assuming there's more to send auto nodeList = DependencyManager::get(); + + EntityPropertyFlags didntFitProperties; + EntityItemProperties propertiesCopy = properties; + if (properties.parentIDChanged() && properties.getParentID() == AVATAR_SELF_ID) { - EntityItemProperties propertiesCopy = properties; const QUuid myNodeID = nodeList->getSessionUUID(); propertiesCopy.setParentID(myNodeID); - success = EntityItemProperties::encodeEntityEditPacket(type, entityItemID, propertiesCopy, bufferOut); - } else { - success = EntityItemProperties::encodeEntityEditPacket(type, entityItemID, properties, bufferOut); } - if (success) { - #ifdef WANT_DEBUG - qCDebug(entities) << "calling queueOctreeEditMessage()..."; - qCDebug(entities) << " id:" << entityItemID; - qCDebug(entities) << " properties:" << properties; - #endif - queueOctreeEditMessage(type, bufferOut); - if (type == PacketType::EntityAdd && !properties.getCertificateID().isEmpty()) { - emit addingEntityWithCertificate(properties.getCertificateID(), DependencyManager::get()->getPlaceName()); + EntityPropertyFlags requestedProperties = propertiesCopy.getChangedProperties(); + + while (encodeResult == OctreeElement::PARTIAL) { + encodeResult = EntityItemProperties::encodeEntityEditPacket(type, entityItemID, propertiesCopy, bufferOut, requestedProperties, didntFitProperties); + + if (encodeResult != OctreeElement::NONE) { + #ifdef WANT_DEBUG + qCDebug(entities) << "calling queueOctreeEditMessage()..."; + qCDebug(entities) << " id:" << entityItemID; + qCDebug(entities) << " properties:" << properties; + #endif + queueOctreeEditMessage(type, bufferOut); + if (type == PacketType::EntityAdd && !properties.getCertificateID().isEmpty()) { + emit addingEntityWithCertificate(properties.getCertificateID(), DependencyManager::get()->getPlaceName()); + } } + + // if we still have properties to send, switch the message type to edit, and request only the packets that didn't fit + if (encodeResult != OctreeElement::COMPLETED) { + type = PacketType::EntityEdit; + requestedProperties = didntFitProperties; + } + + bufferOut.resize(NLPacket::maxPayloadSize(type)); // resize our output buffer for the next packet } } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index f6f4e48a73..3f054e1ccb 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -83,7 +83,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_ANGULAR_VELOCITY; requestedProperties += PROP_ACCELERATION; - requestedProperties += PROP_DIMENSIONS; // NOTE: PROP_RADIUS obsolete + requestedProperties += PROP_DIMENSIONS; requestedProperties += PROP_DENSITY; requestedProperties += PROP_GRAVITY; requestedProperties += PROP_DAMPING; @@ -241,7 +241,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, getLocalAngularVelocity()); APPEND_ENTITY_PROPERTY(PROP_ACCELERATION, getAcceleration()); - APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, getDimensions()); // NOTE: PROP_RADIUS obsolete + APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, getDimensions()); APPEND_ENTITY_PROPERTY(PROP_DENSITY, getDensity()); APPEND_ENTITY_PROPERTY(PROP_GRAVITY, getGravity()); APPEND_ENTITY_PROPERTY(PROP_DAMPING, getDamping()); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index f774b208c4..108fc14e30 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1221,8 +1221,9 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue // // TODO: Implement support for script and visible properties. // -bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItemID id, const EntityItemProperties& properties, - QByteArray& buffer) { +OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItemID id, const EntityItemProperties& properties, + QByteArray& buffer, EntityPropertyFlags requestedProperties, EntityPropertyFlags& didntFitProperties) { + OctreePacketData ourDataPacket(false, buffer.size()); // create a packetData object to add out packet details too. OctreePacketData* packetData = &ourDataPacket; // we want a pointer to this so we can use our APPEND_ENTITY_PROPERTY macro @@ -1264,17 +1265,8 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem QByteArray encodedUpdateDelta = updateDeltaCoder; EntityPropertyFlags propertyFlags(PROP_LAST_ITEM); - EntityPropertyFlags requestedProperties = properties.getChangedProperties(); EntityPropertyFlags propertiesDidntFit = requestedProperties; - // TODO: we need to handle the multi-pass form of this, similar to how we handle entity data - // - // If we are being called for a subsequent pass at appendEntityData() that failed to completely encode this item, - // then our modelTreeElementExtraEncodeData should include data about which properties we need to append. - //if (modelTreeElementExtraEncodeData && modelTreeElementExtraEncodeData->includedItems.contains(getEntityItemID())) { - // requestedProperties = modelTreeElementExtraEncodeData->includedItems.value(getEntityItemID()); - //} - LevelDetails entityLevel = packetData->startLevel(); // Last Edited quint64 always first, before any other details, which allows us easy access to adjusting this @@ -1302,7 +1294,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem int propertyCount = 0; bool headerFits = successIDFits && successTypeFits && successLastEditedFits - && successLastUpdatedFits && successPropertyFlagsFits; + && successLastUpdatedFits && successPropertyFlagsFits; int startOfEntityItemData = packetData->getUncompressedByteOffset(); @@ -1316,7 +1308,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_SIMULATION_OWNER, properties._simulationOwner.toByteArray()); APPEND_ENTITY_PROPERTY(PROP_POSITION, properties.getPosition()); - APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, properties.getDimensions()); // NOTE: PROP_RADIUS obsolete + APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, properties.getDimensions()); APPEND_ENTITY_PROPERTY(PROP_ROTATION, properties.getRotation()); APPEND_ENTITY_PROPERTY(PROP_DENSITY, properties.getDensity()); APPEND_ENTITY_PROPERTY(PROP_VELOCITY, properties.getVelocity()); @@ -1472,6 +1464,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem properties.getType() == EntityTypes::Sphere) { APPEND_ENTITY_PROPERTY(PROP_SHAPE, properties.getShape()); } + APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName()); APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, properties.getCollisionSoundURL()); APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, properties.getActionData()); @@ -1522,12 +1515,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem // If any part of the model items didn't fit, then the element is considered partial if (appendState != OctreeElement::COMPLETED) { - // TODO: handle mechanism for handling partial fitting data! - // add this item into our list for the next appendElementData() pass - //modelTreeElementExtraEncodeData->includedItems.insert(getEntityItemID(), propertiesDidntFit); - - // for now, if it's not complete, it's not successful - success = false; + didntFitProperties = propertiesDidntFit; } } @@ -1543,11 +1531,15 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem } else { qCDebug(entities) << "ERROR - encoded edit message doesn't fit in output buffer."; success = false; + appendState = OctreeElement::NONE; // if we got here, then we didn't include the item + // maybe we should assert!!! } } else { packetData->discardSubTree(); } - return success; + + + return appendState; } QByteArray EntityItemProperties::getPackedNormals() const { @@ -1673,7 +1665,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SIMULATION_OWNER, QByteArray, setSimulationOwner); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_POSITION, glm::vec3, setPosition); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DIMENSIONS, glm::vec3, setDimensions); // NOTE: PROP_RADIUS obsolete + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DIMENSIONS, glm::vec3, setDimensions); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ROTATION, glm::quat, setRotation); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DENSITY, float, setDensity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VELOCITY, glm::vec3, setVelocity); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index a8bb063934..732dbdf69f 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -262,8 +262,8 @@ public: float getLocalRenderAlpha() const { return _localRenderAlpha; } void setLocalRenderAlpha(float value) { _localRenderAlpha = value; _localRenderAlphaChanged = true; } - static bool encodeEntityEditPacket(PacketType command, EntityItemID id, const EntityItemProperties& properties, - QByteArray& buffer); + static OctreeElement::AppendState encodeEntityEditPacket(PacketType command, EntityItemID id, const EntityItemProperties& properties, + QByteArray& buffer, EntityPropertyFlags requestedProperties, EntityPropertyFlags& didntFitProperties); static bool encodeEraseEntityMessage(const EntityItemID& entityItemID, QByteArray& buffer); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index f0f22b0091..35d40b669a 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -21,8 +21,7 @@ enum EntityPropertyList { // these properties are supported by the EntityItem base class PROP_VISIBLE, PROP_POSITION, - PROP_RADIUS, // NOTE: PROP_RADIUS is obsolete and only included in old format streams - PROP_DIMENSIONS = PROP_RADIUS, + PROP_DIMENSIONS, PROP_ROTATION, PROP_DENSITY, PROP_VELOCITY, @@ -47,13 +46,13 @@ enum EntityPropertyList { PROP_ANGULAR_VELOCITY, PROP_ANGULAR_DAMPING, PROP_COLLISIONLESS, - PROP_DYNAMIC, + PROP_DYNAMIC, // 24 // property used by Light entity PROP_IS_SPOTLIGHT, PROP_DIFFUSE_COLOR, - PROP_AMBIENT_COLOR_UNUSED, - PROP_SPECULAR_COLOR_UNUSED, + PROP_AMBIENT_COLOR_UNUSED, // FIXME - No longer used, can remove and bump protocol + PROP_SPECULAR_COLOR_UNUSED, // FIXME - No longer used, can remove and bump protocol PROP_INTENSITY, // Previously PROP_CONSTANT_ATTENUATION PROP_LINEAR_ATTENUATION_UNUSED, PROP_QUADRATIC_ATTENUATION_UNUSED, @@ -61,30 +60,30 @@ enum EntityPropertyList { PROP_CUTOFF, // available to all entities - PROP_LOCKED, + PROP_LOCKED, // 34 PROP_TEXTURES, // used by Model entities - PROP_ANIMATION_SETTINGS, // used by Model entities - PROP_USER_DATA, // all entities + PROP_ANIMATION_SETTINGS_UNUSED, // FIXME - No longer used, can remove and bump protocol + PROP_USER_DATA, // all entities -- 37 PROP_SHAPE_TYPE, // used by Model + zones entities // used by ParticleEffect entities - PROP_MAX_PARTICLES, - PROP_LIFESPAN, + PROP_MAX_PARTICLES, // 39 + PROP_LIFESPAN, // 40 -- used by all entities PROP_EMIT_RATE, PROP_EMIT_SPEED, PROP_EMIT_STRENGTH, - PROP_EMIT_ACCELERATION, - PROP_PARTICLE_RADIUS, + PROP_EMIT_ACCELERATION, // FIXME - doesn't seem to get set in mark all changed???? + PROP_PARTICLE_RADIUS, // 45!! PROP_COMPOUND_SHAPE_URL, // used by Model + zones entities PROP_MARKETPLACE_ID, // all entities PROP_ACCELERATION, // all entities PROP_SIMULATION_OWNER, // formerly known as PROP_SIMULATOR_ID - PROP_NAME, // all entities + PROP_NAME, // all entities -- 50 PROP_COLLISION_SOUND_URL, PROP_RESTITUTION, - PROP_FRICTION, + PROP_FRICTION, // 53 PROP_VOXEL_VOLUME_SIZE, PROP_VOXEL_DATA, @@ -96,7 +95,7 @@ enum EntityPropertyList { // used by hyperlinks PROP_HREF, - PROP_DESCRIPTION, + PROP_DESCRIPTION, // 61 PROP_FACE_CAMERA, PROP_SCRIPT_TIMESTAMP, diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 493dfdcff5..b5b4a161ef 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -68,8 +68,8 @@ bool OctreePacketData::append(const unsigned char* data, int length) { _dirty = true; } - const bool wantDebug = false; - if (wantDebug && !success) { + #ifdef WANT_DEBUG + if (!success) { qCDebug(octree) << "OctreePacketData::append(const unsigned char* data, int length) FAILING...."; qCDebug(octree) << " length=" << length; qCDebug(octree) << " _bytesAvailable=" << _bytesAvailable; @@ -77,6 +77,7 @@ bool OctreePacketData::append(const unsigned char* data, int length) { qCDebug(octree) << " _targetSize=" << _targetSize; qCDebug(octree) << " _bytesReserved=" << _bytesReserved; } + #endif return success; } @@ -647,6 +648,13 @@ void OctreePacketData::debugContent() { printf("\n"); } +void OctreePacketData::debugBytes() { + qCDebug(octree) << " _bytesAvailable=" << _bytesAvailable; + qCDebug(octree) << " _bytesInUse=" << _bytesInUse; + qCDebug(octree) << " _targetSize=" << _targetSize; + qCDebug(octree) << " _bytesReserved=" << _bytesReserved; +} + int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QString& result) { uint16_t length; memcpy(&length, dataBytes, sizeof(length)); diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index ed6a49941b..37c171504b 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -240,6 +240,7 @@ public: /// displays contents for debugging void debugContent(); + void debugBytes(); static quint64 getCompressContentTime() { return _compressContentTime; } /// total time spent compressing content static quint64 getCompressContentCalls() { return _compressContentCalls; } /// total calls to compress content diff --git a/tests/octree/src/OctreeTests.cpp b/tests/octree/src/OctreeTests.cpp index 64d68e8e13..81300a1293 100644 --- a/tests/octree/src/OctreeTests.cpp +++ b/tests/octree/src/OctreeTests.cpp @@ -74,7 +74,7 @@ void OctreeTests::propertyFlagsTests() { EntityPropertyFlags props; props.setHasProperty(PROP_VISIBLE); props.setHasProperty(PROP_POSITION); - props.setHasProperty(PROP_RADIUS); + props.setHasProperty(PROP_DIMENSIONS); props.setHasProperty(PROP_MODEL_URL); props.setHasProperty(PROP_COMPOUND_SHAPE_URL); props.setHasProperty(PROP_ROTATION); From 4a5f52155c8d60a0e7e52a56805691a01ab7c8f5 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 5 Nov 2017 14:33:30 +1300 Subject: [PATCH 113/183] Pin node pointer --- assignment-client/src/entities/EntityTreeSendThread.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index e96a9dc667..f5f8450de7 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -425,7 +425,8 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream uint64_t sendTime = usecTimestampNow(); auto nodeData = static_cast(params.nodeData); nodeData->stats.encodeStarted(); - auto entityNodeData = static_cast(_node.toStrongRef()->getLinkedData()); + auto entityNode = _node.toStrongRef(); + auto entityNodeData = static_cast(entityNode->getLinkedData()); while(!_sendQueue.empty()) { PrioritizedEntity queuedItem = _sendQueue.top(); EntityItemPointer entity = queuedItem.getEntity(); From a76b7855b5d29b887af4784fc538d33a0365272c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 5 Nov 2017 15:03:43 +1300 Subject: [PATCH 114/183] Record only explicitly filtered-in entities for flagging extras --- assignment-client/src/entities/EntityTreeSendThread.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index f5f8450de7..a259dacecd 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -432,8 +432,12 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream EntityItemPointer entity = queuedItem.getEntity(); if (entity) { // Only send entities that match the jsonFilters, but keep track of everything we've tried to send so we don't try to send it again - if (entity->matchesJSONFilters(jsonFilters) || entityNodeData->isEntityFlaggedAsExtra(entity->getID())) { - entityNodeData->insertSentFilteredEntity(entity->getID()); + bool entityMatchesFilters = entity->matchesJSONFilters(jsonFilters); + if (entityMatchesFilters || entityNodeData->isEntityFlaggedAsExtra(entity->getID())) { + if (!jsonFilters.isEmpty() && entityMatchesFilters) { + // Record explicitly filtered-in entity so that extra entities can be flagged. + entityNodeData->insertSentFilteredEntity(entity->getID()); + } OctreeElement::AppendState appendEntityState = entity->appendEntityData(&_packetData, params, _extraEncodeData); if (appendEntityState != OctreeElement::COMPLETED) { From 05275afb4fe034461354cf1f8e0ebd3ba70969a6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 5 Nov 2017 15:48:02 +1300 Subject: [PATCH 115/183] Resending full scene is not necessary after all --- assignment-client/src/entities/EntityTreeSendThread.cpp | 6 +++--- assignment-client/src/entities/EntityTreeSendThread.h | 2 +- libraries/entities/src/DiffTraversal.cpp | 4 ++-- libraries/entities/src/DiffTraversal.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index a259dacecd..11e4d533fb 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -96,7 +96,7 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O nodeData->copyCurrentViewFrustum(viewFrustum); EntityTreeElementPointer root = std::dynamic_pointer_cast(_myServer->getOctree()->getRoot()); int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST); - startNewTraversal(viewFrustum, root, lodLevelOffset, nodeData->getUsesFrustum(), isFullScene); + startNewTraversal(viewFrustum, root, lodLevelOffset, nodeData->getUsesFrustum()); // When the viewFrustum changed the sort order may be incorrect, so we re-sort // and also use the opportunity to cull anything no longer in view @@ -205,9 +205,9 @@ bool EntityTreeSendThread::addDescendantsToExtraFlaggedEntities(const QUuid& fil } void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root, int32_t lodLevelOffset, - bool usesViewFrustum, bool isFullScene) { + bool usesViewFrustum) { - DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset, usesViewFrustum, isFullScene); + DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset, usesViewFrustum); // there are three types of traversal: // // (1) FirstTime = at login --> find everything in view diff --git a/assignment-client/src/entities/EntityTreeSendThread.h b/assignment-client/src/entities/EntityTreeSendThread.h index 1781de9890..a96a18494d 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.h +++ b/assignment-client/src/entities/EntityTreeSendThread.h @@ -39,7 +39,7 @@ private: bool addDescendantsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData); void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, - bool usesViewFrustum, bool isFullScene); + bool usesViewFrustum); bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override; void preDistributionProcessing() override; diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp index 9b16ee90bf..764c420197 100644 --- a/libraries/entities/src/DiffTraversal.cpp +++ b/libraries/entities/src/DiffTraversal.cpp @@ -143,7 +143,7 @@ DiffTraversal::DiffTraversal() { } DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, - int32_t lodLevelOffset, bool usesViewFrustum, bool isFullScene) { + int32_t lodLevelOffset, bool usesViewFrustum) { assert(root); // there are three types of traversal: // @@ -164,7 +164,7 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFr Type type; // If usesViewFrustum changes, treat it as a First traversal - if (_completedView.startTime == 0 || _currentView.usesViewFrustum != _completedView.usesViewFrustum || isFullScene) { + if (_completedView.startTime == 0 || _currentView.usesViewFrustum != _completedView.usesViewFrustum) { type = Type::First; _currentView.viewFrustum = viewFrustum; _currentView.lodScaleFactor = lodScaleFactor; diff --git a/libraries/entities/src/DiffTraversal.h b/libraries/entities/src/DiffTraversal.h index becf322fd5..eb7168356e 100644 --- a/libraries/entities/src/DiffTraversal.h +++ b/libraries/entities/src/DiffTraversal.h @@ -58,7 +58,7 @@ public: DiffTraversal(); Type prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, - bool usesViewFrustum, bool isFullScene); + bool usesViewFrustum); const ViewFrustum& getCurrentView() const { return _currentView.viewFrustum; } const ViewFrustum& getCompletedView() const { return _completedView.viewFrustum; } From 9db0dd6fea01773b03f83fc65c6766b8da9952e2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 5 Nov 2017 20:38:37 +1300 Subject: [PATCH 116/183] Fix Asset Browser's "Copy URL" context menu --- interface/resources/qml/hifi/AssetServer.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/AssetServer.qml b/interface/resources/qml/hifi/AssetServer.qml index 5358ad1adc..37c3c2adab 100644 --- a/interface/resources/qml/hifi/AssetServer.qml +++ b/interface/resources/qml/hifi/AssetServer.qml @@ -16,10 +16,10 @@ import Qt.labs.settings 1.0 import "../styles-uit" import "../controls-uit" as HifiControls -import "../windows" +import "../windows" as Windows import "../dialogs" -ScrollingWindow { +Windows.ScrollingWindow { id: root objectName: "AssetServer" title: "Asset Browser" From e2ca3c6de04e6662f83ff80f550871220bd8afb8 Mon Sep 17 00:00:00 2001 From: Midnight Date: Sun, 5 Nov 2017 13:39:26 -0700 Subject: [PATCH 117/183] Fix lib file path Changed the include to what should be the correct file path. it does not exist in the controllers folder. --- scripts/system/libraries/cloneEntityUtils.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/system/libraries/cloneEntityUtils.js b/scripts/system/libraries/cloneEntityUtils.js index 777504b16d..63b161eb80 100644 --- a/scripts/system/libraries/cloneEntityUtils.js +++ b/scripts/system/libraries/cloneEntityUtils.js @@ -8,8 +8,7 @@ /* global entityIsCloneable:true, getGrabbableData:true, cloneEntity:true, propsAreCloneDynamic:true, Script, propsAreCloneDynamic:true, Entities*/ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); - +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); // Object assign polyfill if (typeof Object.assign !== 'function') { From 9e6472b57783c514e34121941956fcceed902cc1 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 6 Nov 2017 15:55:57 +0100 Subject: [PATCH 118/183] Added OutlineStyleStage --- .../ui/overlays/ContextOverlayInterface.cpp | 20 ++- .../src/ui/overlays/ContextOverlayInterface.h | 8 +- libraries/render-utils/src/OutlineEffect.cpp | 151 ++++++++++++------ libraries/render-utils/src/OutlineEffect.h | 89 ++++++----- .../render-utils/src/RenderDeferredTask.cpp | 16 +- .../render-utils/src/UpdateSceneTask.cpp | 2 + libraries/render/src/render/FilterTask.cpp | 7 +- libraries/render/src/render/FilterTask.h | 5 +- libraries/render/src/render/OutlineStyle.h | 39 +++++ .../render/src/render/OutlineStyleStage.cpp | 46 ++++++ .../render/src/render/OutlineStyleStage.h | 77 +++++++++ libraries/render/src/render/Scene.cpp | 64 ++++++++ libraries/render/src/render/Scene.h | 22 ++- 13 files changed, 427 insertions(+), 119 deletions(-) create mode 100644 libraries/render/src/render/OutlineStyle.h create mode 100644 libraries/render/src/render/OutlineStyleStage.cpp create mode 100644 libraries/render/src/render/OutlineStyleStage.h diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 1e9f827cb2..32e4137526 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -68,11 +68,15 @@ ContextOverlayInterface::ContextOverlayInterface() { connect(&qApp->getOverlays(), &Overlays::hoverEnterOverlay, this, &ContextOverlayInterface::contextOverlays_hoverEnterOverlay); connect(&qApp->getOverlays(), &Overlays::hoverLeaveOverlay, this, &ContextOverlayInterface::contextOverlays_hoverLeaveOverlay); - _selectionToSceneHandlers[0].initialize("contextOverlayHighlightList"); - connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandlers[0], &SelectionToSceneHandler::selectedItemsListChanged); - for (auto i = 1; i < render::Scene::MAX_OUTLINE_COUNT; i++) { - _selectionToSceneHandlers[i].initialize(QString("contextOverlayHighlightList") + QString::number(i)); - connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandlers[i], &SelectionToSceneHandler::selectedItemsListChanged); + { + render::Transaction transaction; + initializeSelectionToSceneHandler(_selectionToSceneHandlers[0], "contextOverlayHighlightList", transaction); + for (auto i = 1; i < MAX_SELECTION_COUNT; i++) { + auto selectionName = QString("contextOverlayHighlightList") + QString::number(i); + initializeSelectionToSceneHandler(_selectionToSceneHandlers[i], selectionName, transaction); + } + const render::ScenePointer& scene = qApp->getMain3DScene(); + scene->enqueueTransaction(transaction); } auto nodeList = DependencyManager::get(); @@ -81,6 +85,12 @@ ContextOverlayInterface::ContextOverlayInterface() { _challengeOwnershipTimeoutTimer.setSingleShot(true); } +void ContextOverlayInterface::initializeSelectionToSceneHandler(SelectionToSceneHandler& handler, const QString& selectionName, render::Transaction& transaction) { + handler.initialize(selectionName); + connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &handler, &SelectionToSceneHandler::selectedItemsListChanged); + transaction.resetSelectionOutline(selectionName.toStdString()); +} + static const uint32_t MOUSE_HW_ID = 0; static const uint32_t LEFT_HAND_HW_ID = 1; static const xColor CONTEXT_OVERLAY_COLOR = { 255, 255, 255 }; diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index e5ebcdcff3..81e398e15d 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -76,6 +76,11 @@ private slots: void handleChallengeOwnershipReplyPacket(QSharedPointer packet, SharedNodePointer sendingNode); private: + + enum { + MAX_SELECTION_COUNT = 16 + }; + bool _verboseLogging { true }; bool _enabled { true }; EntityItemID _currentEntityWithContextOverlay{}; @@ -91,8 +96,9 @@ private: void disableEntityHighlight(const EntityItemID& entityItemID); void deletingEntity(const EntityItemID& entityItemID); + void initializeSelectionToSceneHandler(SelectionToSceneHandler& handler, const QString& selectionName, render::Transaction& transaction); - SelectionToSceneHandler _selectionToSceneHandlers[render::Scene::MAX_OUTLINE_COUNT]; + SelectionToSceneHandler _selectionToSceneHandlers[MAX_SELECTION_COUNT]; Q_INVOKABLE void startChallengeOwnershipTimer(); QTimer _challengeOwnershipTimeoutTimer; diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index a42cbfe358..590277bf6d 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -83,7 +83,11 @@ gpu::FramebufferPointer OutlineRessources::getColorFramebuffer() { } OutlineSharedParameters::OutlineSharedParameters() { - std::fill(_blurPixelWidths.begin(), _blurPixelWidths.end(), 0); + _outlineIds.fill(render::OutlineStyleStage::INVALID_INDEX); +} + +float OutlineSharedParameters::getBlurPixelWidth(const render::OutlineStyle& style, int frameBufferHeight) { + return ceilf(style.width * frameBufferHeight / 400.0f); } PrepareDrawOutline::PrepareDrawOutline() { @@ -141,8 +145,12 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con _boundsBuffer = std::make_shared(sizeof(render::ItemBound)); } - if (!inShapes.empty()) { + auto outlineStage = renderContext->_scene->getStage(render::OutlineStyleStage::getName()); + auto outlineId = _sharedParameters->_outlineIds[_outlineIndex]; + + if (!inShapes.empty() && !render::OutlineStyleStage::isIndexInvalid(outlineId)) { auto ressources = inputs.get1(); + auto& outline = outlineStage->getOutline(outlineId); RenderArgs* args = renderContext->args; ShapeKey::Builder defaultKeyBuilder; @@ -213,10 +221,10 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con // Draw stencil mask with object bounding boxes const auto outlineWidthLoc = _stencilMaskPipeline->getProgram()->getUniforms().findLocation("outlineWidth"); const auto sqrt3 = 1.74f; - const float blurPixelWidth = 2.0f * sqrt3 *_sharedParameters->_blurPixelWidths[_outlineIndex]; + const float blurPixelWidth = 2.0f * sqrt3 * OutlineSharedParameters::getBlurPixelWidth(outline._style, args->_viewport.w); const auto framebufferSize = ressources->getSourceFrameSize(); - auto stencilPipeline = _sharedParameters->_isFilled.test(_outlineIndex) ? _stencilMaskFillPipeline : _stencilMaskPipeline; + auto stencilPipeline = outline._style.isFilled() ? _stencilMaskFillPipeline : _stencilMaskPipeline; batch.setPipeline(stencilPipeline); batch.setResourceBuffer(0, _boundsBuffer); batch._glUniform2f(outlineWidthLoc, blurPixelWidth / framebufferSize.x, blurPixelWidth / framebufferSize.y); @@ -237,24 +245,6 @@ DrawOutline::DrawOutline(unsigned int outlineIndex, OutlineSharedParametersPoint _sharedParameters{ parameters } { } -void DrawOutline::configure(const Config& config) { - const auto OPACITY_EPSILON = 5e-3f; - - _parameters._color = config.color; - _parameters._intensity = config.intensity * (config.glow ? 2.0f : 1.0f); - _parameters._unoccludedFillOpacity = config.unoccludedFillOpacity; - _parameters._occludedFillOpacity = config.occludedFillOpacity; - _parameters._threshold = config.glow ? 1.0f : 1e-3f; - _parameters._blurKernelSize = std::min(7, std::max(2, (int)floorf(config.width * 3 + 0.5f))); - // Size is in normalized screen height. We decide that for outline width = 1, this is equal to 1/400. - _size = config.width / 400.0f; - _parameters._size.x = (_size * _framebufferSize.y) / _framebufferSize.x; - _parameters._size.y = _size; - _sharedParameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y); - _sharedParameters->_isFilled.set(_outlineIndex, (config.unoccludedFillOpacity > OPACITY_EPSILON || config.occludedFillOpacity > OPACITY_EPSILON)); - _configuration.edit() = _parameters; -} - void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { auto outlineFrameBuffer = inputs.get1(); auto outlineRect = inputs.get3(); @@ -267,39 +257,50 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I auto framebufferSize = glm::ivec2(outlinedDepthTexture->getDimensions()); if (sceneDepthBuffer) { - auto pipeline = getPipeline(); auto args = renderContext->args; - if (_framebufferSize != framebufferSize) - { - _parameters._size.x = (_size * framebufferSize.y) / framebufferSize.x; - _parameters._size.y = _size; - _framebufferSize = framebufferSize; - _sharedParameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y); - _configuration.edit() = _parameters; + auto outlineStage = renderContext->_scene->getStage(render::OutlineStyleStage::getName()); + auto outlineId = _sharedParameters->_outlineIds[_outlineIndex]; + if (!render::OutlineStyleStage::isIndexInvalid(outlineId)) { + auto& outline = outlineStage->getOutline(_sharedParameters->_outlineIds[_outlineIndex]); + auto pipeline = getPipeline(outline._style); + { + auto& shaderParameters = _configuration.edit(); + + shaderParameters._color = outline._style.color; + shaderParameters._intensity = outline._style.intensity * (outline._style.glow ? 2.0f : 1.0f); + shaderParameters._unoccludedFillOpacity = outline._style.unoccludedFillOpacity; + shaderParameters._occludedFillOpacity = outline._style.occludedFillOpacity; + shaderParameters._threshold = outline._style.glow ? 1.0f : 1e-3f; + shaderParameters._blurKernelSize = std::min(7, std::max(2, (int)floorf(outline._style.width * 3 + 0.5f))); + // Size is in normalized screen height. We decide that for outline width = 1, this is equal to 1/400. + auto size = outline._style.width / 400.0f; + shaderParameters._size.x = (size * framebufferSize.y) / framebufferSize.x; + shaderParameters._size.y = size; + } + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setFramebuffer(destinationFrameBuffer); + + batch.setViewportTransform(args->_viewport); + batch.setProjectionTransform(glm::mat4()); + batch.resetViewTransform(); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); + batch.setPipeline(pipeline); + + batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); + batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer()); + batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getPrimaryDepthTexture()); + batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthTexture); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); } - - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - batch.enableStereo(false); - batch.setFramebuffer(destinationFrameBuffer); - - batch.setViewportTransform(args->_viewport); - batch.setProjectionTransform(glm::mat4()); - batch.resetViewTransform(); - batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); - batch.setPipeline(pipeline); - - batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); - batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer()); - batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getPrimaryDepthTexture()); - batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthTexture); - batch.draw(gpu::TRIANGLE_STRIP, 4); - }); } } } -const gpu::PipelinePointer& DrawOutline::getPipeline() { +const gpu::PipelinePointer& DrawOutline::getPipeline(const render::OutlineStyle& style) { if (!_pipeline) { gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setDepthTest(gpu::State::DepthTest(false, false)); @@ -324,7 +325,7 @@ const gpu::PipelinePointer& DrawOutline::getPipeline() { gpu::Shader::makeProgram(*program, slotBindings); _pipelineFilled = gpu::Pipeline::create(program, state); } - return _sharedParameters->_isFilled.test(_outlineIndex) ? _pipelineFilled : _pipeline; + return style.isFilled() ? _pipelineFilled : _pipeline; } DebugOutline::DebugOutline() { @@ -424,6 +425,35 @@ const gpu::PipelinePointer& DebugOutline::getDepthPipeline() { return _depthPipeline; } +void SelectionToOutline::run(const render::RenderContextPointer& renderContext, Outputs& outputs) { + auto outlineStage = renderContext->_scene->getStage(render::OutlineStyleStage::getName()); + + outputs.clear(); + _sharedParameters->_outlineIds.fill(render::OutlineStyleStage::INVALID_INDEX); + + for (auto i = 0; i < OutlineSharedParameters::MAX_OUTLINE_COUNT; i++) { + std::ostringstream stream; + stream << "contextOverlayHighlightList"; + if (i > 0) { + stream << i; + } + auto selectionName = stream.str(); + auto outlineId = outlineStage->getOutlineIdBySelection(selectionName); + if (!render::OutlineStyleStage::isIndexInvalid(outlineId)) { + _sharedParameters->_outlineIds[outputs.size()] = outlineId; + outputs.emplace_back(selectionName); + } + } +} + +void ExtractSelectionName::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { + if (_outlineIndex < inputs.size()) { + outputs = inputs[_outlineIndex]; + } else { + outputs.clear(); + } +} + DrawOutlineTask::DrawOutlineTask() { } @@ -433,7 +463,7 @@ void DrawOutlineTask::configure(const Config& config) { } void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { - const auto groups = inputs.getN(0).get(); + const auto items = inputs.getN(0).get(); const auto sceneFrameBuffer = inputs.getN(1); const auto primaryFramebuffer = inputs.getN(2); const auto deferredFrameTransform = inputs.getN(3); @@ -449,12 +479,15 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende } auto sharedParameters = std::make_shared(); + const auto outlineSelectionNames = task.addJob("SelectionToOutline", sharedParameters); + // Prepare for outline group rendering. const auto outlineRessources = task.addJob("PrepareOutline", primaryFramebuffer); render::Varying outline0Rect; - for (auto i = 0; i < render::Scene::MAX_OUTLINE_COUNT; i++) { - const auto groupItems = groups[i]; + for (auto i = 0; i < OutlineSharedParameters::MAX_OUTLINE_COUNT; i++) { + const auto selectionName = task.addJob("ExtractSelectionName", outlineSelectionNames, i); + const auto groupItems = addSelectItemJobs(task, selectionName, items); const auto outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", groupItems); const auto outlinedItems = task.addJob("OutlineMetaToSubItems", outlinedItemIDs); @@ -490,6 +523,20 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende task.addJob("OutlineDebug", debugInputs); } +const render::Varying DrawOutlineTask::addSelectItemJobs(JobModel& task, const render::Varying& selectionName, + const RenderFetchCullSortTask::BucketList& items) { + const auto& opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE]; + const auto& transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; + const auto& metas = items[RenderFetchCullSortTask::META]; + + const auto selectMetaInput = SelectItems::Inputs(metas, Varying(), selectionName).asVarying(); + const auto selectedMetas = task.addJob("MetaSelection", selectMetaInput); + const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas, selectionName).asVarying(); + const auto selectedMetasAndOpaques = task.addJob("OpaqueSelection", selectMetaAndOpaqueInput); + const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques, selectionName).asVarying(); + return task.addJob("TransparentSelection", selectItemInput); +} + #include "model_shadow_vert.h" #include "skin_model_shadow_vert.h" diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index a2bfc88c81..e25184eb5b 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -13,6 +13,9 @@ #define hifi_render_utils_OutlineEffect_h #include +#include +#include + #include "DeferredFramebuffer.h" #include "DeferredFrameTransform.h" @@ -46,10 +49,15 @@ using OutlineRessourcesPointer = std::shared_ptr; class OutlineSharedParameters { public: + enum { + MAX_OUTLINE_COUNT = 8 + }; + OutlineSharedParameters(); - std::array _blurPixelWidths; - std::bitset _isFilled; + std::array _outlineIds; + + static float getBlurPixelWidth(const render::OutlineStyle& style, int frameBufferHeight); }; using OutlineSharedParametersPointer = std::shared_ptr; @@ -70,6 +78,38 @@ private: }; +class SelectionToOutline { +public: + + using Outputs = std::vector; + using JobModel = render::Job::ModelO; + + SelectionToOutline(OutlineSharedParametersPointer parameters) : _sharedParameters{ parameters } {} + + void run(const render::RenderContextPointer& renderContext, Outputs& outputs); + +private: + + OutlineSharedParametersPointer _sharedParameters; +}; + +class ExtractSelectionName { +public: + + using Inputs = SelectionToOutline::Outputs; + using Outputs = std::string; + using JobModel = render::Job::ModelIO; + + ExtractSelectionName(unsigned int outlineIndex) : _outlineIndex{ outlineIndex } {} + + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); + +private: + + unsigned int _outlineIndex; + +}; + class DrawOutlineMask { public: @@ -92,49 +132,15 @@ protected: static gpu::PipelinePointer _stencilMaskFillPipeline; }; -class DrawOutlineConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(bool glow MEMBER glow NOTIFY dirty) - Q_PROPERTY(float width MEMBER width NOTIFY dirty) - Q_PROPERTY(float intensity MEMBER intensity NOTIFY dirty) - Q_PROPERTY(float colorR READ getColorR WRITE setColorR NOTIFY dirty) - Q_PROPERTY(float colorG READ getColorG WRITE setColorG NOTIFY dirty) - Q_PROPERTY(float colorB READ getColorB WRITE setColorB NOTIFY dirty) - Q_PROPERTY(float unoccludedFillOpacity MEMBER unoccludedFillOpacity NOTIFY dirty) - Q_PROPERTY(float occludedFillOpacity MEMBER occludedFillOpacity NOTIFY dirty) - -public: - - void setColorR(float value) { color.r = value; emit dirty(); } - float getColorR() const { return color.r; } - - void setColorG(float value) { color.g = value; emit dirty(); } - float getColorG() const { return color.g; } - - void setColorB(float value) { color.b = value; emit dirty(); } - float getColorB() const { return color.b; } - - glm::vec3 color{ 1.f, 0.7f, 0.2f }; - float width{ 2.0f }; - float intensity{ 0.9f }; - float unoccludedFillOpacity{ 0.0f }; - float occludedFillOpacity{ 0.0f }; - bool glow{ false }; - -signals: - void dirty(); -}; - class DrawOutline { public: using Inputs = render::VaryingSet4; - using Config = DrawOutlineConfig; + using Config = render::Job::Config; using JobModel = render::Job::ModelI; DrawOutline(unsigned int outlineIndex, OutlineSharedParametersPointer parameters); - void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); private: @@ -151,7 +157,7 @@ private: using OutlineConfigurationBuffer = gpu::StructBuffer; - const gpu::PipelinePointer& getPipeline(); + static const gpu::PipelinePointer& getPipeline(const render::OutlineStyle& style); static gpu::PipelinePointer _pipeline; static gpu::PipelinePointer _pipelineFilled; @@ -160,8 +166,6 @@ private: OutlineParameters _parameters; OutlineSharedParametersPointer _sharedParameters; OutlineConfigurationBuffer _configuration; - glm::ivec2 _framebufferSize{ 0,0 }; - float _size; }; class DebugOutlineConfig : public render::Job::Config { @@ -201,8 +205,7 @@ private: class DrawOutlineTask { public: - using Groups = render::VaryingArray; - using Inputs = render::VaryingSet4; + using Inputs = render::VaryingSet4; using Config = render::Task::Config; using JobModel = render::Task::ModelI; @@ -214,6 +217,8 @@ public: private: static void initMaskPipelines(render::ShapePlumber& plumber, gpu::StatePointer state); + static const render::Varying addSelectItemJobs(JobModel& task, const render::Varying& selectionName, const RenderFetchCullSortTask::BucketList& items); + }; #endif // hifi_render_utils_OutlineEffect_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 16db1281f5..52b8896e69 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -64,11 +64,11 @@ const render::Varying RenderDeferredTask::addSelectItemJobs(JobModel& task, cons const render::Varying& metas, const render::Varying& opaques, const render::Varying& transparents) { - const auto selectMetaInput = SelectItems::Inputs(metas, Varying()).asVarying(); + const auto selectMetaInput = SelectItems::Inputs(metas, Varying(), std::string()).asVarying(); const auto selectedMetas = task.addJob("MetaSelection", selectMetaInput, selectionName); - const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas).asVarying(); + const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas, std::string()).asVarying(); const auto selectedMetasAndOpaques = task.addJob("OpaqueSelection", selectMetaAndOpaqueInput, selectionName); - const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques).asVarying(); + const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques, std::string()).asVarying(); return task.addJob("TransparentSelection", selectItemInput, selectionName); } @@ -187,16 +187,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Select items that need to be outlined const auto selectionBaseName = "contextOverlayHighlightList"; const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents); - DrawOutlineTask::Groups outlineGroups; - outlineGroups[0] = selectedItems; - for (auto i = 1; i < render::Scene::MAX_OUTLINE_COUNT; i++) { - std::ostringstream selectionName; - selectionName << selectionBaseName; - selectionName << i; - outlineGroups[i] = addSelectItemJobs(task, selectionName.str().c_str(), metas, opaques, transparents); - } - const auto outlineInputs = DrawOutlineTask::Inputs(outlineGroups, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); + const auto outlineInputs = DrawOutlineTask::Inputs(items.get0(), deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); task.addJob("DrawOutline", outlineInputs); task.addJob("OutlineRangeTimer", outlineRangeTimer); diff --git a/libraries/render-utils/src/UpdateSceneTask.cpp b/libraries/render-utils/src/UpdateSceneTask.cpp index 06e02907f2..d37569b526 100644 --- a/libraries/render-utils/src/UpdateSceneTask.cpp +++ b/libraries/render-utils/src/UpdateSceneTask.cpp @@ -15,6 +15,7 @@ #include "BackgroundStage.h" #include "HazeStage.h" #include +#include #include "DeferredLightingEffect.h" void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { @@ -22,6 +23,7 @@ void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render task.addJob("BackgroundStageSetup"); task.addJob("HazeStageSetup"); task.addJob("TransitionStageSetup"); + task.addJob("OutlineStyleStageSetup"); task.addJob("DefaultLightingSetup"); diff --git a/libraries/render/src/render/FilterTask.cpp b/libraries/render/src/render/FilterTask.cpp index f60f5895b7..20d29f3e5d 100644 --- a/libraries/render/src/render/FilterTask.cpp +++ b/libraries/render/src/render/FilterTask.cpp @@ -57,7 +57,12 @@ void SliceItems::run(const RenderContextPointer& renderContext, const ItemBounds } void SelectItems::run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems) { - auto selection = renderContext->_scene->getSelection(_name); + auto selectionName{ _name }; + if (!inputs.get2().empty()) { + selectionName = inputs.get2(); + } + + auto selection = renderContext->_scene->getSelection(selectionName); const auto& selectedItems = selection.getItems(); const auto& inItems = inputs.get0(); const auto itemsToAppend = inputs[1]; diff --git a/libraries/render/src/render/FilterTask.h b/libraries/render/src/render/FilterTask.h index a7180b6cde..9b40728b00 100644 --- a/libraries/render/src/render/FilterTask.h +++ b/libraries/render/src/render/FilterTask.h @@ -113,12 +113,13 @@ namespace render { // Keep items belonging to the job selection class SelectItems { public: - using Inputs = VaryingSet2; + using Inputs = VaryingSet3; using JobModel = Job::ModelIO; std::string _name; + SelectItems() {} SelectItems(const Selection::Name& name) : _name(name) {} - + void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems); }; diff --git a/libraries/render/src/render/OutlineStyle.h b/libraries/render/src/render/OutlineStyle.h new file mode 100644 index 0000000000..cdcdf79f3e --- /dev/null +++ b/libraries/render/src/render/OutlineStyle.h @@ -0,0 +1,39 @@ +// +// OutlineStyle.h + +// Created by Olivier Prat on 11/06/2017. +// Copyright 2017 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 +// + +#ifndef hifi_render_utils_OutlineStyle_h +#define hifi_render_utils_OutlineStyle_h + +#include + +#include + +namespace render { + + // This holds the configuration for a particular outline style + class OutlineStyle { + public: + + bool isFilled() const { + return unoccludedFillOpacity > 5e-3f || occludedFillOpacity > 5e-3f; + } + + glm::vec3 color{ 1.f, 0.7f, 0.2f }; + float width{ 2.0f }; + float intensity{ 0.9f }; + float unoccludedFillOpacity{ 0.0f }; + float occludedFillOpacity{ 0.0f }; + bool glow{ false }; + std::string selectionName; + }; + +} + +#endif // hifi_render_utils_OutlineStyle_h \ No newline at end of file diff --git a/libraries/render/src/render/OutlineStyleStage.cpp b/libraries/render/src/render/OutlineStyleStage.cpp new file mode 100644 index 0000000000..e3fd1672de --- /dev/null +++ b/libraries/render/src/render/OutlineStyleStage.cpp @@ -0,0 +1,46 @@ +#include "OutlineStyleStage.h" + +using namespace render; + +std::string OutlineStyleStage::_name("OutlineStyle"); + +OutlineStyleStage::Index OutlineStyleStage::addOutline(const std::string& selectionName, const OutlineStyle& style) { + Outline outline{ selectionName, style }; + Index id; + + id = _outlines.newElement(outline); + _activeOutlineIds.push_back(id); + + return id; +} + +void OutlineStyleStage::removeOutline(Index index) { + OutlineIdList::iterator idIterator = std::find(_activeOutlineIds.begin(), _activeOutlineIds.end(), index); + if (idIterator != _activeOutlineIds.end()) { + _activeOutlineIds.erase(idIterator); + } + if (!_outlines.isElementFreed(index)) { + _outlines.freeElement(index); + } +} + +Index OutlineStyleStage::getOutlineIdBySelection(const std::string& selectionName) const { + for (auto outlineId : _activeOutlineIds) { + const auto& outline = _outlines.get(outlineId); + if (outline._selectionName == selectionName) { + return outlineId; + } + } + return INVALID_INDEX; +} + +OutlineStyleStageSetup::OutlineStyleStageSetup() { +} + +void OutlineStyleStageSetup::run(const render::RenderContextPointer& renderContext) { + if (!renderContext->_scene->getStage(OutlineStyleStage::getName())) { + auto stage = std::make_shared(); + renderContext->_scene->resetStage(OutlineStyleStage::getName(), stage); + } +} + diff --git a/libraries/render/src/render/OutlineStyleStage.h b/libraries/render/src/render/OutlineStyleStage.h new file mode 100644 index 0000000000..79835a22a4 --- /dev/null +++ b/libraries/render/src/render/OutlineStyleStage.h @@ -0,0 +1,77 @@ +// +// OutlineStyleStage.h + +// Created by Olivier Prat on 07/07/2017. +// Copyright 2017 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 +// + +#ifndef hifi_render_utils_outlinestage_h +#define hifi_render_utils_outlinestage_h + +#include "Stage.h" +#include "Engine.h" +#include "IndexedContainer.h" +#include "OutlineStyle.h" + +namespace render { + + // OutlineStyle stage to set up OutlineStyle-related effects + class OutlineStyleStage : public Stage { + public: + + class Outline { + public: + + Outline(const std::string& selectionName, const OutlineStyle& style) : _selectionName{ selectionName }, _style{ style } { } + + std::string _selectionName; + OutlineStyle _style; + + }; + + static const std::string& getName() { return _name; } + + using Index = render::indexed_container::Index; + static const Index INVALID_INDEX{ render::indexed_container::INVALID_INDEX }; + using OutlineIdList = render::indexed_container::Indices; + + static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } + + bool checkOutlineId(Index index) const { return _outlines.checkIndex(index); } + + const Outline& getOutline(Index OutlineStyleId) const { return _outlines.get(OutlineStyleId); } + Outline& editOutline(Index OutlineStyleId) { return _outlines.edit(OutlineStyleId); } + + Index addOutline(const std::string& selectionName, const OutlineStyle& style = OutlineStyle()); + Index getOutlineIdBySelection(const std::string& selectionName) const; + void removeOutline(Index index); + + OutlineIdList::iterator begin() { return _activeOutlineIds.begin(); } + OutlineIdList::iterator end() { return _activeOutlineIds.end(); } + + private: + + using Outlines = render::indexed_container::IndexedVector; + + static std::string _name; + + Outlines _outlines; + OutlineIdList _activeOutlineIds; + }; + using OutlineStyleStagePointer = std::shared_ptr; + + class OutlineStyleStageSetup { + public: + using JobModel = render::Job::Model; + + OutlineStyleStageSetup(); + void run(const RenderContextPointer& renderContext); + + protected: + }; + +} +#endif // hifi_render_utils_outlinestage_h diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 714be2a8c6..0e680dfdaf 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -14,6 +14,7 @@ #include #include "Logging.h" #include "TransitionStage.h" +#include "OutlineStyleStage.h" using namespace render; @@ -54,6 +55,18 @@ void Transaction::resetSelection(const Selection& selection) { _resetSelections.emplace_back(selection); } +void Transaction::resetSelectionOutline(const std::string& selectionName, const OutlineStyle& style) { + _outlineResets.emplace_back(OutlineReset{ selectionName, style }); +} + +void Transaction::removeOutlineFromSelection(const std::string& selectionName) { + _outlineRemoves.emplace_back(selectionName); +} + +void Transaction::querySelectionOutline(const std::string& selectionName, SelectionOutlineQueryFunc func) { + _outlineQueries.emplace_back(OutlineQuery{ selectionName, func }); +} + void Transaction::merge(const Transaction& transaction) { _resetItems.insert(_resetItems.end(), transaction._resetItems.begin(), transaction._resetItems.end()); _removedItems.insert(_removedItems.end(), transaction._removedItems.begin(), transaction._removedItems.end()); @@ -62,6 +75,9 @@ void Transaction::merge(const Transaction& transaction) { _addedTransitions.insert(_addedTransitions.end(), transaction._addedTransitions.begin(), transaction._addedTransitions.end()); _queriedTransitions.insert(_queriedTransitions.end(), transaction._queriedTransitions.begin(), transaction._queriedTransitions.end()); _reAppliedTransitions.insert(_reAppliedTransitions.end(), transaction._reAppliedTransitions.begin(), transaction._reAppliedTransitions.end()); + _outlineResets.insert(_outlineResets.end(), transaction._outlineResets.begin(), transaction._outlineResets.end()); + _outlineRemoves.insert(_outlineRemoves.end(), transaction._outlineRemoves.begin(), transaction._outlineRemoves.end()); + _outlineQueries.insert(_outlineQueries.end(), transaction._outlineQueries.begin(), transaction._outlineQueries.end()); } @@ -176,6 +192,10 @@ void Scene::processTransactionFrame(const Transaction& transaction) { // resets and potential NEW items resetSelections(transaction._resetSelections); } + + resetOutlines(transaction._outlineResets); + removeOutlines(transaction._outlineRemoves); + queryOutlines(transaction._outlineQueries); } void Scene::resetItems(const Transaction::Resets& transactions) { @@ -316,6 +336,50 @@ void Scene::queryTransitionItems(const Transaction::TransitionQueries& transacti } } +void Scene::resetOutlines(const Transaction::OutlineResets& transactions) { + auto outlineStage = getStage(OutlineStyleStage::getName()); + + for (auto& transaction : transactions) { + const auto& selectionName = std::get<0>(transaction); + const auto& newStyle = std::get<1>(transaction); + auto outlineId = outlineStage->getOutlineIdBySelection(selectionName); + + if (OutlineStyleStage::isIndexInvalid(outlineId)) { + outlineStage->addOutline(selectionName, newStyle); + } else { + outlineStage->editOutline(outlineId)._style = newStyle; + } + } +} + +void Scene::removeOutlines(const Transaction::OutlineRemoves& transactions) { + auto outlineStage = getStage(OutlineStyleStage::getName()); + + for (auto& selectionName : transactions) { + auto outlineId = outlineStage->getOutlineIdBySelection(selectionName); + + if (!OutlineStyleStage::isIndexInvalid(outlineId)) { + outlineStage->removeOutline(outlineId); + } + } +} + +void Scene::queryOutlines(const Transaction::OutlineQueries& transactions) { + auto outlineStage = getStage(OutlineStyleStage::getName()); + + for (auto& transaction : transactions) { + const auto& selectionName = std::get<0>(transaction); + const auto& func = std::get<1>(transaction); + auto outlineId = outlineStage->getOutlineIdBySelection(selectionName); + + if (!OutlineStyleStage::isIndexInvalid(outlineId)) { + func(&outlineStage->editOutline(outlineId)._style); + } else { + func(nullptr); + } + } +} + void Scene::collectSubItems(ItemID parentId, ItemIDs& subItems) const { // Access the true item auto& item = _items[parentId]; diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 1f3b9a72c3..38f528aced 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -17,6 +17,7 @@ #include "Stage.h" #include "Selection.h" #include "Transition.h" +#include "OutlineStyle.h" namespace render { @@ -37,6 +38,7 @@ class Transaction { public: typedef std::function TransitionQueryFunc; + typedef std::function SelectionOutlineQueryFunc; Transaction() {} ~Transaction() {} @@ -61,6 +63,10 @@ public: // Selection transactions void resetSelection(const Selection& selection); + void resetSelectionOutline(const std::string& selectionName, const OutlineStyle& style = OutlineStyle()); + void removeOutlineFromSelection(const std::string& selectionName); + void querySelectionOutline(const std::string& selectionName, SelectionOutlineQueryFunc func); + void merge(const Transaction& transaction); // Checkers if there is work to do when processing the transaction @@ -75,6 +81,9 @@ protected: using TransitionQuery = std::tuple; using TransitionReApply = ItemID; using SelectionReset = Selection; + using OutlineReset = std::tuple; + using OutlineRemove = std::string; + using OutlineQuery = std::tuple; using Resets = std::vector; using Removes = std::vector; @@ -83,6 +92,9 @@ protected: using TransitionQueries = std::vector; using TransitionReApplies = std::vector; using SelectionResets = std::vector; + using OutlineResets = std::vector; + using OutlineRemoves = std::vector; + using OutlineQueries = std::vector; Resets _resetItems; Removes _removedItems; @@ -91,6 +103,9 @@ protected: TransitionQueries _queriedTransitions; TransitionReApplies _reAppliedTransitions; SelectionResets _resetSelections; + OutlineResets _outlineResets; + OutlineRemoves _outlineRemoves; + OutlineQueries _outlineQueries; }; typedef std::queue TransactionQueue; @@ -103,10 +118,6 @@ typedef std::queue TransactionQueue; class Scene { public: - enum { - MAX_OUTLINE_COUNT = 8 - }; - Scene(glm::vec3 origin, float size); ~Scene(); @@ -192,6 +203,9 @@ protected: void transitionItems(const Transaction::TransitionAdds& transactions); void reApplyTransitions(const Transaction::TransitionReApplies& transactions); void queryTransitionItems(const Transaction::TransitionQueries& transactions); + void resetOutlines(const Transaction::OutlineResets& transactions); + void removeOutlines(const Transaction::OutlineRemoves& transactions); + void queryOutlines(const Transaction::OutlineQueries& transactions); void collectSubItems(ItemID parentId, ItemIDs& subItems) const; From 650df247611fe83ab1b6c4e2035f42d410ce4e02 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Mon, 6 Nov 2017 14:27:02 -0800 Subject: [PATCH 119/183] Improved Haze UI in Create menu --- scripts/system/html/entityProperties.html | 46 +++++++++++++---------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index e7d4aed3fb..7fdeee67d3 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -555,20 +555,21 @@
-
+
+ + < + /div>
-
-
-
-
-
-
-
+
+
+
+
+
@@ -582,6 +583,15 @@
+
+
+
+
+ + +
+
+
@@ -600,20 +610,18 @@
-
-
-
-
-
- - +
+
+ + +
+
+ + +
-
- - -
From b272b2e6c8655862a54d63be9dc7948318d3bc56 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 7 Nov 2017 11:28:35 +1300 Subject: [PATCH 120/183] Fix import from URL adding multiple copies of imported entities --- scripts/system/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index e76a02b6f5..a5b1d9358b 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1533,7 +1533,7 @@ function handeMenuEvent(menuItem) { Window.openFileChanged.connect(onFileOpenChanged); Window.browseAsync("Select Model to Import", "", "*.json"); } else { - Window.promptTextChanged.connect(onFileOpenChanged); + Window.promptTextChanged.connect(onPromptTextChanged); Window.promptAsync("URL of SVO to import", ""); } } else if (menuItem === "Entity List...") { From bb21c52783dba74bae3a32eff1266306c8a0f5c8 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 6 Nov 2017 15:12:01 -0800 Subject: [PATCH 121/183] Fix crash when logging out while Passphrase screen visible --- interface/src/commerce/QmlCommerce.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 9d07ddb4ab..f29e46d843 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -33,7 +33,7 @@ QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) { connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus); auto accountManager = DependencyManager::get(); - connect(accountManager.data(), &AccountManager::usernameChanged, [&]() { + connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { setPassphrase(""); }); } From 3b15897b123e40d6faa1dab4edb46bc36f77fd04 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 6 Nov 2017 15:21:20 -0800 Subject: [PATCH 122/183] fixed farGrab parent grabbing and laser LockEndUUID --- interface/src/raypick/LaserPointer.cpp | 11 +- interface/src/raypick/LaserPointer.h | 3 +- interface/src/raypick/LaserPointerManager.cpp | 4 +- interface/src/raypick/LaserPointerManager.h | 2 +- .../raypick/LaserPointerScriptingInterface.h | 2 +- .../controllerModules/farActionGrabEntity.js | 107 +++++++++++------- .../libraries/controllerDispatcherUtils.js | 10 -- 7 files changed, 78 insertions(+), 61 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 9da8ff34ac..0d691911c8 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -25,7 +25,7 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende _distanceScaleEnd(distanceScaleEnd), _rayPickUID(DependencyManager::get()->createRayPick(rayProps)) { - + _offsetMat = glm::mat4(); for (auto& state : _renderStates) { if (!enabled || state.first != _currentRenderState) { @@ -134,8 +134,10 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter registrationPoint = glm::vec3(0.5f); } else { EntityItemProperties props = DependencyManager::get()->getEntityProperties(_objectLockEnd.first); - pos = props.getPosition(); - rot = props.getRotation(); + glm::mat4 entityMat = createMatFromQuatAndPos(props.getRotation(), props.getPosition()); + glm::mat4 finalPosAndRotMat = entityMat * _offsetMat; + pos = extractTranslation(finalPosAndRotMat); + rot = glmExtractRotation(finalPosAndRotMat); dim = props.getDimensions(); registrationPoint = props.getRegistrationPoint(); } @@ -233,9 +235,10 @@ void LaserPointer::setLaserLength(const float laserLength) { }); } -void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offset) { +void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offsetMat) { withWriteLock([&] { _objectLockEnd = std::pair(objectID, isOverlay); + _offsetMat = offsetMat; }); } diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index a80f9d447d..40a7d93356 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -74,7 +74,7 @@ public: void setPrecisionPicking(const bool precisionPicking); void setLaserLength(const float laserLength); - void setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offset = glm::mat4()); + void setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offsetMat = glm::mat4()); void setIgnoreItems(const QVector& ignoreItems) const; void setIncludeItems(const QVector& includeItems) const; @@ -91,6 +91,7 @@ private: bool _centerEndY; bool _lockEnd; bool _distanceScaleEnd; + glm::mat4 _offsetMat; std::pair _objectLockEnd { std::pair(QUuid(), false)}; const QUuid _rayPickUID; diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 9d58cc2587..45420d1488 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -113,9 +113,9 @@ void LaserPointerManager::setIncludeItems(const QUuid& uid, const QVector } } -void LaserPointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const { +void LaserPointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay, const glm::mat4& offsetMat) const { auto laserPointer = find(uid); if (laserPointer) { - laserPointer->setLockEndUUID(objectID, isOverlay); + laserPointer->setLockEndUUID(objectID, isOverlay, offsetMat); } } diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index e302318483..25089a291a 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -39,7 +39,7 @@ public: void setIgnoreItems(const QUuid& uid, const QVector& ignoreEntities) const; void setIncludeItems(const QUuid& uid, const QVector& includeEntities) const; - void setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const; + void setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const; void update(); diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 19262e6e5d..986c53e24f 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -35,7 +35,7 @@ public slots: Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities) const; Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities) const; - Q_INVOKABLE void setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay) const { qApp->getLaserPointerManager().setLockEndUUID(uid, objectID, isOverlay); } + Q_INVOKABLE void setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const { qApp->getLaserPointerManager().setLockEndUUID(uid, objectID, isOverlay, offsetMat); } private: static RenderState buildRenderState(const QVariantMap& propMap); diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index e63d7c7c35..7d9a6dc1b5 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -13,13 +13,13 @@ makeDispatcherModuleParameters, MSECS_PER_SEC, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic, - getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI + getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI, Xform, getEntityParents */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); -Script.include("/~/system/libraries/Xform.hs"); +Script.include("/~/system/libraries/Xform.js"); (function() { var PICK_WITH_HAND_RAY = true; @@ -115,32 +115,53 @@ Script.include("/~/system/libraries/Xform.hs"); var MARGIN = 25; - function TargetObject(entityID) { + function TargetObject(entityID, entityProps) { this.entityID = entityID; - this.entityProps = null; - this.parentID = null; - this.parentProps = []; - this.childrenProps = []; - this.parentsCollisionStatus = []; - this.childrenCollisionStatus = []; + this.entityProps = entityProps; + this.targetEntityID = null; + this.targetEntityProps = null; + this.previousCollisionStatus = null; this.madeDynamic = null; - this.parentEntityProps = null; this.makeDynamic = function() { + if (this.targetEntityID) { + var newProps = { + dynamic: true, + collisionless: true + }; + this.previousCollisionStatus = this.targetEntityProps.collisionless; + Entities.editEntity(this.targetEntityID, newProps); + this.madeDynamic = true; + } }; - this.saveCollisionStatus = function() { - }; - - this.restoreEntitiesProperties = function() { + this.restoreTargetEntityOriginalProps = function() { + if (this.madeDynamic) { + var props = {}; + props.dynamic = false; + props.collisionless = this.previousCollisionStatus; + var zeroVector = {x: 0, y: 0, z:0}; + props.localVelocity = zeroVector; + props.localRotation = zeroVector; + Entities.editEntity(this.targetEntityID, props); + } }; this.getTargetEntity = function() { var parentPropsLength = this.parentProps.length; if (parentPropsLength !== 0) { - return this.parentProps[parentPropsLength].id; + var targetEntity = { + id: this.parentProps[parentPropsLength - 1].id, + props: this.parentProps[parentPropsLength - 1]}; + this.targetEntityID = targetEntity.id; + this.targetEntityProps = targetEntity.props; + return targetEntity; } - return this.entityID; + this.targetEntityID = this.entityID; + this.targetEntityProps = this.entityProps; + return { + id: this.entityID, + props: this.entityProps}; }; } @@ -153,11 +174,11 @@ Script.include("/~/system/libraries/Xform.hs"); this.entityWithContextOverlay = false; this.contextOverlayTimer = false; this.previousCollisionStatus = false; + this.locked = false; this.reticleMinX = MARGIN; this.reticleMaxX; this.reticleMinY = MARGIN; this.reticleMaxY; - this.madeDynamic = false; var ACTION_TTL = 15; // seconds @@ -191,10 +212,25 @@ Script.include("/~/system/libraries/Xform.hs"); LaserPointers.enableLaserPointer(laserPointerID); LaserPointers.setRenderState(laserPointerID, mode); if (this.distanceHolding || this.distanceRotating) { - // calculate offset - LaserPointers.setLockEndUUID(laserPointerID, this.entityToLockOnto, this.grabbedIsOverlay); + if (!this.locked) { + // calculate offset + var targetProps = Entities.getEntityProperties(this.targetObject.entityID, [ + "position", + "rotation" + ]); + var zeroVector = { x: 0, y: 0, z:0, w: 0 }; + var intersection = controllerData.rayPicks[this.hand].intersection; + var intersectionMat = new Xform(zeroVector, intersection); + var modelMat = new Xform(targetProps.rotation, targetProps.position); + var modelMatInv = modelMat.inv(); + var xformMat = Xform.mul(modelMatInv, intersectionMat); + var offsetMat = Mat4.createFromRotAndTrans(xformMat.rot, xformMat.pos); + LaserPointers.setLockEndUUID(laserPointerID, this.targetObject.entityID, this.grabbedIsOverlay, offsetMat); + this.locked = true; + } } else { LaserPointers.setLockEndUUID(laserPointerID, null, false); + this.locked = false; } }; @@ -373,22 +409,15 @@ Script.include("/~/system/libraries/Xform.hs"); var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.grabbedThingID, "releaseGrab", args); - - if (this.madeDynamic) { - var props = {}; - props.dynamic = false; - props.collisionless = this.previousCollisionStatus; - props.localVelocity = {x: 0, y: 0, z: 0}; - props.localRotation = {x: 0, y: 0, z: 0}; - Entities.editEntity(this.grabbedThingID, props); - this.madeDynamic = false; + if (this.targetObject) { + this.targetObject.restoreTargetEntityOriginalProps(); } this.actionID = null; this.grabbedThingID = null; - this.entityToLockOnto = null; + this.targetObject = null; }; - this.updateRecommendedArea = function() { + this.updateRecommendedArea = function() { var dims = Controller.getViewportDimensions(); this.reticleMaxX = dims.x - MARGIN; this.reticleMaxY = dims.y - MARGIN; @@ -532,30 +561,24 @@ Script.include("/~/system/libraries/Xform.hs"); if (rayPickInfo.type === RayPick.INTERSECTED_ENTITY) { if (controllerData.triggerClicks[this.hand]) { var entityID = rayPickInfo.objectID; - this.entityToLockOnto = entityID; var targetProps = Entities.getEntityProperties(entityID, [ "dynamic", "shapeType", "position", "rotation", "dimensions", "density", "userData", "locked", "type" ]); - this.targetObject = new TargetObject(entityID); + this.targetObject = new TargetObject(entityID, targetProps); + this.targetObject.parentProps = getEntityParents(targetProps); if (entityID !== this.entityWithContextOverlay) { this.destroyContextOverlay(); } + var targetEntity = this.targetObject.getTargetEntity(); + entityID = targetEntity.id; + targetProps = targetEntity.props; if (entityIsGrabbable(targetProps)) { - var groupRootProps = findGroupParent(controllerData, targetProps); - if (entityIsGrabbable(groupRootProps)) { - targetProps = groupRootProps; - entityID = targetProps.id; - } if (!entityIsDistanceGrabbable(targetProps)) { - targetProps.dynamic = true; - this.previousCollisionStatus = targetProps.collisionless; - targetProps.collisionless = true; - Entities.editEntity(entityID, targetProps); - this.madeDynamic = true; + this.targetObject.makeDynamic(); } if (!this.distanceRotating) { diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 148530c5ec..fb6de0e683 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -308,16 +308,6 @@ findGroupParent = function (controllerData, targetProps) { return targetProps; }; -getChildrenProps = function(entityID) { - var childrenProps = []; - var childrenIDs = Entities.getChildrenIDs(entityID); - for (var index = 0; index < childrenIDs.length; index++) { - var childProps = Entities.getEntityProperties(childrenIDs[index]); - childrenProps.push(childProps); - } - return childrenProps; -}; - getEntityParents = function(targetProps) { var parentProperties = []; while (targetProps.parentID && From 41c6261b74d0d591a908fa31f255e07354eef803 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 6 Nov 2017 16:04:33 -0800 Subject: [PATCH 123/183] LaserPointer: made _objectLockEnd into a struct --- interface/src/raypick/LaserPointer.cpp | 23 ++++++++++++----------- interface/src/raypick/LaserPointer.h | 8 +++++++- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 0d691911c8..f3d74d18a5 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -119,23 +119,23 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter qApp->getOverlays().editOverlay(renderState.getStartID(), startProps); } glm::vec3 endVec; - if (((defaultState || !_lockEnd) && _objectLockEnd.first.isNull()) || type == IntersectionType::HUD) { + if (((defaultState || !_lockEnd) && _lockEndObject.id.isNull()) || type == IntersectionType::HUD) { endVec = pickRay.origin + pickRay.direction * distance; } else { - if (!_objectLockEnd.first.isNull()) { + if (!_lockEndObject.id.isNull()) { glm::vec3 pos; glm::quat rot; glm::vec3 dim; glm::vec3 registrationPoint; - if (_objectLockEnd.second) { - pos = vec3FromVariant(qApp->getOverlays().getProperty(_objectLockEnd.first, "position").value); - rot = quatFromVariant(qApp->getOverlays().getProperty(_objectLockEnd.first, "rotation").value); - dim = vec3FromVariant(qApp->getOverlays().getProperty(_objectLockEnd.first, "dimensions").value); + if (_lockEndObject.isOverlay) { + pos = vec3FromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "position").value); + rot = quatFromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "rotation").value); + dim = vec3FromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "dimensions").value); registrationPoint = glm::vec3(0.5f); } else { - EntityItemProperties props = DependencyManager::get()->getEntityProperties(_objectLockEnd.first); + EntityItemProperties props = DependencyManager::get()->getEntityProperties(_lockEndObject.id); glm::mat4 entityMat = createMatFromQuatAndPos(props.getRotation(), props.getPosition()); - glm::mat4 finalPosAndRotMat = entityMat * _offsetMat; + glm::mat4 finalPosAndRotMat = entityMat * _lockEndObject.offsetMat; pos = extractTranslation(finalPosAndRotMat); rot = glmExtractRotation(finalPosAndRotMat); dim = props.getDimensions(); @@ -211,7 +211,7 @@ void LaserPointer::update() { withReadLock([&] { RayPickResult prevRayPickResult = qApp->getRayPickManager().getPrevRayPickResult(_rayPickUID); if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() && - (prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) { + (prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_lockEndObject.id.isNull())) { float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance; updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false); disableRenderState(_defaultRenderStates[_currentRenderState].second); @@ -237,8 +237,9 @@ void LaserPointer::setLaserLength(const float laserLength) { void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offsetMat) { withWriteLock([&] { - _objectLockEnd = std::pair(objectID, isOverlay); - _offsetMat = offsetMat; + _lockEndObject.id = objectID; + _lockEndObject.isOverlay; + _lockEndObject.offsetMat = offsetMat; }); } diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 40a7d93356..2171698cc5 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -21,6 +21,12 @@ class RayPickResult; +struct LockEndObject { + QUuid id {QUuid()}; + bool isOverlay {false}; + glm::mat4 offsetMat {glm::mat4()}; +}; + class RenderState { public: @@ -91,8 +97,8 @@ private: bool _centerEndY; bool _lockEnd; bool _distanceScaleEnd; + LockEndObject _lockEndObject; glm::mat4 _offsetMat; - std::pair _objectLockEnd { std::pair(QUuid(), false)}; const QUuid _rayPickUID; From 646e5455ac8c4eee8454da1c3fa498196e50e67c Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 6 Nov 2017 16:05:44 -0800 Subject: [PATCH 124/183] forgot to remove unused variable --- interface/src/raypick/LaserPointer.h | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 2171698cc5..32ef189d76 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -98,7 +98,6 @@ private: bool _lockEnd; bool _distanceScaleEnd; LockEndObject _lockEndObject; - glm::mat4 _offsetMat; const QUuid _rayPickUID; From 067ed2ffe064126065852ec83cd56306421e206d Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 6 Nov 2017 16:09:31 -0800 Subject: [PATCH 125/183] apply coding standard --- interface/src/raypick/LaserPointer.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 32ef189d76..896752a96e 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -22,9 +22,9 @@ class RayPickResult; struct LockEndObject { - QUuid id {QUuid()}; - bool isOverlay {false}; - glm::mat4 offsetMat {glm::mat4()}; + QUuid id { QUuid() }; + bool isOverlay { false }; + glm::mat4 offsetMat { glm::mat4() }; }; class RenderState { From c9d67f762bbcd1db95b73faf7f624fd3c8eacd39 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 6 Nov 2017 16:20:16 -0800 Subject: [PATCH 126/183] made requested changes --- interface/src/raypick/LaserPointer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index f3d74d18a5..32dd74279b 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -25,7 +25,6 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende _distanceScaleEnd(distanceScaleEnd), _rayPickUID(DependencyManager::get()->createRayPick(rayProps)) { - _offsetMat = glm::mat4(); for (auto& state : _renderStates) { if (!enabled || state.first != _currentRenderState) { @@ -238,7 +237,7 @@ void LaserPointer::setLaserLength(const float laserLength) { void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offsetMat) { withWriteLock([&] { _lockEndObject.id = objectID; - _lockEndObject.isOverlay; + _lockEndObject.isOverlay = isOverlay; _lockEndObject.offsetMat = offsetMat; }); } From 60319e8d53a3605dc5cefc0f70e275357eacf364 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 7 Nov 2017 13:35:31 +1300 Subject: [PATCH 127/183] Don't move or rotate entities if Alt or Meta keys are pressed --- scripts/system/controllers/grab.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index a1846e7ad7..eaa15ee3b1 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -315,6 +315,10 @@ Grabber.prototype.pressEvent = function(event) { return; } + if (event.isAlt || event.isMeta) { + return; + } + if (Overlays.getOverlayAtPoint(Reticle.position) > 0) { // the mouse is pointing at an overlay; don't look for entities underneath the overlay. return; From f665bf384b30ca82feacf9978c0126ad592266b4 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 6 Nov 2017 17:02:10 -0800 Subject: [PATCH 128/183] merge with upstream, and clean code --- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index bbd0110c11..d2dc116e15 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -728,21 +728,19 @@ void Avatar::simulateAttachments(float deltaTime) { glm::quat jointRotation; if (attachment.isSoft) { // soft attachments do not have transform offsets - // model->setTranslation(getPosition()); - // model->setRotation(getOrientation() * Quaternions::Y_180); model->setTransformNoUpdateRenderItems(Transform(getOrientation() * Quaternions::Y_180, glm::vec3(1.0), getPosition())); model->simulate(deltaTime); model->updateRenderItems(); } else { if (_skeletonModel->getJointPositionInWorldFrame(jointIndex, jointPosition) && _skeletonModel->getJointRotationInWorldFrame(jointIndex, jointRotation)) { - model->setTranslation(jointPosition + jointRotation * attachment.translation * getModelScale()); - model->setRotation(jointRotation * attachment.rotation); + model->setTransformNoUpdateRenderItems(Transform(jointRotation * attachment.rotation, glm::vec3(1.0), jointPosition + jointRotation * attachment.translation * getModelScale())); float scale = getModelScale() * attachment.scale; model->setScaleToFit(true, model->getNaturalDimensions() * scale, true); // hack to force rescale model->setSnapModelToCenter(false); // hack to force resnap model->setSnapModelToCenter(true); model->simulate(deltaTime); + model->updateRenderItems(); } } } From fadbf09cdd659569b4f8df988a9e23a48571c111 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 7 Nov 2017 18:10:10 +1300 Subject: [PATCH 129/183] Avoid potentially slow entity list refresh upon deleting entities --- scripts/system/edit.js | 13 +++++++++++-- scripts/system/html/js/entityList.js | 7 ++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index e76a02b6f5..ba84ffd716 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1333,7 +1333,7 @@ function sortSelectedEntities(selected) { return sortedEntities; } -function recursiveDelete(entities, childrenList) { +function recursiveDelete(entities, childrenList, deletedIDs) { var entitiesLength = entities.length; for (var i = 0; i < entitiesLength; i++) { var entityID = entities[i]; @@ -1346,6 +1346,7 @@ function recursiveDelete(entities, childrenList) { properties: initialProperties, children: grandchildrenList }); + deletedIDs.push(entityID); Entities.deleteEntity(entityID); } } @@ -1413,6 +1414,8 @@ function parentSelectedEntities() { } function deleteSelectedEntities() { if (SelectionManager.hasSelection()) { + var deletedIDs = []; + selectedParticleEntityID = null; particleExplorerTool.destroyWebView(); SelectionManager.saveProperties(); @@ -1423,16 +1426,22 @@ function deleteSelectedEntities() { var initialProperties = SelectionManager.savedProperties[entityID]; var children = Entities.getChildrenIDs(entityID); var childList = []; - recursiveDelete(children, childList); + recursiveDelete(children, childList, deletedIDs); savedProperties.push({ entityID: entityID, properties: initialProperties, children: childList }); + deletedIDs.push(entityID); Entities.deleteEntity(entityID); } SelectionManager.clearSelections(); pushCommandForSelections([], savedProperties); + + entityListTool.webView.emitScriptEvent(JSON.stringify({ + type: "deleted", + ids: deletedIDs + })); } } diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index ea79750154..7b25e66c67 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -286,7 +286,6 @@ function loaded() { } elDelete.onclick = function() { EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' })); - refreshEntities(); } document.addEventListener("keydown", function (keyDownEvent) { @@ -362,6 +361,12 @@ function loaded() { updateSelectedEntities(data.selectedIDs); resize(); } + } else if (data.type === "deleted") { + for (i = 0, length = data.ids.length; i < length; i++) { + delete entities[data.ids[i]]; + entityList.remove("id", data.ids[i]); + } + refreshFooter(); } }); setTimeout(refreshEntities, 1000); From 3cc445ff023b2a641996cde913b1812cf95a52bf Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 7 Nov 2017 11:07:25 +0100 Subject: [PATCH 130/183] Renamed outline to highlight --- .gitignore | 1 + .../ui/overlays/ContextOverlayInterface.cpp | 2 +- .../src/{Outline.slf => Highlight.slf} | 6 +- .../src/{Outline.slh => Highlight.slh} | 24 +- ...{OutlineEffect.cpp => HighlightEffect.cpp} | 239 +++++++++--------- .../{OutlineEffect.h => HighlightEffect.h} | 112 ++++---- ...{Outline_aabox.slv => Highlight_aabox.slv} | 0 ...utline_filled.slf => Highlight_filled.slf} | 6 +- ...utline_shared.slh => Highlight_shared.slh} | 4 +- .../render-utils/src/RenderDeferredTask.cpp | 10 +- .../render-utils/src/UpdateSceneTask.cpp | 4 +- .../render/src/render/HighlightStage.cpp | 46 ++++ libraries/render/src/render/HighlightStage.h | 77 ++++++ .../{OutlineStyle.h => HighlightStyle.h} | 17 +- .../render/src/render/OutlineStyleStage.cpp | 46 ---- .../render/src/render/OutlineStyleStage.h | 77 ------ libraries/render/src/render/Scene.cpp | 58 ++--- libraries/render/src/render/Scene.h | 34 +-- .../{debugOutline.js => debugHighlight.js} | 22 +- .../render/{outline.qml => highlight.qml} | 12 +- .../HighlightPage.qml} | 6 +- .../utilities/render/highlightPage/qmldir | 1 + .../utilities/render/outlinePage/qmldir | 1 - 23 files changed, 403 insertions(+), 402 deletions(-) rename libraries/render-utils/src/{Outline.slf => Highlight.slf} (72%) rename libraries/render-utils/src/{Outline.slh => Highlight.slh} (75%) rename libraries/render-utils/src/{OutlineEffect.cpp => HighlightEffect.cpp} (63%) rename libraries/render-utils/src/{OutlineEffect.h => HighlightEffect.h} (55%) rename libraries/render-utils/src/{Outline_aabox.slv => Highlight_aabox.slv} (100%) rename libraries/render-utils/src/{Outline_filled.slf => Highlight_filled.slf} (71%) rename libraries/render-utils/src/{Outline_shared.slh => Highlight_shared.slh} (84%) create mode 100644 libraries/render/src/render/HighlightStage.cpp create mode 100644 libraries/render/src/render/HighlightStage.h rename libraries/render/src/render/{OutlineStyle.h => HighlightStyle.h} (68%) delete mode 100644 libraries/render/src/render/OutlineStyleStage.cpp delete mode 100644 libraries/render/src/render/OutlineStyleStage.h rename scripts/developer/utilities/render/{debugOutline.js => debugHighlight.js} (88%) rename scripts/developer/utilities/render/{outline.qml => highlight.qml} (88%) rename scripts/developer/utilities/render/{outlinePage/OutlinePage.qml => highlightPage/HighlightPage.qml} (96%) create mode 100644 scripts/developer/utilities/render/highlightPage/qmldir delete mode 100644 scripts/developer/utilities/render/outlinePage/qmldir diff --git a/.gitignore b/.gitignore index 072e6001da..4b6949e268 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,7 @@ gvr-interface/libs/* # ignore files for various dev environments TAGS *.sw[po] +*.qmlc # ignore node files for the console node_modules diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 32e4137526..6a21221a8b 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -88,7 +88,7 @@ ContextOverlayInterface::ContextOverlayInterface() { void ContextOverlayInterface::initializeSelectionToSceneHandler(SelectionToSceneHandler& handler, const QString& selectionName, render::Transaction& transaction) { handler.initialize(selectionName); connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &handler, &SelectionToSceneHandler::selectedItemsListChanged); - transaction.resetSelectionOutline(selectionName.toStdString()); + transaction.resetSelectionHighlight(selectionName.toStdString()); } static const uint32_t MOUSE_HW_ID = 0; diff --git a/libraries/render-utils/src/Outline.slf b/libraries/render-utils/src/Highlight.slf similarity index 72% rename from libraries/render-utils/src/Outline.slf rename to libraries/render-utils/src/Highlight.slf index 68ef870cba..bf65f92613 100644 --- a/libraries/render-utils/src/Outline.slf +++ b/libraries/render-utils/src/Highlight.slf @@ -1,5 +1,5 @@ -// Outline.slf -// Add outline effect based on two zbuffers : one containing the total scene z and another +// Highlight.slf +// Add highlight effect based on two zbuffers : one containing the total scene z and another // with the z of only the objects to be outlined. // This is the version without the fill effect inside the silhouette. // @@ -9,5 +9,5 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include Outline.slh@> +<@include Highlight.slh@> <$main(0)$> diff --git a/libraries/render-utils/src/Outline.slh b/libraries/render-utils/src/Highlight.slh similarity index 75% rename from libraries/render-utils/src/Outline.slh rename to libraries/render-utils/src/Highlight.slh index aeaf20a24a..2faa10682e 100644 --- a/libraries/render-utils/src/Outline.slh +++ b/libraries/render-utils/src/Highlight.slh @@ -1,7 +1,7 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> <$declareDeferredFrameTransform()$> -<@include Outline_shared.slh@> +<@include Highlight_shared.slh@> -uniform outlineParamsBuffer { - OutlineParameters params; +uniform highlightParamsBuffer { + HighlightParameters params; }; uniform sampler2D sceneDepthMap; -uniform sampler2D outlinedDepthMap; +uniform sampler2D highlightedDepthMap; in vec2 varTexCoord0; out vec4 outFragColor; @@ -35,20 +35,20 @@ void main(void) { // We offset by half a texel to be centered on the depth sample. If we don't do this // the blur will have a different width between the left / right sides and top / bottom // sides of the silhouette - float outlinedDepth = texture(outlinedDepthMap, varTexCoord0).x; + float highlightedDepth = texture(highlightedDepthMap, varTexCoord0).x; float intensity = 0.0; - if (outlinedDepth < FAR_Z) { - // We're not on the far plane so we are on the outlined object, thus no outline to do! + if (highlightedDepth < FAR_Z) { + // We're not on the far plane so we are on the highlighted object, thus no outline to do! <@if IS_FILLED@> // But we need to fill the interior float sceneDepth = texture(sceneDepthMap, varTexCoord0).x; // Transform to linear depth for better precision - outlinedDepth = -evalZeyeFromZdb(outlinedDepth); + highlightedDepth = -evalZeyeFromZdb(highlightedDepth); sceneDepth = -evalZeyeFromZdb(sceneDepth); // Are we occluded? - intensity = sceneDepth < (outlinedDepth-LINEAR_DEPTH_BIAS) ? params._occludedFillOpacity : params._unoccludedFillOpacity; + intensity = sceneDepth < (highlightedDepth-LINEAR_DEPTH_BIAS) ? params._occludedFillOpacity : params._unoccludedFillOpacity; <@else@> discard; <@endif@> @@ -70,8 +70,8 @@ void main(void) { for (x=0 ; x=0.0 && uv.x<=1.0) { - outlinedDepth = texture(outlinedDepthMap, uv).x; - intensity += (outlinedDepth < FAR_Z) ? 1.0 : 0.0; + highlightedDepth = texture(highlightedDepthMap, uv).x; + intensity += (highlightedDepth < FAR_Z) ? 1.0 : 0.0; weight += 1.0; } uv.x += deltaUv.x; diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/HighlightEffect.cpp similarity index 63% rename from libraries/render-utils/src/OutlineEffect.cpp rename to libraries/render-utils/src/HighlightEffect.cpp index 590277bf6d..e332be53de 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/HighlightEffect.cpp @@ -1,5 +1,5 @@ // -// OutlineEffect.cpp +// HighlightEffect.cpp // render-utils/src/ // // Created by Olivier Prat on 08/08/17. @@ -8,7 +8,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "OutlineEffect.h" +#include "HighlightEffect.h" #include "GeometryCache.h" @@ -25,18 +25,19 @@ #include "surfaceGeometry_copyDepth_frag.h" #include "debug_deferred_buffer_vert.h" #include "debug_deferred_buffer_frag.h" -#include "Outline_frag.h" -#include "Outline_filled_frag.h" -#include "Outline_aabox_vert.h" +#include "Highlight_frag.h" +#include "Highlight_filled_frag.h" +#include "Highlight_aabox_vert.h" +#include "nop_frag.h" using namespace render; #define OUTLINE_STENCIL_MASK 1 -OutlineRessources::OutlineRessources() { +HighlightRessources::HighlightRessources() { } -void OutlineRessources::update(const gpu::FramebufferPointer& primaryFrameBuffer) { +void HighlightRessources::update(const gpu::FramebufferPointer& primaryFrameBuffer) { auto newFrameSize = glm::ivec2(primaryFrameBuffer->getSize()); // If the buffer size changed, we need to delete our FBOs and recreate them at the @@ -55,64 +56,64 @@ void OutlineRessources::update(const gpu::FramebufferPointer& primaryFrameBuffer } } -void OutlineRessources::allocateColorBuffer(const gpu::FramebufferPointer& primaryFrameBuffer) { +void HighlightRessources::allocateColorBuffer(const gpu::FramebufferPointer& primaryFrameBuffer) { _colorFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithStencil")); _colorFrameBuffer->setRenderBuffer(0, primaryFrameBuffer->getRenderBuffer(0)); _colorFrameBuffer->setDepthStencilBuffer(_depthStencilTexture, _depthStencilTexture->getTexelFormat()); } -void OutlineRessources::allocateDepthBuffer(const gpu::FramebufferPointer& primaryFrameBuffer) { +void HighlightRessources::allocateDepthBuffer(const gpu::FramebufferPointer& primaryFrameBuffer) { auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); _depthStencilTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(depthFormat, _frameSize.x, _frameSize.y)); - _depthFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); + _depthFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("highlightDepth")); _depthFrameBuffer->setDepthStencilBuffer(_depthStencilTexture, depthFormat); } -gpu::FramebufferPointer OutlineRessources::getDepthFramebuffer() { +gpu::FramebufferPointer HighlightRessources::getDepthFramebuffer() { assert(_depthFrameBuffer); return _depthFrameBuffer; } -gpu::TexturePointer OutlineRessources::getDepthTexture() { +gpu::TexturePointer HighlightRessources::getDepthTexture() { return _depthStencilTexture; } -gpu::FramebufferPointer OutlineRessources::getColorFramebuffer() { +gpu::FramebufferPointer HighlightRessources::getColorFramebuffer() { assert(_colorFrameBuffer); return _colorFrameBuffer; } -OutlineSharedParameters::OutlineSharedParameters() { - _outlineIds.fill(render::OutlineStyleStage::INVALID_INDEX); +HighlightSharedParameters::HighlightSharedParameters() { + _highlightIds.fill(render::HighlightStage::INVALID_INDEX); } -float OutlineSharedParameters::getBlurPixelWidth(const render::OutlineStyle& style, int frameBufferHeight) { - return ceilf(style.width * frameBufferHeight / 400.0f); +float HighlightSharedParameters::getBlurPixelWidth(const render::HighlightStyle& style, int frameBufferHeight) { + return ceilf(style.outlineWidth * frameBufferHeight / 400.0f); } -PrepareDrawOutline::PrepareDrawOutline() { - _ressources = std::make_shared(); +PrepareDrawHighlight::PrepareDrawHighlight() { + _ressources = std::make_shared(); } -void PrepareDrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { +void PrepareDrawHighlight::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { auto destinationFrameBuffer = inputs; _ressources->update(destinationFrameBuffer); outputs = _ressources; } -gpu::PipelinePointer DrawOutlineMask::_stencilMaskPipeline; -gpu::PipelinePointer DrawOutlineMask::_stencilMaskFillPipeline; -gpu::BufferPointer DrawOutlineMask::_boundsBuffer; +gpu::PipelinePointer DrawHighlightMask::_stencilMaskPipeline; +gpu::PipelinePointer DrawHighlightMask::_stencilMaskFillPipeline; +gpu::BufferPointer DrawHighlightMask::_boundsBuffer; -DrawOutlineMask::DrawOutlineMask(unsigned int outlineIndex, - render::ShapePlumberPointer shapePlumber, OutlineSharedParametersPointer parameters) : - _outlineIndex{ outlineIndex }, +DrawHighlightMask::DrawHighlightMask(unsigned int highlightIndex, + render::ShapePlumberPointer shapePlumber, HighlightSharedParametersPointer parameters) : + _highlightIndex{ highlightIndex }, _shapePlumber { shapePlumber }, _sharedParameters{ parameters } { } -void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { +void DrawHighlightMask::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); auto& inShapes = inputs.get0(); @@ -130,8 +131,8 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con fillState->setColorWriteMask(false, false, false, false); fillState->setCullMode(gpu::State::CULL_FRONT); - auto vs = gpu::Shader::createVertex(std::string(Outline_aabox_vert)); - auto ps = gpu::StandardShaderLib::getDrawWhitePS(); + auto vs = gpu::Shader::createVertex(std::string(Highlight_aabox_vert)); + auto ps = gpu::Shader::createPixel(std::string(nop_frag)); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; @@ -145,12 +146,12 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con _boundsBuffer = std::make_shared(sizeof(render::ItemBound)); } - auto outlineStage = renderContext->_scene->getStage(render::OutlineStyleStage::getName()); - auto outlineId = _sharedParameters->_outlineIds[_outlineIndex]; + auto highlightStage = renderContext->_scene->getStage(render::HighlightStage::getName()); + auto highlightId = _sharedParameters->_highlightIds[_highlightIndex]; - if (!inShapes.empty() && !render::OutlineStyleStage::isIndexInvalid(outlineId)) { + if (!inShapes.empty() && !render::HighlightStage::isIndexInvalid(highlightId)) { auto ressources = inputs.get1(); - auto& outline = outlineStage->getOutline(outlineId); + auto& highlight = highlightStage->getHighlight(highlightId); RenderArgs* args = renderContext->args; ShapeKey::Builder defaultKeyBuilder; @@ -219,62 +220,62 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con batch.setViewTransform(viewMat); // Draw stencil mask with object bounding boxes - const auto outlineWidthLoc = _stencilMaskPipeline->getProgram()->getUniforms().findLocation("outlineWidth"); + const auto highlightWidthLoc = _stencilMaskPipeline->getProgram()->getUniforms().findLocation("outlineWidth"); const auto sqrt3 = 1.74f; - const float blurPixelWidth = 2.0f * sqrt3 * OutlineSharedParameters::getBlurPixelWidth(outline._style, args->_viewport.w); + const float blurPixelWidth = 2.0f * sqrt3 * HighlightSharedParameters::getBlurPixelWidth(highlight._style, args->_viewport.w); const auto framebufferSize = ressources->getSourceFrameSize(); - auto stencilPipeline = outline._style.isFilled() ? _stencilMaskFillPipeline : _stencilMaskPipeline; + auto stencilPipeline = highlight._style.isFilled() ? _stencilMaskFillPipeline : _stencilMaskPipeline; batch.setPipeline(stencilPipeline); batch.setResourceBuffer(0, _boundsBuffer); - batch._glUniform2f(outlineWidthLoc, blurPixelWidth / framebufferSize.x, blurPixelWidth / framebufferSize.y); + batch._glUniform2f(highlightWidthLoc, blurPixelWidth / framebufferSize.x, blurPixelWidth / framebufferSize.y); static const int NUM_VERTICES_PER_CUBE = 36; batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_CUBE * (gpu::uint32) itemBounds.size(), 0); }); } else { - // Outline rect should be null as there are no outlined shapes + // Highlight rect should be null as there are no highlighted shapes outputs = glm::ivec4(0, 0, 0, 0); } } -gpu::PipelinePointer DrawOutline::_pipeline; -gpu::PipelinePointer DrawOutline::_pipelineFilled; +gpu::PipelinePointer DrawHighlight::_pipeline; +gpu::PipelinePointer DrawHighlight::_pipelineFilled; -DrawOutline::DrawOutline(unsigned int outlineIndex, OutlineSharedParametersPointer parameters) : - _outlineIndex{ outlineIndex }, +DrawHighlight::DrawHighlight(unsigned int highlightIndex, HighlightSharedParametersPointer parameters) : + _highlightIndex{ highlightIndex }, _sharedParameters{ parameters } { } -void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { - auto outlineFrameBuffer = inputs.get1(); - auto outlineRect = inputs.get3(); +void DrawHighlight::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { + auto highlightFrameBuffer = inputs.get1(); + auto highlightRect = inputs.get3(); - if (outlineFrameBuffer && outlineRect.z>0 && outlineRect.w>0) { + if (highlightFrameBuffer && highlightRect.z>0 && highlightRect.w>0) { auto sceneDepthBuffer = inputs.get2(); const auto frameTransform = inputs.get0(); - auto outlinedDepthTexture = outlineFrameBuffer->getDepthTexture(); - auto destinationFrameBuffer = outlineFrameBuffer->getColorFramebuffer(); - auto framebufferSize = glm::ivec2(outlinedDepthTexture->getDimensions()); + auto highlightedDepthTexture = highlightFrameBuffer->getDepthTexture(); + auto destinationFrameBuffer = highlightFrameBuffer->getColorFramebuffer(); + auto framebufferSize = glm::ivec2(highlightedDepthTexture->getDimensions()); if (sceneDepthBuffer) { auto args = renderContext->args; - auto outlineStage = renderContext->_scene->getStage(render::OutlineStyleStage::getName()); - auto outlineId = _sharedParameters->_outlineIds[_outlineIndex]; - if (!render::OutlineStyleStage::isIndexInvalid(outlineId)) { - auto& outline = outlineStage->getOutline(_sharedParameters->_outlineIds[_outlineIndex]); - auto pipeline = getPipeline(outline._style); + auto highlightStage = renderContext->_scene->getStage(render::HighlightStage::getName()); + auto highlightId = _sharedParameters->_highlightIds[_highlightIndex]; + if (!render::HighlightStage::isIndexInvalid(highlightId)) { + auto& highlight = highlightStage->getHighlight(_sharedParameters->_highlightIds[_highlightIndex]); + auto pipeline = getPipeline(highlight._style); { auto& shaderParameters = _configuration.edit(); - shaderParameters._color = outline._style.color; - shaderParameters._intensity = outline._style.intensity * (outline._style.glow ? 2.0f : 1.0f); - shaderParameters._unoccludedFillOpacity = outline._style.unoccludedFillOpacity; - shaderParameters._occludedFillOpacity = outline._style.occludedFillOpacity; - shaderParameters._threshold = outline._style.glow ? 1.0f : 1e-3f; - shaderParameters._blurKernelSize = std::min(7, std::max(2, (int)floorf(outline._style.width * 3 + 0.5f))); - // Size is in normalized screen height. We decide that for outline width = 1, this is equal to 1/400. - auto size = outline._style.width / 400.0f; + shaderParameters._color = highlight._style.color; + shaderParameters._intensity = highlight._style.outlineIntensity * (highlight._style.isOutlineSmooth ? 2.0f : 1.0f); + shaderParameters._unoccludedFillOpacity = highlight._style.unoccludedFillOpacity; + shaderParameters._occludedFillOpacity = highlight._style.occludedFillOpacity; + shaderParameters._threshold = highlight._style.isOutlineSmooth ? 1.0f : 1e-3f; + shaderParameters._blurKernelSize = std::min(7, std::max(2, (int)floorf(highlight._style.outlineWidth * 3 + 0.5f))); + // Size is in normalized screen height. We decide that for highlight width = 1, this is equal to 1/400. + auto size = highlight._style.outlineWidth / 400.0f; shaderParameters._size.x = (size * framebufferSize.y) / framebufferSize.x; shaderParameters._size.y = size; } @@ -289,10 +290,10 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); batch.setPipeline(pipeline); - batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); + batch.setUniformBuffer(HIGHLIGHT_PARAMS_SLOT, _configuration); batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer()); - batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getPrimaryDepthTexture()); - batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthTexture); + batch.setResourceTexture(SCENE_DEPTH_MAP_SLOT, sceneDepthBuffer->getPrimaryDepthTexture()); + batch.setResourceTexture(HIGHLIGHTED_DEPTH_MAP_SLOT, highlightedDepthTexture); batch.draw(gpu::TRIANGLE_STRIP, 4); }); } @@ -300,7 +301,7 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I } } -const gpu::PipelinePointer& DrawOutline::getPipeline(const render::OutlineStyle& style) { +const gpu::PipelinePointer& DrawHighlight::getPipeline(const render::HighlightStyle& style) { if (!_pipeline) { gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setDepthTest(gpu::State::DepthTest(false, false)); @@ -308,19 +309,19 @@ const gpu::PipelinePointer& DrawOutline::getPipeline(const render::OutlineStyle& state->setStencilTest(true, 0, gpu::State::StencilTest(OUTLINE_STENCIL_MASK, 0xFF, gpu::EQUAL)); auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); - auto ps = gpu::Shader::createPixel(std::string(Outline_frag)); + auto ps = gpu::Shader::createPixel(std::string(Highlight_frag)); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding("outlineParamsBuffer", OUTLINE_PARAMS_SLOT)); + slotBindings.insert(gpu::Shader::Binding("highlightParamsBuffer", HIGHLIGHT_PARAMS_SLOT)); slotBindings.insert(gpu::Shader::Binding("deferredFrameTransformBuffer", FRAME_TRANSFORM_SLOT)); - slotBindings.insert(gpu::Shader::Binding("sceneDepthMap", SCENE_DEPTH_SLOT)); - slotBindings.insert(gpu::Shader::Binding("outlinedDepthMap", OUTLINED_DEPTH_SLOT)); + slotBindings.insert(gpu::Shader::Binding("sceneDepthMap", SCENE_DEPTH_MAP_SLOT)); + slotBindings.insert(gpu::Shader::Binding("highlightedDepthMap", HIGHLIGHTED_DEPTH_MAP_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); _pipeline = gpu::Pipeline::create(program, state); - ps = gpu::Shader::createPixel(std::string(Outline_filled_frag)); + ps = gpu::Shader::createPixel(std::string(Highlight_filled_frag)); program = gpu::Shader::createProgram(vs, ps); gpu::Shader::makeProgram(*program, slotBindings); _pipelineFilled = gpu::Pipeline::create(program, state); @@ -328,33 +329,33 @@ const gpu::PipelinePointer& DrawOutline::getPipeline(const render::OutlineStyle& return style.isFilled() ? _pipelineFilled : _pipeline; } -DebugOutline::DebugOutline() { +DebugHighlight::DebugHighlight() { _geometryDepthId = DependencyManager::get()->allocateID(); } -DebugOutline::~DebugOutline() { +DebugHighlight::~DebugHighlight() { auto geometryCache = DependencyManager::get(); if (geometryCache) { geometryCache->releaseID(_geometryDepthId); } } -void DebugOutline::configure(const Config& config) { +void DebugHighlight::configure(const Config& config) { _isDisplayEnabled = config.viewMask; } -void DebugOutline::run(const render::RenderContextPointer& renderContext, const Inputs& input) { - const auto outlineRessources = input.get0(); - const auto outlineRect = input.get1(); +void DebugHighlight::run(const render::RenderContextPointer& renderContext, const Inputs& input) { + const auto highlightRessources = input.get0(); + const auto highlightRect = input.get1(); - if (_isDisplayEnabled && outlineRessources && outlineRect.z>0 && outlineRect.w>0) { + if (_isDisplayEnabled && highlightRessources && highlightRect.z>0 && highlightRect.w>0) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.setViewportTransform(args->_viewport); - batch.setFramebuffer(outlineRessources->getColorFramebuffer()); + batch.setFramebuffer(highlightRessources->getColorFramebuffer()); const auto geometryBuffer = DependencyManager::get(); @@ -369,7 +370,7 @@ void DebugOutline::run(const render::RenderContextPointer& renderContext, const const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); batch.setPipeline(getDepthPipeline()); - batch.setResourceTexture(0, outlineRessources->getDepthTexture()); + batch.setResourceTexture(0, highlightRessources->getDepthTexture()); const glm::vec2 bottomLeft(-1.0f, -1.0f); const glm::vec2 topRight(1.0f, 1.0f); geometryBuffer->renderQuad(batch, bottomLeft, topRight, color, _geometryDepthId); @@ -379,7 +380,7 @@ void DebugOutline::run(const render::RenderContextPointer& renderContext, const } } -void DebugOutline::initializePipelines() { +void DebugHighlight::initializePipelines() { static const std::string VERTEX_SHADER{ debug_deferred_buffer_vert }; static const std::string FRAGMENT_SHADER{ debug_deferred_buffer_frag }; static const std::string SOURCE_PLACEHOLDER{ "//SOURCE_PLACEHOLDER" }; @@ -417,7 +418,7 @@ void DebugOutline::initializePipelines() { } } -const gpu::PipelinePointer& DebugOutline::getDepthPipeline() { +const gpu::PipelinePointer& DebugHighlight::getDepthPipeline() { if (!_depthPipeline) { initializePipelines(); } @@ -425,44 +426,44 @@ const gpu::PipelinePointer& DebugOutline::getDepthPipeline() { return _depthPipeline; } -void SelectionToOutline::run(const render::RenderContextPointer& renderContext, Outputs& outputs) { - auto outlineStage = renderContext->_scene->getStage(render::OutlineStyleStage::getName()); +void SelectionToHighlight::run(const render::RenderContextPointer& renderContext, Outputs& outputs) { + auto highlightStage = renderContext->_scene->getStage(render::HighlightStage::getName()); outputs.clear(); - _sharedParameters->_outlineIds.fill(render::OutlineStyleStage::INVALID_INDEX); + _sharedParameters->_highlightIds.fill(render::HighlightStage::INVALID_INDEX); - for (auto i = 0; i < OutlineSharedParameters::MAX_OUTLINE_COUNT; i++) { + for (auto i = 0; i < HighlightSharedParameters::MAX_HIGHLIGHT_COUNT; i++) { std::ostringstream stream; stream << "contextOverlayHighlightList"; if (i > 0) { stream << i; } auto selectionName = stream.str(); - auto outlineId = outlineStage->getOutlineIdBySelection(selectionName); - if (!render::OutlineStyleStage::isIndexInvalid(outlineId)) { - _sharedParameters->_outlineIds[outputs.size()] = outlineId; + auto highlightId = highlightStage->getHighlightIdBySelection(selectionName); + if (!render::HighlightStage::isIndexInvalid(highlightId)) { + _sharedParameters->_highlightIds[outputs.size()] = highlightId; outputs.emplace_back(selectionName); } } } void ExtractSelectionName::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { - if (_outlineIndex < inputs.size()) { - outputs = inputs[_outlineIndex]; + if (_highlightIndex < inputs.size()) { + outputs = inputs[_highlightIndex]; } else { outputs.clear(); } } -DrawOutlineTask::DrawOutlineTask() { +DrawHighlightTask::DrawHighlightTask() { } -void DrawOutlineTask::configure(const Config& config) { +void DrawHighlightTask::configure(const Config& config) { } -void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { +void DrawHighlightTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { const auto items = inputs.getN(0).get(); const auto sceneFrameBuffer = inputs.getN(1); const auto primaryFramebuffer = inputs.getN(2); @@ -477,53 +478,53 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende initMaskPipelines(*shapePlumber, state); } - auto sharedParameters = std::make_shared(); + auto sharedParameters = std::make_shared(); - const auto outlineSelectionNames = task.addJob("SelectionToOutline", sharedParameters); + const auto highlightSelectionNames = task.addJob("SelectionToHighlight", sharedParameters); - // Prepare for outline group rendering. - const auto outlineRessources = task.addJob("PrepareOutline", primaryFramebuffer); - render::Varying outline0Rect; + // Prepare for highlight group rendering. + const auto highlightRessources = task.addJob("PrepareHighlight", primaryFramebuffer); + render::Varying highlight0Rect; - for (auto i = 0; i < OutlineSharedParameters::MAX_OUTLINE_COUNT; i++) { - const auto selectionName = task.addJob("ExtractSelectionName", outlineSelectionNames, i); + for (auto i = 0; i < HighlightSharedParameters::MAX_HIGHLIGHT_COUNT; i++) { + const auto selectionName = task.addJob("ExtractSelectionName", highlightSelectionNames, i); const auto groupItems = addSelectItemJobs(task, selectionName, items); - const auto outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", groupItems); - const auto outlinedItems = task.addJob("OutlineMetaToSubItems", outlinedItemIDs); + const auto highlightedItemIDs = task.addJob("HighlightMetaToSubItemIDs", groupItems); + const auto highlightedItems = task.addJob("HighlightMetaToSubItems", highlightedItemIDs); // Sort - const auto sortedPipelines = task.addJob("OutlinePipelineSort", outlinedItems); - const auto sortedBounds = task.addJob("OutlineDepthSort", sortedPipelines); + const auto sortedPipelines = task.addJob("HighlightPipelineSort", highlightedItems); + const auto sortedBounds = task.addJob("HighlightDepthSort", sortedPipelines); - // Draw depth of outlined objects in separate buffer + // Draw depth of highlighted objects in separate buffer std::string name; { std::ostringstream stream; - stream << "OutlineMask" << i; + stream << "HighlightMask" << i; name = stream.str(); } - const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedBounds, outlineRessources).asVarying(); - const auto outlinedRect = task.addJob(name, drawMaskInputs, i, shapePlumber, sharedParameters); + const auto drawMaskInputs = DrawHighlightMask::Inputs(sortedBounds, highlightRessources).asVarying(); + const auto highlightedRect = task.addJob(name, drawMaskInputs, i, shapePlumber, sharedParameters); if (i == 0) { - outline0Rect = outlinedRect; + highlight0Rect = highlightedRect; } - // Draw outline + // Draw highlight { std::ostringstream stream; - stream << "OutlineEffect" << i; + stream << "HighlightEffect" << i; name = stream.str(); } - const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlineRessources, sceneFrameBuffer, outlinedRect).asVarying(); - task.addJob(name, drawOutlineInputs, i, sharedParameters); + const auto drawHighlightInputs = DrawHighlight::Inputs(deferredFrameTransform, highlightRessources, sceneFrameBuffer, highlightedRect).asVarying(); + task.addJob(name, drawHighlightInputs, i, sharedParameters); } - // Debug outline - const auto debugInputs = DebugOutline::Inputs(outlineRessources, const_cast(outline0Rect)).asVarying(); - task.addJob("OutlineDebug", debugInputs); + // Debug highlight + const auto debugInputs = DebugHighlight::Inputs(highlightRessources, const_cast(highlight0Rect)).asVarying(); + task.addJob("HighlightDebug", debugInputs); } -const render::Varying DrawOutlineTask::addSelectItemJobs(JobModel& task, const render::Varying& selectionName, +const render::Varying DrawHighlightTask::addSelectItemJobs(JobModel& task, const render::Varying& selectionName, const RenderFetchCullSortTask::BucketList& items) { const auto& opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE]; const auto& transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; @@ -542,7 +543,7 @@ const render::Varying DrawOutlineTask::addSelectItemJobs(JobModel& task, const r #include "model_shadow_frag.h" -void DrawOutlineTask::initMaskPipelines(render::ShapePlumber& shapePlumber, gpu::StatePointer state) { +void DrawHighlightTask::initMaskPipelines(render::ShapePlumber& shapePlumber, gpu::StatePointer state) { auto modelVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel); diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/HighlightEffect.h similarity index 55% rename from libraries/render-utils/src/OutlineEffect.h rename to libraries/render-utils/src/HighlightEffect.h index e25184eb5b..0531c03efd 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/HighlightEffect.h @@ -1,5 +1,5 @@ // -// OutlineEffect.h +// HighlightEffect.h // render-utils/src/ // // Created by Olivier Prat on 08/08/17. @@ -9,19 +9,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_render_utils_OutlineEffect_h -#define hifi_render_utils_OutlineEffect_h +#ifndef hifi_render_utils_HighlightEffect_h +#define hifi_render_utils_HighlightEffect_h #include -#include +#include #include #include "DeferredFramebuffer.h" #include "DeferredFrameTransform.h" -class OutlineRessources { +class HighlightRessources { public: - OutlineRessources(); + HighlightRessources(); gpu::FramebufferPointer getDepthFramebuffer(); gpu::TexturePointer getDepthTexture(); @@ -44,131 +44,131 @@ protected: void allocateDepthBuffer(const gpu::FramebufferPointer& primaryFrameBuffer); }; -using OutlineRessourcesPointer = std::shared_ptr; +using HighlightRessourcesPointer = std::shared_ptr; -class OutlineSharedParameters { +class HighlightSharedParameters { public: enum { - MAX_OUTLINE_COUNT = 8 + MAX_HIGHLIGHT_COUNT = 8 }; - OutlineSharedParameters(); + HighlightSharedParameters(); - std::array _outlineIds; + std::array _highlightIds; - static float getBlurPixelWidth(const render::OutlineStyle& style, int frameBufferHeight); + static float getBlurPixelWidth(const render::HighlightStyle& style, int frameBufferHeight); }; -using OutlineSharedParametersPointer = std::shared_ptr; +using HighlightSharedParametersPointer = std::shared_ptr; -class PrepareDrawOutline { +class PrepareDrawHighlight { public: using Inputs = gpu::FramebufferPointer; - using Outputs = OutlineRessourcesPointer; - using JobModel = render::Job::ModelIO; + using Outputs = HighlightRessourcesPointer; + using JobModel = render::Job::ModelIO; - PrepareDrawOutline(); + PrepareDrawHighlight(); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); private: - OutlineRessourcesPointer _ressources; + HighlightRessourcesPointer _ressources; }; -class SelectionToOutline { +class SelectionToHighlight { public: using Outputs = std::vector; - using JobModel = render::Job::ModelO; + using JobModel = render::Job::ModelO; - SelectionToOutline(OutlineSharedParametersPointer parameters) : _sharedParameters{ parameters } {} + SelectionToHighlight(HighlightSharedParametersPointer parameters) : _sharedParameters{ parameters } {} void run(const render::RenderContextPointer& renderContext, Outputs& outputs); private: - OutlineSharedParametersPointer _sharedParameters; + HighlightSharedParametersPointer _sharedParameters; }; class ExtractSelectionName { public: - using Inputs = SelectionToOutline::Outputs; + using Inputs = SelectionToHighlight::Outputs; using Outputs = std::string; using JobModel = render::Job::ModelIO; - ExtractSelectionName(unsigned int outlineIndex) : _outlineIndex{ outlineIndex } {} + ExtractSelectionName(unsigned int highlightIndex) : _highlightIndex{ highlightIndex } {} void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); private: - unsigned int _outlineIndex; + unsigned int _highlightIndex; }; -class DrawOutlineMask { +class DrawHighlightMask { public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet2; using Outputs = glm::ivec4; - using JobModel = render::Job::ModelIO; + using JobModel = render::Job::ModelIO; - DrawOutlineMask(unsigned int outlineIndex, render::ShapePlumberPointer shapePlumber, OutlineSharedParametersPointer parameters); + DrawHighlightMask(unsigned int highlightIndex, render::ShapePlumberPointer shapePlumber, HighlightSharedParametersPointer parameters); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); protected: - unsigned int _outlineIndex; + unsigned int _highlightIndex; render::ShapePlumberPointer _shapePlumber; - OutlineSharedParametersPointer _sharedParameters; + HighlightSharedParametersPointer _sharedParameters; static gpu::BufferPointer _boundsBuffer; static gpu::PipelinePointer _stencilMaskPipeline; static gpu::PipelinePointer _stencilMaskFillPipeline; }; -class DrawOutline { +class DrawHighlight { public: - using Inputs = render::VaryingSet4; + using Inputs = render::VaryingSet4; using Config = render::Job::Config; - using JobModel = render::Job::ModelI; + using JobModel = render::Job::ModelI; - DrawOutline(unsigned int outlineIndex, OutlineSharedParametersPointer parameters); + DrawHighlight(unsigned int highlightIndex, HighlightSharedParametersPointer parameters); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); private: -#include "Outline_shared.slh" +#include "Highlight_shared.slh" enum { - SCENE_DEPTH_SLOT = 0, - OUTLINED_DEPTH_SLOT, + SCENE_DEPTH_MAP_SLOT = 0, + HIGHLIGHTED_DEPTH_MAP_SLOT, - OUTLINE_PARAMS_SLOT = 0, + HIGHLIGHT_PARAMS_SLOT = 0, FRAME_TRANSFORM_SLOT, }; - using OutlineConfigurationBuffer = gpu::StructBuffer; + using HighlightConfigurationBuffer = gpu::StructBuffer; - static const gpu::PipelinePointer& getPipeline(const render::OutlineStyle& style); + static const gpu::PipelinePointer& getPipeline(const render::HighlightStyle& style); static gpu::PipelinePointer _pipeline; static gpu::PipelinePointer _pipelineFilled; - unsigned int _outlineIndex; - OutlineParameters _parameters; - OutlineSharedParametersPointer _sharedParameters; - OutlineConfigurationBuffer _configuration; + unsigned int _highlightIndex; + HighlightParameters _parameters; + HighlightSharedParametersPointer _sharedParameters; + HighlightConfigurationBuffer _configuration; }; -class DebugOutlineConfig : public render::Job::Config { +class DebugHighlightConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(bool viewMask MEMBER viewMask NOTIFY dirty) @@ -180,14 +180,14 @@ signals: void dirty(); }; -class DebugOutline { +class DebugHighlight { public: - using Inputs = render::VaryingSet2; - using Config = DebugOutlineConfig; - using JobModel = render::Job::ModelI; + using Inputs = render::VaryingSet2; + using Config = DebugHighlightConfig; + using JobModel = render::Job::ModelI; - DebugOutline(); - ~DebugOutline(); + DebugHighlight(); + ~DebugHighlight(); void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); @@ -202,14 +202,14 @@ private: void initializePipelines(); }; -class DrawOutlineTask { +class DrawHighlightTask { public: using Inputs = render::VaryingSet4; using Config = render::Task::Config; - using JobModel = render::Task::ModelI; + using JobModel = render::Task::ModelI; - DrawOutlineTask(); + DrawHighlightTask(); void configure(const Config& config); void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); @@ -221,6 +221,6 @@ private: }; -#endif // hifi_render_utils_OutlineEffect_h +#endif // hifi_render_utils_HighlightEffect_h diff --git a/libraries/render-utils/src/Outline_aabox.slv b/libraries/render-utils/src/Highlight_aabox.slv similarity index 100% rename from libraries/render-utils/src/Outline_aabox.slv rename to libraries/render-utils/src/Highlight_aabox.slv diff --git a/libraries/render-utils/src/Outline_filled.slf b/libraries/render-utils/src/Highlight_filled.slf similarity index 71% rename from libraries/render-utils/src/Outline_filled.slf rename to libraries/render-utils/src/Highlight_filled.slf index aaa3396bac..53530746f0 100644 --- a/libraries/render-utils/src/Outline_filled.slf +++ b/libraries/render-utils/src/Highlight_filled.slf @@ -1,5 +1,5 @@ -// Outline_filled.slf -// Add outline effect based on two zbuffers : one containing the total scene z and another +// Highlight_filled.slf +// Add highlight effect based on two zbuffers : one containing the total scene z and another // with the z of only the objects to be outlined. // This is the version with the fill effect inside the silhouette. // @@ -9,5 +9,5 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include Outline.slh@> +<@include Highlight.slh@> <$main(1)$> diff --git a/libraries/render-utils/src/Outline_shared.slh b/libraries/render-utils/src/Highlight_shared.slh similarity index 84% rename from libraries/render-utils/src/Outline_shared.slh rename to libraries/render-utils/src/Highlight_shared.slh index 3fd089e2fc..5efbde4d52 100644 --- a/libraries/render-utils/src/Outline_shared.slh +++ b/libraries/render-utils/src/Highlight_shared.slh @@ -1,4 +1,4 @@ -// glsl / C++ compatible source as interface for Outline +// glsl / C++ compatible source as interface for highlight #ifdef __cplusplus # define TVEC2 glm::vec2 # define TVEC3 glm::vec3 @@ -9,7 +9,7 @@ # define TVEC4 vec4 #endif -struct OutlineParameters +struct HighlightParameters { TVEC3 _color; float _intensity; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 52b8896e69..1f839b25eb 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -42,7 +42,7 @@ #include "ToneMappingEffect.h" #include "SubsurfaceScattering.h" #include "DrawHaze.h" -#include "OutlineEffect.h" +#include "HighlightEffect.h" #include @@ -183,15 +183,15 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer).asVarying(); task.addJob("ToneMapping", toneMappingInputs); - const auto outlineRangeTimer = task.addJob("BeginOutlineRangeTimer", "Outline"); + const auto outlineRangeTimer = task.addJob("BeginHighlightRangeTimer", "Highlight"); // Select items that need to be outlined const auto selectionBaseName = "contextOverlayHighlightList"; const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents); - const auto outlineInputs = DrawOutlineTask::Inputs(items.get0(), deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); - task.addJob("DrawOutline", outlineInputs); + const auto outlineInputs = DrawHighlightTask::Inputs(items.get0(), deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); + task.addJob("DrawHighlight", outlineInputs); - task.addJob("OutlineRangeTimer", outlineRangeTimer); + task.addJob("HighlightRangeTimer", outlineRangeTimer); { // DEbug the bounds of the rendered items, still look at the zbuffer task.addJob("DrawMetaBounds", metas); diff --git a/libraries/render-utils/src/UpdateSceneTask.cpp b/libraries/render-utils/src/UpdateSceneTask.cpp index d37569b526..e05f28ef0d 100644 --- a/libraries/render-utils/src/UpdateSceneTask.cpp +++ b/libraries/render-utils/src/UpdateSceneTask.cpp @@ -15,7 +15,7 @@ #include "BackgroundStage.h" #include "HazeStage.h" #include -#include +#include #include "DeferredLightingEffect.h" void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { @@ -23,7 +23,7 @@ void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render task.addJob("BackgroundStageSetup"); task.addJob("HazeStageSetup"); task.addJob("TransitionStageSetup"); - task.addJob("OutlineStyleStageSetup"); + task.addJob("HighlightStageSetup"); task.addJob("DefaultLightingSetup"); diff --git a/libraries/render/src/render/HighlightStage.cpp b/libraries/render/src/render/HighlightStage.cpp new file mode 100644 index 0000000000..effb7c7e98 --- /dev/null +++ b/libraries/render/src/render/HighlightStage.cpp @@ -0,0 +1,46 @@ +#include "HighlightStage.h" + +using namespace render; + +std::string HighlightStage::_name("Highlight"); + +HighlightStage::Index HighlightStage::addHighlight(const std::string& selectionName, const HighlightStyle& style) { + Highlight outline{ selectionName, style }; + Index id; + + id = _highlights.newElement(outline); + _activeHighlightIds.push_back(id); + + return id; +} + +void HighlightStage::removeHighlight(Index index) { + HighlightIdList::iterator idIterator = std::find(_activeHighlightIds.begin(), _activeHighlightIds.end(), index); + if (idIterator != _activeHighlightIds.end()) { + _activeHighlightIds.erase(idIterator); + } + if (!_highlights.isElementFreed(index)) { + _highlights.freeElement(index); + } +} + +Index HighlightStage::getHighlightIdBySelection(const std::string& selectionName) const { + for (auto outlineId : _activeHighlightIds) { + const auto& outline = _highlights.get(outlineId); + if (outline._selectionName == selectionName) { + return outlineId; + } + } + return INVALID_INDEX; +} + +HighlightStageSetup::HighlightStageSetup() { +} + +void HighlightStageSetup::run(const render::RenderContextPointer& renderContext) { + if (!renderContext->_scene->getStage(HighlightStage::getName())) { + auto stage = std::make_shared(); + renderContext->_scene->resetStage(HighlightStage::getName(), stage); + } +} + diff --git a/libraries/render/src/render/HighlightStage.h b/libraries/render/src/render/HighlightStage.h new file mode 100644 index 0000000000..a2c123580c --- /dev/null +++ b/libraries/render/src/render/HighlightStage.h @@ -0,0 +1,77 @@ +// +// HighlightStage.h + +// Created by Olivier Prat on 07/07/2017. +// Copyright 2017 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 +// + +#ifndef hifi_render_utils_HighlightStage_h +#define hifi_render_utils_HighlightStage_h + +#include "Stage.h" +#include "Engine.h" +#include "IndexedContainer.h" +#include "HighlightStyle.h" + +namespace render { + + // Highlight stage to set up HighlightStyle-related effects + class HighlightStage : public Stage { + public: + + class Highlight { + public: + + Highlight(const std::string& selectionName, const HighlightStyle& style) : _selectionName{ selectionName }, _style{ style } { } + + std::string _selectionName; + HighlightStyle _style; + + }; + + static const std::string& getName() { return _name; } + + using Index = render::indexed_container::Index; + static const Index INVALID_INDEX{ render::indexed_container::INVALID_INDEX }; + using HighlightIdList = render::indexed_container::Indices; + + static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } + + bool checkHighlightId(Index index) const { return _highlights.checkIndex(index); } + + const Highlight& getHighlight(Index index) const { return _highlights.get(index); } + Highlight& editHighlight(Index index) { return _highlights.edit(index); } + + Index addHighlight(const std::string& selectionName, const HighlightStyle& style = HighlightStyle()); + Index getHighlightIdBySelection(const std::string& selectionName) const; + void removeHighlight(Index index); + + HighlightIdList::iterator begin() { return _activeHighlightIds.begin(); } + HighlightIdList::iterator end() { return _activeHighlightIds.end(); } + + private: + + using Highlights = render::indexed_container::IndexedVector; + + static std::string _name; + + Highlights _highlights; + HighlightIdList _activeHighlightIds; + }; + using HighlightStagePointer = std::shared_ptr; + + class HighlightStageSetup { + public: + using JobModel = render::Job::Model; + + HighlightStageSetup(); + void run(const RenderContextPointer& renderContext); + + protected: + }; + +} +#endif // hifi_render_utils_HighlightStage_h diff --git a/libraries/render/src/render/OutlineStyle.h b/libraries/render/src/render/HighlightStyle.h similarity index 68% rename from libraries/render/src/render/OutlineStyle.h rename to libraries/render/src/render/HighlightStyle.h index cdcdf79f3e..6e7373c78b 100644 --- a/libraries/render/src/render/OutlineStyle.h +++ b/libraries/render/src/render/HighlightStyle.h @@ -1,5 +1,5 @@ // -// OutlineStyle.h +// HighlightStyle.h // Created by Olivier Prat on 11/06/2017. // Copyright 2017 High Fidelity, Inc. @@ -8,8 +8,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_render_utils_OutlineStyle_h -#define hifi_render_utils_OutlineStyle_h +#ifndef hifi_render_utils_HighlightStyle_h +#define hifi_render_utils_HighlightStyle_h #include @@ -18,7 +18,7 @@ namespace render { // This holds the configuration for a particular outline style - class OutlineStyle { + class HighlightStyle { public: bool isFilled() const { @@ -26,14 +26,13 @@ namespace render { } glm::vec3 color{ 1.f, 0.7f, 0.2f }; - float width{ 2.0f }; - float intensity{ 0.9f }; + float outlineWidth{ 2.0f }; + float outlineIntensity{ 0.9f }; float unoccludedFillOpacity{ 0.0f }; float occludedFillOpacity{ 0.0f }; - bool glow{ false }; - std::string selectionName; + bool isOutlineSmooth{ false }; }; } -#endif // hifi_render_utils_OutlineStyle_h \ No newline at end of file +#endif // hifi_render_utils_HighlightStyle_h \ No newline at end of file diff --git a/libraries/render/src/render/OutlineStyleStage.cpp b/libraries/render/src/render/OutlineStyleStage.cpp deleted file mode 100644 index e3fd1672de..0000000000 --- a/libraries/render/src/render/OutlineStyleStage.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "OutlineStyleStage.h" - -using namespace render; - -std::string OutlineStyleStage::_name("OutlineStyle"); - -OutlineStyleStage::Index OutlineStyleStage::addOutline(const std::string& selectionName, const OutlineStyle& style) { - Outline outline{ selectionName, style }; - Index id; - - id = _outlines.newElement(outline); - _activeOutlineIds.push_back(id); - - return id; -} - -void OutlineStyleStage::removeOutline(Index index) { - OutlineIdList::iterator idIterator = std::find(_activeOutlineIds.begin(), _activeOutlineIds.end(), index); - if (idIterator != _activeOutlineIds.end()) { - _activeOutlineIds.erase(idIterator); - } - if (!_outlines.isElementFreed(index)) { - _outlines.freeElement(index); - } -} - -Index OutlineStyleStage::getOutlineIdBySelection(const std::string& selectionName) const { - for (auto outlineId : _activeOutlineIds) { - const auto& outline = _outlines.get(outlineId); - if (outline._selectionName == selectionName) { - return outlineId; - } - } - return INVALID_INDEX; -} - -OutlineStyleStageSetup::OutlineStyleStageSetup() { -} - -void OutlineStyleStageSetup::run(const render::RenderContextPointer& renderContext) { - if (!renderContext->_scene->getStage(OutlineStyleStage::getName())) { - auto stage = std::make_shared(); - renderContext->_scene->resetStage(OutlineStyleStage::getName(), stage); - } -} - diff --git a/libraries/render/src/render/OutlineStyleStage.h b/libraries/render/src/render/OutlineStyleStage.h deleted file mode 100644 index 79835a22a4..0000000000 --- a/libraries/render/src/render/OutlineStyleStage.h +++ /dev/null @@ -1,77 +0,0 @@ -// -// OutlineStyleStage.h - -// Created by Olivier Prat on 07/07/2017. -// Copyright 2017 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 -// - -#ifndef hifi_render_utils_outlinestage_h -#define hifi_render_utils_outlinestage_h - -#include "Stage.h" -#include "Engine.h" -#include "IndexedContainer.h" -#include "OutlineStyle.h" - -namespace render { - - // OutlineStyle stage to set up OutlineStyle-related effects - class OutlineStyleStage : public Stage { - public: - - class Outline { - public: - - Outline(const std::string& selectionName, const OutlineStyle& style) : _selectionName{ selectionName }, _style{ style } { } - - std::string _selectionName; - OutlineStyle _style; - - }; - - static const std::string& getName() { return _name; } - - using Index = render::indexed_container::Index; - static const Index INVALID_INDEX{ render::indexed_container::INVALID_INDEX }; - using OutlineIdList = render::indexed_container::Indices; - - static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } - - bool checkOutlineId(Index index) const { return _outlines.checkIndex(index); } - - const Outline& getOutline(Index OutlineStyleId) const { return _outlines.get(OutlineStyleId); } - Outline& editOutline(Index OutlineStyleId) { return _outlines.edit(OutlineStyleId); } - - Index addOutline(const std::string& selectionName, const OutlineStyle& style = OutlineStyle()); - Index getOutlineIdBySelection(const std::string& selectionName) const; - void removeOutline(Index index); - - OutlineIdList::iterator begin() { return _activeOutlineIds.begin(); } - OutlineIdList::iterator end() { return _activeOutlineIds.end(); } - - private: - - using Outlines = render::indexed_container::IndexedVector; - - static std::string _name; - - Outlines _outlines; - OutlineIdList _activeOutlineIds; - }; - using OutlineStyleStagePointer = std::shared_ptr; - - class OutlineStyleStageSetup { - public: - using JobModel = render::Job::Model; - - OutlineStyleStageSetup(); - void run(const RenderContextPointer& renderContext); - - protected: - }; - -} -#endif // hifi_render_utils_outlinestage_h diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 0e680dfdaf..9cdaa89cf6 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -14,7 +14,7 @@ #include #include "Logging.h" #include "TransitionStage.h" -#include "OutlineStyleStage.h" +#include "HighlightStage.h" using namespace render; @@ -55,16 +55,16 @@ void Transaction::resetSelection(const Selection& selection) { _resetSelections.emplace_back(selection); } -void Transaction::resetSelectionOutline(const std::string& selectionName, const OutlineStyle& style) { - _outlineResets.emplace_back(OutlineReset{ selectionName, style }); +void Transaction::resetSelectionHighlight(const std::string& selectionName, const HighlightStyle& style) { + _highlightResets.emplace_back(HighlightReset{ selectionName, style }); } -void Transaction::removeOutlineFromSelection(const std::string& selectionName) { - _outlineRemoves.emplace_back(selectionName); +void Transaction::removeHighlightFromSelection(const std::string& selectionName) { + _highlightRemoves.emplace_back(selectionName); } -void Transaction::querySelectionOutline(const std::string& selectionName, SelectionOutlineQueryFunc func) { - _outlineQueries.emplace_back(OutlineQuery{ selectionName, func }); +void Transaction::querySelectionHighlight(const std::string& selectionName, SelectionHighlightQueryFunc func) { + _highlightQueries.emplace_back(HighlightQuery{ selectionName, func }); } void Transaction::merge(const Transaction& transaction) { @@ -75,9 +75,9 @@ void Transaction::merge(const Transaction& transaction) { _addedTransitions.insert(_addedTransitions.end(), transaction._addedTransitions.begin(), transaction._addedTransitions.end()); _queriedTransitions.insert(_queriedTransitions.end(), transaction._queriedTransitions.begin(), transaction._queriedTransitions.end()); _reAppliedTransitions.insert(_reAppliedTransitions.end(), transaction._reAppliedTransitions.begin(), transaction._reAppliedTransitions.end()); - _outlineResets.insert(_outlineResets.end(), transaction._outlineResets.begin(), transaction._outlineResets.end()); - _outlineRemoves.insert(_outlineRemoves.end(), transaction._outlineRemoves.begin(), transaction._outlineRemoves.end()); - _outlineQueries.insert(_outlineQueries.end(), transaction._outlineQueries.begin(), transaction._outlineQueries.end()); + _highlightResets.insert(_highlightResets.end(), transaction._highlightResets.begin(), transaction._highlightResets.end()); + _highlightRemoves.insert(_highlightRemoves.end(), transaction._highlightRemoves.begin(), transaction._highlightRemoves.end()); + _highlightQueries.insert(_highlightQueries.end(), transaction._highlightQueries.begin(), transaction._highlightQueries.end()); } @@ -193,9 +193,9 @@ void Scene::processTransactionFrame(const Transaction& transaction) { resetSelections(transaction._resetSelections); } - resetOutlines(transaction._outlineResets); - removeOutlines(transaction._outlineRemoves); - queryOutlines(transaction._outlineQueries); + resetHighlights(transaction._highlightResets); + removeHighlights(transaction._highlightRemoves); + queryHighlights(transaction._highlightQueries); } void Scene::resetItems(const Transaction::Resets& transactions) { @@ -336,44 +336,44 @@ void Scene::queryTransitionItems(const Transaction::TransitionQueries& transacti } } -void Scene::resetOutlines(const Transaction::OutlineResets& transactions) { - auto outlineStage = getStage(OutlineStyleStage::getName()); +void Scene::resetHighlights(const Transaction::HighlightResets& transactions) { + auto outlineStage = getStage(HighlightStage::getName()); for (auto& transaction : transactions) { const auto& selectionName = std::get<0>(transaction); const auto& newStyle = std::get<1>(transaction); - auto outlineId = outlineStage->getOutlineIdBySelection(selectionName); + auto outlineId = outlineStage->getHighlightIdBySelection(selectionName); - if (OutlineStyleStage::isIndexInvalid(outlineId)) { - outlineStage->addOutline(selectionName, newStyle); + if (HighlightStage::isIndexInvalid(outlineId)) { + outlineStage->addHighlight(selectionName, newStyle); } else { - outlineStage->editOutline(outlineId)._style = newStyle; + outlineStage->editHighlight(outlineId)._style = newStyle; } } } -void Scene::removeOutlines(const Transaction::OutlineRemoves& transactions) { - auto outlineStage = getStage(OutlineStyleStage::getName()); +void Scene::removeHighlights(const Transaction::HighlightRemoves& transactions) { + auto outlineStage = getStage(HighlightStage::getName()); for (auto& selectionName : transactions) { - auto outlineId = outlineStage->getOutlineIdBySelection(selectionName); + auto outlineId = outlineStage->getHighlightIdBySelection(selectionName); - if (!OutlineStyleStage::isIndexInvalid(outlineId)) { - outlineStage->removeOutline(outlineId); + if (!HighlightStage::isIndexInvalid(outlineId)) { + outlineStage->removeHighlight(outlineId); } } } -void Scene::queryOutlines(const Transaction::OutlineQueries& transactions) { - auto outlineStage = getStage(OutlineStyleStage::getName()); +void Scene::queryHighlights(const Transaction::HighlightQueries& transactions) { + auto outlineStage = getStage(HighlightStage::getName()); for (auto& transaction : transactions) { const auto& selectionName = std::get<0>(transaction); const auto& func = std::get<1>(transaction); - auto outlineId = outlineStage->getOutlineIdBySelection(selectionName); + auto outlineId = outlineStage->getHighlightIdBySelection(selectionName); - if (!OutlineStyleStage::isIndexInvalid(outlineId)) { - func(&outlineStage->editOutline(outlineId)._style); + if (!HighlightStage::isIndexInvalid(outlineId)) { + func(&outlineStage->editHighlight(outlineId)._style); } else { func(nullptr); } diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 38f528aced..4bf38b89cc 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -17,7 +17,7 @@ #include "Stage.h" #include "Selection.h" #include "Transition.h" -#include "OutlineStyle.h" +#include "HighlightStyle.h" namespace render { @@ -38,7 +38,7 @@ class Transaction { public: typedef std::function TransitionQueryFunc; - typedef std::function SelectionOutlineQueryFunc; + typedef std::function SelectionHighlightQueryFunc; Transaction() {} ~Transaction() {} @@ -63,9 +63,9 @@ public: // Selection transactions void resetSelection(const Selection& selection); - void resetSelectionOutline(const std::string& selectionName, const OutlineStyle& style = OutlineStyle()); - void removeOutlineFromSelection(const std::string& selectionName); - void querySelectionOutline(const std::string& selectionName, SelectionOutlineQueryFunc func); + void resetSelectionHighlight(const std::string& selectionName, const HighlightStyle& style = HighlightStyle()); + void removeHighlightFromSelection(const std::string& selectionName); + void querySelectionHighlight(const std::string& selectionName, SelectionHighlightQueryFunc func); void merge(const Transaction& transaction); @@ -81,9 +81,9 @@ protected: using TransitionQuery = std::tuple; using TransitionReApply = ItemID; using SelectionReset = Selection; - using OutlineReset = std::tuple; - using OutlineRemove = std::string; - using OutlineQuery = std::tuple; + using HighlightReset = std::tuple; + using HighlightRemove = std::string; + using HighlightQuery = std::tuple; using Resets = std::vector; using Removes = std::vector; @@ -92,9 +92,9 @@ protected: using TransitionQueries = std::vector; using TransitionReApplies = std::vector; using SelectionResets = std::vector; - using OutlineResets = std::vector; - using OutlineRemoves = std::vector; - using OutlineQueries = std::vector; + using HighlightResets = std::vector; + using HighlightRemoves = std::vector; + using HighlightQueries = std::vector; Resets _resetItems; Removes _removedItems; @@ -103,9 +103,9 @@ protected: TransitionQueries _queriedTransitions; TransitionReApplies _reAppliedTransitions; SelectionResets _resetSelections; - OutlineResets _outlineResets; - OutlineRemoves _outlineRemoves; - OutlineQueries _outlineQueries; + HighlightResets _highlightResets; + HighlightRemoves _highlightRemoves; + HighlightQueries _highlightQueries; }; typedef std::queue TransactionQueue; @@ -203,9 +203,9 @@ protected: void transitionItems(const Transaction::TransitionAdds& transactions); void reApplyTransitions(const Transaction::TransitionReApplies& transactions); void queryTransitionItems(const Transaction::TransitionQueries& transactions); - void resetOutlines(const Transaction::OutlineResets& transactions); - void removeOutlines(const Transaction::OutlineRemoves& transactions); - void queryOutlines(const Transaction::OutlineQueries& transactions); + void resetHighlights(const Transaction::HighlightResets& transactions); + void removeHighlights(const Transaction::HighlightRemoves& transactions); + void queryHighlights(const Transaction::HighlightQueries& transactions); void collectSubItems(ItemID parentId, ItemIDs& subItems) const; diff --git a/scripts/developer/utilities/render/debugOutline.js b/scripts/developer/utilities/render/debugHighlight.js similarity index 88% rename from scripts/developer/utilities/render/debugOutline.js rename to scripts/developer/utilities/render/debugHighlight.js index ce32d61e1b..5175761978 100644 --- a/scripts/developer/utilities/render/debugOutline.js +++ b/scripts/developer/utilities/render/debugHighlight.js @@ -1,5 +1,5 @@ // -// debugOutline.js +// debugHighlight.js // developer/utilities/render // // Olivier Prat, created on 08/08/2017. @@ -10,9 +10,9 @@ // // Set up the qml ui -var qml = Script.resolvePath('outline.qml'); +var qml = Script.resolvePath('highlight.qml'); var window = new OverlayWindow({ - title: 'Outline', + title: 'Highlight', source: qml, width: 400, height: 400, @@ -54,7 +54,7 @@ var end2 = { visible: true } -var outlineGroupIndex = 0 +var highlightGroupIndex = 0 var isSelectionAddEnabled = false var isSelectionEnabled = false var renderStates = [{name: "test", end: end}]; @@ -72,18 +72,18 @@ var ray = LaserPointers.createLaserPointer({ function getSelectionName() { var selectionName = "contextOverlayHighlightList" - if (outlineGroupIndex>0) { - selectionName += outlineGroupIndex + if (highlightGroupIndex>0) { + selectionName += highlightGroupIndex } return selectionName } function fromQml(message) { tokens = message.split(' ') - print("Received '"+message+"' from outline.qml") - if (tokens[0]=="outline") { - outlineGroupIndex = parseInt(tokens[1]) - print("Switching to outline group "+outlineGroupIndex) + print("Received '"+message+"' from hightlight.qml") + if (tokens[0]=="highlight") { + highlightGroupIndex = parseInt(tokens[1]) + print("Switching to highlight group "+highlightGroupIndex) } else if (tokens[0]=="pick") { isSelectionEnabled = tokens[1]=='true' print("Ray picking set to "+isSelectionEnabled.toString()) @@ -143,7 +143,7 @@ function update(deltaTime) { selectedID = prevID selectedType = prevType Selection.addToSelectedItemsList(selectionName, selectedType, selectedID) - print("OUTLINE " + outlineGroupIndex + " picked type: " + result.type + ", id: " + result.objectID); + print("HIGHLIGHT " + highlightGroupIndex + " picked type: " + result.type + ", id: " + result.objectID); } } else { if (prevID != 0 && !isSelectionAddEnabled) { diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/highlight.qml similarity index 88% rename from scripts/developer/utilities/render/outline.qml rename to scripts/developer/utilities/render/highlight.qml index 8269ea830e..eb2c66b275 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/highlight.qml @@ -1,5 +1,5 @@ // -// outline.qml +// highlight.qml // developer/utilities/render // // Olivier Prat, created on 08/08/2017. @@ -11,7 +11,7 @@ import QtQuick 2.7 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 -import "outlinePage" +import "highlightPage" import "qrc:///qml/styles-uit" import "qrc:///qml/controls-uit" as HifiControls @@ -21,7 +21,7 @@ Rectangle { color: hifi.colors.baseGray; anchors.margins: hifi.dimensions.contentMargin.x - property var debugConfig: Render.getConfig("RenderMainView.OutlineDebug") + property var debugConfig: Render.getConfig("RenderMainView.HighlightDebug") signal sendToScript(var message); Column { @@ -65,15 +65,15 @@ Rectangle { height: 400 onCurrentIndexChanged: { - sendToScript("outline "+currentIndex) + sendToScript("highlight "+currentIndex) } Repeater { model: [ 0, 1, 2, 3 ] Tab { title: "Outl."+modelData - OutlinePage { - outlineIndex: modelData + HighlightPage { + highlightIndex: modelData } } } diff --git a/scripts/developer/utilities/render/outlinePage/OutlinePage.qml b/scripts/developer/utilities/render/highlightPage/HighlightPage.qml similarity index 96% rename from scripts/developer/utilities/render/outlinePage/OutlinePage.qml rename to scripts/developer/utilities/render/highlightPage/HighlightPage.qml index ff1d7fa23b..5669f90628 100644 --- a/scripts/developer/utilities/render/outlinePage/OutlinePage.qml +++ b/scripts/developer/utilities/render/highlightPage/HighlightPage.qml @@ -1,5 +1,5 @@ // -// outlinePage.qml +// highlightPage.qml // developer/utilities/render // // Olivier Prat, created on 08/08/2017. @@ -17,8 +17,8 @@ import "qrc:///qml/controls-uit" as HifiControls Rectangle { id: root - property var outlineIndex: 0 - property var drawConfig: Render.getConfig("RenderMainView.OutlineEffect"+outlineIndex) + property var highlightIndex: 0 + property var drawConfig: Render.getConfig("RenderMainView.HighlightEffect"+highlightIndex) HifiConstants { id: hifi;} anchors.margins: hifi.dimensions.contentMargin.x diff --git a/scripts/developer/utilities/render/highlightPage/qmldir b/scripts/developer/utilities/render/highlightPage/qmldir new file mode 100644 index 0000000000..bb3de24b84 --- /dev/null +++ b/scripts/developer/utilities/render/highlightPage/qmldir @@ -0,0 +1 @@ +HighlightPage 1.0 HighlightPage.qml \ No newline at end of file diff --git a/scripts/developer/utilities/render/outlinePage/qmldir b/scripts/developer/utilities/render/outlinePage/qmldir deleted file mode 100644 index 56f5d45414..0000000000 --- a/scripts/developer/utilities/render/outlinePage/qmldir +++ /dev/null @@ -1 +0,0 @@ -OutlinePage 1.0 OutlinePage.qml \ No newline at end of file From 9817cb4c44e4f47b777fdd0368c1893e5623f554 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 7 Nov 2017 15:35:43 +0100 Subject: [PATCH 131/183] Added highlight configuration in HighlightStageSetup job --- .../ui/overlays/ContextOverlayInterface.cpp | 2 +- .../render-utils/src/HighlightEffect.cpp | 5 +- .../render/src/render/HighlightStage.cpp | 97 +++++++++++++- libraries/render/src/render/HighlightStage.h | 60 ++++++++- .../developer/utilities/render/highlight.qml | 123 ++++++++++++++++-- 5 files changed, 262 insertions(+), 25 deletions(-) diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 6a21221a8b..d40c0972e9 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -72,7 +72,7 @@ ContextOverlayInterface::ContextOverlayInterface() { render::Transaction transaction; initializeSelectionToSceneHandler(_selectionToSceneHandlers[0], "contextOverlayHighlightList", transaction); for (auto i = 1; i < MAX_SELECTION_COUNT; i++) { - auto selectionName = QString("contextOverlayHighlightList") + QString::number(i); + auto selectionName = QString("highlightList") + QString::number(i); initializeSelectionToSceneHandler(_selectionToSceneHandlers[i], selectionName, transaction); } const render::ScenePointer& scene = qApp->getMain3DScene(); diff --git a/libraries/render-utils/src/HighlightEffect.cpp b/libraries/render-utils/src/HighlightEffect.cpp index e332be53de..c938567425 100644 --- a/libraries/render-utils/src/HighlightEffect.cpp +++ b/libraries/render-utils/src/HighlightEffect.cpp @@ -434,9 +434,10 @@ void SelectionToHighlight::run(const render::RenderContextPointer& renderContext for (auto i = 0; i < HighlightSharedParameters::MAX_HIGHLIGHT_COUNT; i++) { std::ostringstream stream; - stream << "contextOverlayHighlightList"; if (i > 0) { - stream << i; + stream << "highlightList" << i; + } else { + stream << "contextOverlayHighlightList"; } auto selectionName = stream.str(); auto highlightId = highlightStage->getHighlightIdBySelection(selectionName); diff --git a/libraries/render/src/render/HighlightStage.cpp b/libraries/render/src/render/HighlightStage.cpp index effb7c7e98..6821504649 100644 --- a/libraries/render/src/render/HighlightStage.cpp +++ b/libraries/render/src/render/HighlightStage.cpp @@ -34,13 +34,96 @@ Index HighlightStage::getHighlightIdBySelection(const std::string& selectionName return INVALID_INDEX; } -HighlightStageSetup::HighlightStageSetup() { -} - -void HighlightStageSetup::run(const render::RenderContextPointer& renderContext) { - if (!renderContext->_scene->getStage(HighlightStage::getName())) { - auto stage = std::make_shared(); - renderContext->_scene->resetStage(HighlightStage::getName(), stage); +const HighlightStyle& HighlightStageConfig::getStyle() const { + auto styleIterator = _styles.find(_selectionName); + if (styleIterator != _styles.end()) { + return styleIterator->second; + } else { + auto insertion = _styles.insert(SelectionStyles::value_type{ _selectionName, HighlightStyle{} }); + return insertion.first->second; + } +} + +HighlightStyle& HighlightStageConfig::editStyle() { + auto styleIterator = _styles.find(_selectionName); + if (styleIterator != _styles.end()) { + return styleIterator->second; + } else { + auto insertion = _styles.insert(SelectionStyles::value_type{ _selectionName, HighlightStyle{} }); + return insertion.first->second; + } +} + +void HighlightStageConfig::setSelectionName(const QString& name) { + _selectionName = name.toStdString(); + emit dirty(); +} + +void HighlightStageConfig::setOutlineSmooth(bool isSmooth) { + editStyle().isOutlineSmooth = isSmooth; + emit dirty(); +} + +void HighlightStageConfig::setColorRed(float value) { + editStyle().color.r = value; + emit dirty(); +} + +void HighlightStageConfig::setColorGreen(float value) { + editStyle().color.g = value; + emit dirty(); +} + +void HighlightStageConfig::setColorBlue(float value) { + editStyle().color.b = value; + emit dirty(); +} + +void HighlightStageConfig::setOutlineWidth(float value) { + editStyle().outlineWidth = value; + emit dirty(); +} + +void HighlightStageConfig::setOutlineIntensity(float value) { + editStyle().outlineIntensity = value; + emit dirty(); +} + +void HighlightStageConfig::setUnoccludedFillOpacity(float value) { + editStyle().unoccludedFillOpacity = value; + emit dirty(); +} + +void HighlightStageConfig::setOccludedFillOpacity(float value) { + editStyle().occludedFillOpacity = value; + emit dirty(); +} + +HighlightStageSetup::HighlightStageSetup() { +} + +void HighlightStageSetup::configure(const Config& config) { + // Copy the styles here but update the stage with the new styles in run to be sure everything is + // thread safe... + _styles = config._styles; +} + +void HighlightStageSetup::run(const render::RenderContextPointer& renderContext) { + auto stage = renderContext->_scene->getStage(HighlightStage::getName()); + if (!stage) { + stage = std::make_shared(); + renderContext->_scene->resetStage(HighlightStage::getName(), stage); + } + + if (!_styles.empty()) { + render::Transaction transaction; + for (const auto& selection : _styles) { + auto& selectionName = selection.first; + auto& selectionStyle = selection.second; + transaction.resetSelectionHighlight(selectionName, selectionStyle); + } + renderContext->_scene->enqueueTransaction(transaction); + _styles.clear(); } } diff --git a/libraries/render/src/render/HighlightStage.h b/libraries/render/src/render/HighlightStage.h index a2c123580c..7600f1f724 100644 --- a/libraries/render/src/render/HighlightStage.h +++ b/libraries/render/src/render/HighlightStage.h @@ -63,14 +63,72 @@ namespace render { }; using HighlightStagePointer = std::shared_ptr; + class HighlightStageConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(QString selectionName READ getSelectionName WRITE setSelectionName NOTIFY dirty) + Q_PROPERTY(bool isOutlineSmooth READ isOutlineSmooth WRITE setOutlineSmooth NOTIFY dirty) + Q_PROPERTY(float colorR READ getColorRed WRITE setColorRed NOTIFY dirty) + Q_PROPERTY(float colorG READ getColorGreen WRITE setColorGreen NOTIFY dirty) + Q_PROPERTY(float colorB READ getColorBlue WRITE setColorBlue NOTIFY dirty) + Q_PROPERTY(float outlineWidth READ getOutlineWidth WRITE setOutlineWidth NOTIFY dirty) + Q_PROPERTY(float outlineIntensity READ getOutlineIntensity WRITE setOutlineIntensity NOTIFY dirty) + Q_PROPERTY(float unoccludedFillOpacity READ getUnoccludedFillOpacity WRITE setUnoccludedFillOpacity NOTIFY dirty) + Q_PROPERTY(float occludedFillOpacity READ getOccludedFillOpacity WRITE setOccludedFillOpacity NOTIFY dirty) + + public: + + using SelectionStyles = std::map; + + QString getSelectionName() const { return QString(_selectionName.c_str()); } + void setSelectionName(const QString& name); + + bool isOutlineSmooth() const { return getStyle().isOutlineSmooth; } + void setOutlineSmooth(bool isSmooth); + + float getColorRed() const { return getStyle().color.r; } + void setColorRed(float value); + + float getColorGreen() const { return getStyle().color.g; } + void setColorGreen(float value); + + float getColorBlue() const { return getStyle().color.b; } + void setColorBlue(float value); + + float getOutlineWidth() const { return getStyle().outlineWidth; } + void setOutlineWidth(float value); + + float getOutlineIntensity() const { return getStyle().outlineIntensity; } + void setOutlineIntensity(float value); + + float getUnoccludedFillOpacity() const { return getStyle().unoccludedFillOpacity; } + void setUnoccludedFillOpacity(float value); + + float getOccludedFillOpacity() const { return getStyle().occludedFillOpacity; } + void setOccludedFillOpacity(float value); + + std::string _selectionName{ "contextOverlayHighlightList" }; + mutable SelectionStyles _styles; + + const HighlightStyle& getStyle() const; + HighlightStyle& editStyle(); + + signals: + void dirty(); + }; + class HighlightStageSetup { public: - using JobModel = render::Job::Model; + using Config = HighlightStageConfig; + using JobModel = render::Job::Model; HighlightStageSetup(); + + void configure(const Config& config); void run(const RenderContextPointer& renderContext); protected: + + HighlightStageConfig::SelectionStyles _styles; }; } diff --git a/scripts/developer/utilities/render/highlight.qml b/scripts/developer/utilities/render/highlight.qml index eb2c66b275..6be74fcf40 100644 --- a/scripts/developer/utilities/render/highlight.qml +++ b/scripts/developer/utilities/render/highlight.qml @@ -11,9 +11,10 @@ import QtQuick 2.7 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 -import "highlightPage" + import "qrc:///qml/styles-uit" import "qrc:///qml/controls-uit" as HifiControls +import "configSlider" Rectangle { id: root @@ -22,10 +23,13 @@ Rectangle { anchors.margins: hifi.dimensions.contentMargin.x property var debugConfig: Render.getConfig("RenderMainView.HighlightDebug") + property var highlightConfig: Render.getConfig("UpdateScene.HighlightStageSetup") + signal sendToScript(var message); Column { - spacing: 5 + id: col + spacing: 10 anchors.left: parent.left anchors.right: parent.right anchors.margins: hifi.dimensions.contentMargin.x @@ -59,21 +63,112 @@ Rectangle { } } - TabView { - id: tabs - width: 384 - height: 400 + HifiControls.ComboBox { + id: box + width: 350 + z: 999 + editable: true + colorScheme: hifi.colorSchemes.dark + model: [ + "contextOverlayHighlightList", + "highlightList1", + "highlightList2", + "highlightList3", + "highlightList4"] + label: "" - onCurrentIndexChanged: { - sendToScript("highlight "+currentIndex) + Timer { + id: postpone + interval: 100; running: false; repeat: false + onTriggered: { paramWidgetLoader.sourceComponent = paramWidgets } } + onCurrentIndexChanged: { + root.highlightConfig["selectionName"] = model[currentIndex]; + sendToScript("highlight "+currentIndex) + // This is a hack to be sure the widgets below properly reflect the change of category: delete the Component + // by setting the loader source to Null and then recreate it 100ms later + paramWidgetLoader.sourceComponent = undefined; + postpone.interval = 100 + postpone.start() + } + } - Repeater { - model: [ 0, 1, 2, 3 ] - Tab { - title: "Outl."+modelData - HighlightPage { - highlightIndex: modelData + Loader { + id: paramWidgetLoader + sourceComponent: paramWidgets + width: 350 + } + + Component { + id: paramWidgets + + Column { + spacing: 10 + anchors.margins: hifi.dimensions.contentMargin.x + + HifiControls.Label { + text: "Outline" + } + Column { + spacing: 10 + anchors.left: parent.left + anchors.right: parent.right + HifiControls.CheckBox { + text: "Smooth" + checked: root.highlightConfig["isOutlineSmooth"] + onCheckedChanged: { + root.highlightConfig["isOutlineSmooth"] = checked; + } + } + Repeater { + model: ["Width:outlineWidth:5.0:0.0", + "Intensity:outlineIntensity:1.0:0.0" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: false + config: root.highlightConfig + property: modelData.split(":")[1] + max: modelData.split(":")[2] + min: modelData.split(":")[3] + } + } + } + + Separator {} + HifiControls.Label { + text: "Color" + } + Repeater { + model: ["Red:colorR:1.0:0.0", + "Green:colorG:1.0:0.0", + "Blue:colorB:1.0:0.0" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: false + config: root.highlightConfig + property: modelData.split(":")[1] + max: modelData.split(":")[2] + min: modelData.split(":")[3] + } + } + + Separator {} + HifiControls.Label { + text: "Fill Opacity" + } + Repeater { + model: ["Unoccluded:unoccludedFillOpacity:1.0:0.0", + "Occluded:occludedFillOpacity:1.0:0.0" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: false + config: root.highlightConfig + property: modelData.split(":")[1] + max: modelData.split(":")[2] + min: modelData.split(":")[3] } } } From 25b2a2ff5ee070cb90c4a94b5276fbdf341ddb4b Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 7 Nov 2017 16:57:33 +0100 Subject: [PATCH 132/183] Bounds buffer is now per instance to fix a bug --- libraries/render-utils/src/OutlineEffect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index a2bfc88c81..50c30db728 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -86,8 +86,8 @@ protected: unsigned int _outlineIndex; render::ShapePlumberPointer _shapePlumber; OutlineSharedParametersPointer _sharedParameters; + gpu::BufferPointer _boundsBuffer; - static gpu::BufferPointer _boundsBuffer; static gpu::PipelinePointer _stencilMaskPipeline; static gpu::PipelinePointer _stencilMaskFillPipeline; }; From fe79730012da39e024b86af80cb60dc5fc462593 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 7 Nov 2017 16:58:04 +0100 Subject: [PATCH 133/183] Bounds buffer is now per instance to fix a bug --- libraries/render-utils/src/OutlineEffect.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index a42cbfe358..4d2682cebd 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -99,7 +99,6 @@ void PrepareDrawOutline::run(const render::RenderContextPointer& renderContext, gpu::PipelinePointer DrawOutlineMask::_stencilMaskPipeline; gpu::PipelinePointer DrawOutlineMask::_stencilMaskFillPipeline; -gpu::BufferPointer DrawOutlineMask::_boundsBuffer; DrawOutlineMask::DrawOutlineMask(unsigned int outlineIndex, render::ShapePlumberPointer shapePlumber, OutlineSharedParametersPointer parameters) : From ffa46b487a898db3eac17a436fab8f744cd38eb0 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 7 Nov 2017 17:07:37 +0100 Subject: [PATCH 134/183] Only non empty selections are now linked to highlight passes --- .../render-utils/src/HighlightEffect.cpp | 36 ++++++++++--------- libraries/render-utils/src/HighlightEffect.h | 16 ++++----- libraries/render/src/render/Scene.cpp | 13 ++++++- libraries/render/src/render/Scene.h | 4 +++ 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/libraries/render-utils/src/HighlightEffect.cpp b/libraries/render-utils/src/HighlightEffect.cpp index c938567425..98a8835409 100644 --- a/libraries/render-utils/src/HighlightEffect.cpp +++ b/libraries/render-utils/src/HighlightEffect.cpp @@ -104,11 +104,10 @@ void PrepareDrawHighlight::run(const render::RenderContextPointer& renderContext gpu::PipelinePointer DrawHighlightMask::_stencilMaskPipeline; gpu::PipelinePointer DrawHighlightMask::_stencilMaskFillPipeline; -gpu::BufferPointer DrawHighlightMask::_boundsBuffer; DrawHighlightMask::DrawHighlightMask(unsigned int highlightIndex, render::ShapePlumberPointer shapePlumber, HighlightSharedParametersPointer parameters) : - _highlightIndex{ highlightIndex }, + _highlightPassIndex{ highlightIndex }, _shapePlumber { shapePlumber }, _sharedParameters{ parameters } { } @@ -147,7 +146,7 @@ void DrawHighlightMask::run(const render::RenderContextPointer& renderContext, c } auto highlightStage = renderContext->_scene->getStage(render::HighlightStage::getName()); - auto highlightId = _sharedParameters->_highlightIds[_highlightIndex]; + auto highlightId = _sharedParameters->_highlightIds[_highlightPassIndex]; if (!inShapes.empty() && !render::HighlightStage::isIndexInvalid(highlightId)) { auto ressources = inputs.get1(); @@ -221,8 +220,8 @@ void DrawHighlightMask::run(const render::RenderContextPointer& renderContext, c // Draw stencil mask with object bounding boxes const auto highlightWidthLoc = _stencilMaskPipeline->getProgram()->getUniforms().findLocation("outlineWidth"); - const auto sqrt3 = 1.74f; - const float blurPixelWidth = 2.0f * sqrt3 * HighlightSharedParameters::getBlurPixelWidth(highlight._style, args->_viewport.w); + const auto securityMargin = 2.0f; + const float blurPixelWidth = 2.0f * securityMargin * HighlightSharedParameters::getBlurPixelWidth(highlight._style, args->_viewport.w); const auto framebufferSize = ressources->getSourceFrameSize(); auto stencilPipeline = highlight._style.isFilled() ? _stencilMaskFillPipeline : _stencilMaskPipeline; @@ -242,7 +241,7 @@ gpu::PipelinePointer DrawHighlight::_pipeline; gpu::PipelinePointer DrawHighlight::_pipelineFilled; DrawHighlight::DrawHighlight(unsigned int highlightIndex, HighlightSharedParametersPointer parameters) : - _highlightIndex{ highlightIndex }, + _highlightPassIndex{ highlightIndex }, _sharedParameters{ parameters } { } @@ -261,9 +260,9 @@ void DrawHighlight::run(const render::RenderContextPointer& renderContext, const auto args = renderContext->args; auto highlightStage = renderContext->_scene->getStage(render::HighlightStage::getName()); - auto highlightId = _sharedParameters->_highlightIds[_highlightIndex]; + auto highlightId = _sharedParameters->_highlightIds[_highlightPassIndex]; if (!render::HighlightStage::isIndexInvalid(highlightId)) { - auto& highlight = highlightStage->getHighlight(_sharedParameters->_highlightIds[_highlightIndex]); + auto& highlight = highlightStage->getHighlight(highlightId); auto pipeline = getPipeline(highlight._style); { auto& shaderParameters = _configuration.edit(); @@ -427,12 +426,13 @@ const gpu::PipelinePointer& DebugHighlight::getDepthPipeline() { } void SelectionToHighlight::run(const render::RenderContextPointer& renderContext, Outputs& outputs) { - auto highlightStage = renderContext->_scene->getStage(render::HighlightStage::getName()); + auto scene = renderContext->_scene; + auto highlightStage = scene->getStage(render::HighlightStage::getName()); outputs.clear(); _sharedParameters->_highlightIds.fill(render::HighlightStage::INVALID_INDEX); - for (auto i = 0; i < HighlightSharedParameters::MAX_HIGHLIGHT_COUNT; i++) { + for (auto i = 0; i < HighlightSharedParameters::MAX_PASS_COUNT; i++) { std::ostringstream stream; if (i > 0) { stream << "highlightList" << i; @@ -440,17 +440,19 @@ void SelectionToHighlight::run(const render::RenderContextPointer& renderContext stream << "contextOverlayHighlightList"; } auto selectionName = stream.str(); - auto highlightId = highlightStage->getHighlightIdBySelection(selectionName); - if (!render::HighlightStage::isIndexInvalid(highlightId)) { - _sharedParameters->_highlightIds[outputs.size()] = highlightId; - outputs.emplace_back(selectionName); + if (!scene->isSelectionEmpty(selectionName)) { + auto highlightId = highlightStage->getHighlightIdBySelection(selectionName); + if (!render::HighlightStage::isIndexInvalid(highlightId)) { + _sharedParameters->_highlightIds[outputs.size()] = highlightId; + outputs.emplace_back(selectionName); + } } } } void ExtractSelectionName::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { - if (_highlightIndex < inputs.size()) { - outputs = inputs[_highlightIndex]; + if (_highlightPassIndex < inputs.size()) { + outputs = inputs[_highlightPassIndex]; } else { outputs.clear(); } @@ -487,7 +489,7 @@ void DrawHighlightTask::build(JobModel& task, const render::Varying& inputs, ren const auto highlightRessources = task.addJob("PrepareHighlight", primaryFramebuffer); render::Varying highlight0Rect; - for (auto i = 0; i < HighlightSharedParameters::MAX_HIGHLIGHT_COUNT; i++) { + for (auto i = 0; i < HighlightSharedParameters::MAX_PASS_COUNT; i++) { const auto selectionName = task.addJob("ExtractSelectionName", highlightSelectionNames, i); const auto groupItems = addSelectItemJobs(task, selectionName, items); const auto highlightedItemIDs = task.addJob("HighlightMetaToSubItemIDs", groupItems); diff --git a/libraries/render-utils/src/HighlightEffect.h b/libraries/render-utils/src/HighlightEffect.h index 0531c03efd..90a8e730ce 100644 --- a/libraries/render-utils/src/HighlightEffect.h +++ b/libraries/render-utils/src/HighlightEffect.h @@ -50,12 +50,12 @@ class HighlightSharedParameters { public: enum { - MAX_HIGHLIGHT_COUNT = 8 + MAX_PASS_COUNT = 8 }; HighlightSharedParameters(); - std::array _highlightIds; + std::array _highlightIds; static float getBlurPixelWidth(const render::HighlightStyle& style, int frameBufferHeight); }; @@ -100,13 +100,13 @@ public: using Outputs = std::string; using JobModel = render::Job::ModelIO; - ExtractSelectionName(unsigned int highlightIndex) : _highlightIndex{ highlightIndex } {} + ExtractSelectionName(unsigned int highlightIndex) : _highlightPassIndex{ highlightIndex } {} void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); private: - unsigned int _highlightIndex; + unsigned int _highlightPassIndex; }; @@ -123,11 +123,11 @@ public: protected: - unsigned int _highlightIndex; + unsigned int _highlightPassIndex; render::ShapePlumberPointer _shapePlumber; HighlightSharedParametersPointer _sharedParameters; - - static gpu::BufferPointer _boundsBuffer; + gpu::BufferPointer _boundsBuffer; + static gpu::PipelinePointer _stencilMaskPipeline; static gpu::PipelinePointer _stencilMaskFillPipeline; }; @@ -162,7 +162,7 @@ private: static gpu::PipelinePointer _pipeline; static gpu::PipelinePointer _pipelineFilled; - unsigned int _highlightIndex; + unsigned int _highlightPassIndex; HighlightParameters _parameters; HighlightSharedParametersPointer _sharedParameters; HighlightConfigurationBuffer _configuration; diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 9cdaa89cf6..88e25b6d27 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -426,7 +426,7 @@ void Scene::resetItemTransition(ItemID itemId) { } } -// THis fucntion is thread safe +// This function is thread safe Selection Scene::getSelection(const Selection::Name& name) const { std::unique_lock lock(_selectionsMutex); auto found = _selections.find(name); @@ -437,6 +437,17 @@ Selection Scene::getSelection(const Selection::Name& name) const { } } +// This function is thread safe +bool Scene::isSelectionEmpty(const Selection::Name& name) const { + std::unique_lock lock(_selectionsMutex); + auto found = _selections.find(name); + if (found == _selections.end()) { + return false; + } else { + return (*found).second.isEmpty(); + } +} + void Scene::resetSelections(const Transaction::SelectionResets& transactions) { for (auto selection : transactions) { auto found = _selections.find(selection.getName()); diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 4bf38b89cc..af6204acb4 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -143,6 +143,10 @@ public: // Thread safe Selection getSelection(const Selection::Name& name) const; + // Check if a particular selection is empty (returns true if doesn't exist) + // Thread safe + bool isSelectionEmpty(const Selection::Name& name) const; + // This next call are NOT threadsafe, you have to call them from the correct thread to avoid any potential issues // Access a particular item form its ID From 0bbd1edc0aff10cb275c11bfae23c211dcf9603f Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 7 Nov 2017 18:26:15 +0100 Subject: [PATCH 135/183] Fixed fluttering highlight bug by attaching only stencil when drawing outline --- libraries/gpu/src/gpu/Framebuffer.cpp | 63 +++++++++++++++---- libraries/gpu/src/gpu/Framebuffer.h | 3 + .../render-utils/src/HighlightEffect.cpp | 2 +- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index f1257e7c83..4fcc9ab0f9 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -220,7 +220,7 @@ uint32 Framebuffer::getRenderBufferSubresource(uint32 slot) const { } } -bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource) { +bool Framebuffer::assignDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource) { if (isSwapchain()) { return false; } @@ -244,20 +244,59 @@ bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, const For // assign the new one _depthStencilBuffer = TextureView(texture, subresource, format); - _bufferMask = ( _bufferMask & ~BUFFER_DEPTHSTENCIL); - if (texture) { - if (format.getSemantic() == gpu::DEPTH) { - _bufferMask |= BUFFER_DEPTH; - } else if (format.getSemantic() == gpu::STENCIL) { - _bufferMask |= BUFFER_STENCIL; - } else if (format.getSemantic() == gpu::DEPTH_STENCIL) { - _bufferMask |= BUFFER_DEPTHSTENCIL; - } - } - return true; } +bool Framebuffer::setDepthBuffer(const TexturePointer& texture, const Format& format, uint32 subresource) { + if (assignDepthStencilBuffer(texture, format, subresource)) { + _bufferMask = (_bufferMask & ~BUFFER_DEPTHSTENCIL); + if (texture) { + if (format.getSemantic() == gpu::DEPTH || format.getSemantic() == gpu::DEPTH_STENCIL) { + _bufferMask |= BUFFER_DEPTH; + } else { + return false; + } + } + + return true; + } + return false; +} + +bool Framebuffer::setStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource) { + if (assignDepthStencilBuffer(texture, format, subresource)) { + _bufferMask = (_bufferMask & ~BUFFER_DEPTHSTENCIL); + if (texture) { + if (format.getSemantic() == gpu::STENCIL || format.getSemantic() == gpu::DEPTH_STENCIL) { + _bufferMask |= BUFFER_STENCIL; + } else { + return false; + } + } + + return true; + } + return false; +} + +bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource) { + if (assignDepthStencilBuffer(texture, format, subresource)) { + _bufferMask = (_bufferMask & ~BUFFER_DEPTHSTENCIL); + if (texture) { + if (format.getSemantic() == gpu::DEPTH) { + _bufferMask |= BUFFER_DEPTH; + } else if (format.getSemantic() == gpu::STENCIL) { + _bufferMask |= BUFFER_STENCIL; + } else if (format.getSemantic() == gpu::DEPTH_STENCIL) { + _bufferMask |= BUFFER_DEPTHSTENCIL; + } + } + + return true; + } + return false; +} + TexturePointer Framebuffer::getDepthStencilBuffer() const { if (isSwapchain()) { return TexturePointer(); diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index b3a500d68f..b3cf0fbba3 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -107,6 +107,8 @@ public: TexturePointer getRenderBuffer(uint32 slot) const; uint32 getRenderBufferSubresource(uint32 slot) const; + bool setDepthBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0); + bool setStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0); bool setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0); TexturePointer getDepthStencilBuffer() const; uint32 getDepthStencilBufferSubresource() const; @@ -168,6 +170,7 @@ protected: uint16 _numSamples = 0; void updateSize(const TexturePointer& texture); + bool assignDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource); // Non exposed Framebuffer(const Framebuffer& framebuffer) = delete; diff --git a/libraries/render-utils/src/HighlightEffect.cpp b/libraries/render-utils/src/HighlightEffect.cpp index 98a8835409..7c58e5ba66 100644 --- a/libraries/render-utils/src/HighlightEffect.cpp +++ b/libraries/render-utils/src/HighlightEffect.cpp @@ -59,7 +59,7 @@ void HighlightRessources::update(const gpu::FramebufferPointer& primaryFrameBuff void HighlightRessources::allocateColorBuffer(const gpu::FramebufferPointer& primaryFrameBuffer) { _colorFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithStencil")); _colorFrameBuffer->setRenderBuffer(0, primaryFrameBuffer->getRenderBuffer(0)); - _colorFrameBuffer->setDepthStencilBuffer(_depthStencilTexture, _depthStencilTexture->getTexelFormat()); + _colorFrameBuffer->setStencilBuffer(_depthStencilTexture, _depthStencilTexture->getTexelFormat()); } void HighlightRessources::allocateDepthBuffer(const gpu::FramebufferPointer& primaryFrameBuffer) { From f248eb5518daf79a1671ee1c1890abb0d56550e0 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 7 Nov 2017 11:30:09 -0800 Subject: [PATCH 136/183] Change wallet home when 0 transactions --- .../qml/hifi/commerce/wallet/WalletHome.qml | 62 +++++++++++++++---- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index 1fe0dcc58b..ff89f01943 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -196,7 +196,52 @@ Item { anchors.bottom: parent.bottom; anchors.left: parent.left; anchors.right: parent.right; - anchors.rightMargin: 24; + + Item { + visible: transactionHistoryModel.count === 0 && root.historyReceived; + anchors.centerIn: parent; + width: parent.width - 12; + height: parent.height; + + HifiControlsUit.Separator { + colorScheme: 1; + anchors.left: parent.left; + anchors.right: parent.right; + anchors.top: parent.top; + } + + RalewayRegular { + id: noActivityText; + text: "No activity yet.


Looking for a little spending money?
Click the button below to apply for your free HFC!"; + // Text size + size: 24; + // Style + color: hifi.colors.blueAccent; + anchors.top: parent.top; + anchors.topMargin: 26; + anchors.left: parent.left; + anchors.right: parent.right; + height: paintedHeight; + wrapMode: Text.WordWrap; + horizontalAlignment: Text.AlignHCenter; + } + + // "Apply" button + HifiControlsUit.Button { + id: changePassphraseButton; + color: hifi.buttons.blue; + colorScheme: hifi.colorSchemes.dark; + anchors.top: noActivityText.bottom; + anchors.topMargin: 25; + anchors.horizontalCenter: parent.horizontalCenter; + width: 180; + height: 40; + text: "Apply Now"; + onClicked: { + Qt.openUrlExternally("https://www.highfidelity.com/"); + } + } + } ListView { id: transactionHistory; @@ -294,17 +339,6 @@ Item { } } } - - // This should never be visible (since you immediately get 100 HFC) - FiraSansRegular { - id: emptyTransationHistory; - size: 24; - visible: !transactionHistory.visible && root.historyReceived; - text: "Recent Activity Unavailable"; - anchors.fill: parent; - horizontalAlignment: Text.AlignHCenter; - verticalAlignment: Text.AlignVCenter; - } } } @@ -350,7 +384,9 @@ Item { } root.pendingCount = pendingCount; - transactionHistoryModel.insert(0, {"transaction_type": "pendingCount"}); + if (pendingCount > 0) { + transactionHistoryModel.insert(0, {"transaction_type": "pendingCount"}); + } } // From 8f54c106f6411ad8cfe624fdf3a32ac72fbb0e5f Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 7 Nov 2017 12:12:27 -0800 Subject: [PATCH 137/183] Could it be this simple? --- interface/src/commerce/Ledger.cpp | 9 +++++++++ interface/src/commerce/Wallet.cpp | 16 ++++++++++++---- interface/src/commerce/Wallet.h | 5 +++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index f607c923ee..ed862384dc 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -90,6 +90,15 @@ void Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, cons signedSend("transaction", transactionString, hfc_key, "buy", "buySuccess", "buyFailure", controlled_failure); } +void Ledger::receiveAtSuccess(QNetworkReply& reply) { + auto wallet = DependencyManager::get(); + QByteArray response = reply.readAll(); + QJsonObject data = QJsonDocument::fromJson(response).object(); + + if (data["status"] == "fail") { // Not on "The List" for receiving HFC + wallet->setMustRegenerateKeypair(true); + } +} bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key, const QString& machine_fingerprint) { auto accountManager = DependencyManager::get(); if (!accountManager->isLoggedIn()) { diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 9bc8dc9e43..b746b58015 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -327,6 +327,12 @@ Wallet::Wallet() { auto walletScriptingInterface = DependencyManager::get(); uint status; + if (_mustRegenerateKeypair) { + _mustRegenerateKeypair = false; + resetKeysOnly(); + generateKeyPair(); + } + if (wallet->getKeyFilePath() == "" || !wallet->getSecurityImage()) { status = (uint)WalletStatus::WALLET_STATUS_NOT_SET_UP; } else if (!wallet->walletIsAuthenticatedWithPassphrase()) { @@ -661,9 +667,13 @@ QString Wallet::getKeyFilePath() { } } -void Wallet::reset() { +void Wallet::resetKeysOnly() { _publicKeys.clear(); + QFile keyFile(keyFilePath()); + keyFile.remove(); +} +void Wallet::reset() { delete _securityImage; _securityImage = nullptr; @@ -671,9 +681,7 @@ void Wallet::reset() { updateImageProvider(); _passphrase->clear(); - - QFile keyFile(keyFilePath()); - keyFile.remove(); + resetKeysOnly(); } bool Wallet::writeWallet(const QString& newPassphrase) { RSA* keys = readKeys(keyFilePath().toStdString().c_str()); diff --git a/interface/src/commerce/Wallet.h b/interface/src/commerce/Wallet.h index ed145df451..f0f13aaf6e 100644 --- a/interface/src/commerce/Wallet.h +++ b/interface/src/commerce/Wallet.h @@ -49,6 +49,7 @@ public: bool walletIsAuthenticatedWithPassphrase(); bool changePassphrase(const QString& newPassphrase); + void resetKeysOnly(); void reset(); void getWalletStatus(); @@ -59,6 +60,8 @@ public: WALLET_STATUS_READY }; + void setMustRegenerateKeypair(const bool& val) { _mustRegenerateKeypair = val; } + signals: void securityImageResult(bool exists); void keyFilePathIfExistsResult(const QString& path); @@ -83,6 +86,8 @@ private: bool writeBackupInstructions(); void account(); + + bool _mustRegenerateKeypair { false }; }; #endif // hifi_Wallet_h From 6481e0f713169e51205855ff64688b32b86b019e Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 7 Nov 2017 12:52:23 -0800 Subject: [PATCH 138/183] Address cauterized cluster matrices issue --- libraries/render-utils/src/CauterizedMeshPartPayload.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp index a54a072b75..a5d782098d 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp @@ -39,8 +39,8 @@ void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector (const gpu::Byte*) cauterizedClusterMatrices.data()); } else { - _cauterizedClusterBuffer->setSubData(0, clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) clusterMatrices.data()); + _cauterizedClusterBuffer->setSubData(0, cauterizedClusterMatrices.size() * sizeof(glm::mat4), + (const gpu::Byte*) cauterizedClusterMatrices.data()); } } } From e37010565fd77ff0e4778d5c44d3d70831abe467 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 7 Nov 2017 16:55:07 -0800 Subject: [PATCH 139/183] changed fileDialog return value to be compatible with musvis --- interface/src/Application.cpp | 4 ---- libraries/ui/src/OffscreenUi.cpp | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d099af9ea0..0b580ddb5d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2702,7 +2702,6 @@ bool Application::importFromZIP(const QString& filePath) { return true; } -<<<<<<< HEAD bool Application::importFromFBX(const QString& filePath) { qDebug() << "An fbx file has been dropped in: " << filePath; QUrl empty; @@ -2715,9 +2714,6 @@ bool Application::importFromFBX(const QString& filePath) { return true; } -======= -// thread-safe ->>>>>>> 85efe5265d1e31eccae22571e407b938030c8f6e void Application::onPresent(quint32 frameCount) { bool expected = false; if (_pendingIdleEvent.compare_exchange_strong(expected, true)) { diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 297ed9ca50..96272c4f1f 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -720,7 +720,8 @@ QString OffscreenUi::fileDialog(const QVariantMap& properties) { return QString(); } qCDebug(uiLogging) << result.toString(); - return result.toUrl().toLocalFile(); + // originally was result.toUrl().toLocalFile();, but toLocalFile() is not working + return result.toString(); } ModalDialogListener* OffscreenUi::fileDialogAsync(const QVariantMap& properties) { From 9a09ffe12f4f9a3d82990f329aa61048ed5814de Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 7 Nov 2017 17:10:57 -0800 Subject: [PATCH 140/183] removed old fbx code --- interface/src/Application.cpp | 45 +++++++++-------------------------- interface/src/Application.h | 1 - 2 files changed, 11 insertions(+), 35 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0b580ddb5d..1ca58311d4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -355,8 +355,7 @@ const QHash Application::_acceptedExtensi { JS_EXTENSION, &Application::askToLoadScript }, { FST_EXTENSION, &Application::askToSetAvatarUrl }, { JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent }, - { ZIP_EXTENSION, &Application::importFromZIP }, - { FBX_EXTENSION, &Application::importFromFBX } + { ZIP_EXTENSION, &Application::importFromZIP } }; class DeadlockWatchdogThread : public QThread { @@ -2702,17 +2701,7 @@ bool Application::importFromZIP(const QString& filePath) { return true; } -bool Application::importFromFBX(const QString& filePath) { - qDebug() << "An fbx file has been dropped in: " << filePath; - QUrl empty; - // handle Blocks download from Marketplace - if (filePath.contains("vr.google.com/downloads")) { - addAssetToWorldFromURL(filePath); - } else { - addAssetToWorld(filePath, "", false, false); - } - return true; -} +// thread-safe void Application::onPresent(quint32 frameCount) { bool expected = false; @@ -6250,11 +6239,7 @@ void Application::addAssetToWorldFromURL(QString url) { if (url.contains("vr.google.com/downloads")) { filename = url.section('/', -1); if (url.contains("noDownload")) { - if (url.contains(".fbx")) { - filename.remove("?noDownload=false"); - } else { - filename.remove(".zip?noDownload=false"); - } + filename.remove(".zip?noDownload=false"); } else { filename.remove(".zip"); } @@ -6281,7 +6266,7 @@ void Application::addAssetToWorldFromURLRequestFinished() { auto result = request->getResult(); QString filename; - bool isBlocksOBJ = false; + bool isBlocks = false; if (url.contains("filename")) { filename = url.section("filename=", 1, 1); // Filename is in "?filename=" parameter at end of URL. @@ -6289,15 +6274,11 @@ void Application::addAssetToWorldFromURLRequestFinished() { if (url.contains("vr.google.com/downloads")) { filename = url.section('/', -1); if (url.contains("noDownload")) { - if (url.contains(".fbx")) { - filename.remove("?noDownload=false"); - } else { - filename.remove(".zip?noDownload=false"); - } + filename.remove(".zip?noDownload=false"); } else { filename.remove(".zip"); } - isBlocksOBJ = true; + isBlocks = true; } if (result == ResourceRequest::Success) { @@ -6314,11 +6295,7 @@ void Application::addAssetToWorldFromURLRequestFinished() { tempFile.write(request->getData()); addAssetToWorldInfoClear(filename); // Remove message from list; next one added will have a different key. tempFile.close(); - if (url.contains(".fbx")) { - addAssetToWorld(downloadPath, "", false, false); - } else { - qApp->getFileDownloadInterface()->runUnzip(downloadPath, url, true, false, isBlocksOBJ); - } + qApp->getFileDownloadInterface()->runUnzip(downloadPath, url, true, false, isBlocks); } else { QString errorInfo = "Couldn't open temporary file for download"; qWarning(interfaceapp) << errorInfo; @@ -6348,7 +6325,7 @@ void Application::addAssetToWorldUnzipFailure(QString filePath) { addAssetToWorldError(filename, "Couldn't unzip file " + filename + "."); } -void Application::addAssetToWorld(QString filePath, QString zipFile, bool isZip, bool isBlocksOBJ) { +void Application::addAssetToWorld(QString filePath, QString zipFile, bool isZip, bool isBlocks) { // Automatically upload and add asset to world as an alternative manual process initiated by showAssetServerWidget(). QString mapping; QString path = filePath; @@ -6357,7 +6334,7 @@ void Application::addAssetToWorld(QString filePath, QString zipFile, bool isZip, QString assetFolder = zipFile.section("/", -1); assetFolder.remove(".zip"); mapping = "/" + assetFolder + "/" + filename; - } else if (isBlocksOBJ) { + } else if (isBlocks) { qCDebug(interfaceapp) << "Path to asset folder: " << zipFile; QString assetFolder = zipFile.section('/', -1); assetFolder.remove(".zip?noDownload=false"); @@ -6750,12 +6727,12 @@ void Application::onAssetToWorldMessageBoxClosed() { } -void Application::handleUnzip(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip, bool isBlocksOBJ) { +void Application::handleUnzip(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip, bool isBlocks) { if (autoAdd) { if (!unzipFile.isEmpty()) { for (int i = 0; i < unzipFile.length(); i++) { qCDebug(interfaceapp) << "Preparing file for asset server: " << unzipFile.at(i); - addAssetToWorld(unzipFile.at(i), zipFile, isZip, isBlocksOBJ); + addAssetToWorld(unzipFile.at(i), zipFile, isZip, isBlocks); } } else { addAssetToWorldUnzipFailure(zipFile); diff --git a/interface/src/Application.h b/interface/src/Application.h index 03e256fba7..fbfb3979be 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -472,7 +472,6 @@ private: bool importJSONFromURL(const QString& urlString); bool importSVOFromURL(const QString& urlString); bool importFromZIP(const QString& filePath); - bool importFromFBX(const QString& filePath); bool nearbyEntitiesAreReadyForPhysics(); int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode); From 1ceec174052aa7295aa170738c74cb8a3bea34e0 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 7 Nov 2017 17:12:39 -0800 Subject: [PATCH 141/183] missed an fbx block --- interface/src/Application.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1ca58311d4..4f051697ad 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2702,7 +2702,6 @@ bool Application::importFromZIP(const QString& filePath) { } // thread-safe - void Application::onPresent(quint32 frameCount) { bool expected = false; if (_pendingIdleEvent.compare_exchange_strong(expected, true)) { @@ -6467,13 +6466,6 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { // Close progress message box. addAssetToWorldInfoDone(filenameFromPath(filePath)); } - - // Delete temporary directories created from downloads - if (filePath.contains(".fbx")) { - QString tempPath = filePath.remove(filePath.section("/", -1)); - qCDebug(interfaceapp) << "Removing temporary path: " << tempPath; - QDir(tempPath).removeRecursively(); - } } void Application::addAssetToWorldCheckModelSize() { From ebe5d51ee8164eda2a6b2aca528df10c5b0fc49a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 8 Nov 2017 14:25:10 +1300 Subject: [PATCH 142/183] Label models.json.gz paths in server Content tab with operating system --- domain-server/resources/web/content/index.shtml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/domain-server/resources/web/content/index.shtml b/domain-server/resources/web/content/index.shtml index e1ba5499b6..0e48c1eff8 100644 --- a/domain-server/resources/web/content/index.shtml +++ b/domain-server/resources/web/content/index.shtml @@ -19,12 +19,13 @@ Upload an entities file (e.g.: models.json.gz) to replace the content of this domain.
Note: Your domain's content will be replaced by the content you upload, but the backup files of your domain's content will not immediately be changed.

-

- If your domain has any content that you would like to re-use at a later date, save a manual backup of your models.json.gz file, which is usually stored at the following paths:
-

C:/Users/[username]/AppData/Roaming/High Fidelity/assignment-client/entities/models.json.gz
-
/Users/[username]/Library/Application Support/High Fidelity/assignment-client/entities/models.json.gz
-
/home/[username]/.local/share/High Fidelity/assignment-client/entities/models.json.gz
-

+

If your domain has any content that you would like to re-use at a later date, save a manual backup of your models.json.gz file, which is usually stored at the following paths:

+ +
C:/Users/[username]/AppData/Roaming/High Fidelity/assignment-client/entities/models.json.gz
+ +
/Users/[username]/Library/Application Support/High Fidelity/assignment-client/entities/models.json.gz
+ +
/home/[username]/.local/share/High Fidelity/assignment-client/entities/models.json.gz


From 0718763ed1d8ff076e13ca8de8460236bd365d80 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 7 Nov 2017 17:31:15 -0800 Subject: [PATCH 143/183] Adjust syntax --- libraries/render-utils/src/CauterizedMeshPartPayload.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp index a5d782098d..983832e9c8 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp @@ -37,8 +37,7 @@ void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector if (!_cauterizedClusterBuffer) { _cauterizedClusterBuffer = std::make_shared(cauterizedClusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) cauterizedClusterMatrices.data()); - } - else { + } else { _cauterizedClusterBuffer->setSubData(0, cauterizedClusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) cauterizedClusterMatrices.data()); } From bbcb0b2d9b82dce3d233d4e207f4419af115d7b3 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 8 Nov 2017 13:49:18 +0100 Subject: [PATCH 144/183] Fixed highlight in stereo mode, including HMD (testing on simulator) --- libraries/gpu/src/gpu/Transform.slh | 12 ++++++++---- libraries/render-utils/src/Highlight_aabox.slv | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 9feca4a3c9..b9b8544601 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -193,13 +193,17 @@ TransformObject getTransformObject() { } <@endfunc@> -<@func transformModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@> - { // transformModelToClipPos +<@func transformModelToMonoClipPos(cameraTransform, objectTransform, modelPos, clipPos)@> + { // transformModelToMonoClipPos vec4 eyeWAPos; <$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$> - <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos; - + } +<@endfunc@> + +<@func transformModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@> + { // transformModelToClipPos + <$transformModelToMonoClipPos($cameraTransform$, $objectTransform$, $modelPos$, $clipPos$)$> <$transformStereoClipsSpace($cameraTransform$, $clipPos$)$> } <@endfunc@> diff --git a/libraries/render-utils/src/Highlight_aabox.slv b/libraries/render-utils/src/Highlight_aabox.slv index 1a46ccd9c7..4927db9610 100644 --- a/libraries/render-utils/src/Highlight_aabox.slv +++ b/libraries/render-utils/src/Highlight_aabox.slv @@ -93,11 +93,12 @@ void main(void) { // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, pos, gl_Position)$> + <$transformModelToMonoClipPos(cam, obj, pos, gl_Position)$> // Offset the vertex to take into account the outline width pos.xyz += UNIT_BOX_NORMALS[triangleIndex]; vec4 offsetPosition; - <$transformModelToClipPos(cam, obj, pos, offsetPosition)$> + <$transformModelToMonoClipPos(cam, obj, pos, offsetPosition)$> gl_Position.xy += normalize(offsetPosition.xy-gl_Position.xy) * outlineWidth * gl_Position.w; + <$transformStereoClipsSpace(cam, gl_Position)$> } From 5e32298183caa1cc7ef8f1a05d372d545cf6bef8 Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 8 Nov 2017 18:43:59 +0100 Subject: [PATCH 145/183] Rework as script=only solution --- interface/src/Application.cpp | 18 ++++-------------- interface/src/Application.h | 4 ---- scripts/developer/debugging/debugWindow.js | 10 ++++++++++ 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 13765e41d3..4f051697ad 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5781,7 +5781,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe ClipboardScriptingInterface* clipboardScriptable = new ClipboardScriptingInterface(); scriptEngine->registerGlobalObject("Clipboard", clipboardScriptable); connect(scriptEngine.data(), &ScriptEngine::finished, clipboardScriptable, &ClipboardScriptingInterface::deleteLater); - connect(scriptEngine.data(), &ScriptEngine::finished, this, &Application::cleanupRunningScripts); scriptEngine->registerGlobalObject("Overlays", &_overlays); qScriptRegisterMetaType(scriptEngine.data(), OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue); @@ -6195,15 +6194,10 @@ void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const } void Application::showScriptLogs() { - if (!_runningScripts.contains("debugWindow.js")) { - auto scriptEngines = DependencyManager::get(); - QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation(); - defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js"); - ScriptEnginePointer sePointer = scriptEngines->loadScript(defaultScriptsLoc.toString()); - _runningScripts["debugWindow.js"] = sePointer; - } else { - qWarning() << "Scripts Log already running"; - } + auto scriptEngines = DependencyManager::get(); + QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation(); + defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js"); + scriptEngines->loadScript(defaultScriptsLoc.toString()); } void Application::showAssetServerWidget(QString filePath) { @@ -7302,10 +7296,6 @@ void Application::switchDisplayMode() { _previousHMDWornStatus = currentHMDWornStatus; } -void Application::cleanupRunningScripts(const QString& fileNameString, ScriptEnginePointer) { - _runningScripts.remove(QUrl(fileNameString).fileName()); -} - void Application::startHMDStandBySession() { _autoSwitchDisplayModeSupportedHMDPlugin->startStandBySession(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index c651ea6d5b..fbfb3979be 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -440,8 +440,6 @@ private slots: void handleSandboxStatus(QNetworkReply* reply); void switchDisplayMode(); - - void cleanupRunningScripts(const QString& fileNameString, ScriptEnginePointer); private: static void initDisplay(); void init(); @@ -712,7 +710,5 @@ private: std::atomic _pendingIdleEvent { false }; std::atomic _pendingRenderEvent { false }; - - QHash _runningScripts; }; #endif // hifi_Application_h diff --git a/scripts/developer/debugging/debugWindow.js b/scripts/developer/debugging/debugWindow.js index b16739b2b8..4390cf1f77 100644 --- a/scripts/developer/debugging/debugWindow.js +++ b/scripts/developer/debugging/debugWindow.js @@ -10,13 +10,23 @@ (function() { // BEGIN LOCAL_SCOPE +//check if script already running. +var scriptData = ScriptDiscoveryService.getRunning(); +var scripts = scriptData.filter(function (datum) { return datum.name === 'debugWindow.js'; }); +if (scripts.length >= 2) { + //2nd instance of the script is too much + return; +} + // Set up the qml ui var qml = Script.resolvePath('debugWindow.qml'); + var window = new OverlayWindow({ title: 'Debug Window', source: qml, width: 400, height: 900, }); + window.setPosition(25, 50); window.closed.connect(function() { Script.stop(); }); From b7163bb8fc1bf1e9425ae3a2c12e487f14f84ccd Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 8 Nov 2017 10:24:26 -0800 Subject: [PATCH 146/183] Frontend changes --- interface/resources/qml/hifi/commerce/wallet/WalletHome.qml | 3 ++- interface/src/commerce/Ledger.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index ff89f01943..9b244d66ca 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -212,7 +212,8 @@ Item { RalewayRegular { id: noActivityText; - text: "No activity yet.


Looking for a little spending money?
Click the button below to apply for your free HFC!"; + text: "The Wallet app is in closed Beta.

To request entry and receive free HFC, please contact " + + "info@highfidelity.com with your High Fidelity account username and the email address registered to that account."; // Text size size: 24; // Style diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index ed862384dc..01c11347fd 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -43,7 +43,6 @@ QJsonObject Ledger::failResponse(const QString& label, QNetworkReply& reply) { #define FailHandler(NAME) void Ledger::NAME##Failure(QNetworkReply& reply) { emit NAME##Result(failResponse(#NAME, reply)); } #define Handler(NAME) ApiHandler(NAME) FailHandler(NAME) Handler(buy) -Handler(receiveAt) Handler(balance) Handler(inventory) @@ -99,6 +98,7 @@ void Ledger::receiveAtSuccess(QNetworkReply& reply) { wallet->setMustRegenerateKeypair(true); } } +void Ledger::receiveAtFailure(QNetworkReply& reply) { failResponse("receiveAt", reply); } bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key, const QString& machine_fingerprint) { auto accountManager = DependencyManager::get(); if (!accountManager->isLoggedIn()) { From 72fa0823ba05a21bf04af4358070e70c09843ca6 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 8 Nov 2017 10:40:47 -0800 Subject: [PATCH 147/183] Logic changes --- .../qml/hifi/commerce/wallet/WalletHome.qml | 21 +++---------------- interface/src/commerce/Wallet.cpp | 6 +++++- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index 9b244d66ca..fd7ce0fdfd 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -218,30 +218,15 @@ Item { size: 24; // Style color: hifi.colors.blueAccent; - anchors.top: parent.top; - anchors.topMargin: 26; anchors.left: parent.left; + anchors.leftMargin: 12; anchors.right: parent.right; + anchors.rightMargin: 12; + anchors.verticalCenter: parent.verticalCenter; height: paintedHeight; wrapMode: Text.WordWrap; horizontalAlignment: Text.AlignHCenter; } - - // "Apply" button - HifiControlsUit.Button { - id: changePassphraseButton; - color: hifi.buttons.blue; - colorScheme: hifi.colorSchemes.dark; - anchors.top: noActivityText.bottom; - anchors.topMargin: 25; - anchors.horizontalCenter: parent.horizontalCenter; - width: 180; - height: 40; - text: "Apply Now"; - onClicked: { - Qt.openUrlExternally("https://www.highfidelity.com/"); - } - } } ListView { diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index b746b58015..fa72d02cca 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -324,12 +324,16 @@ Wallet::Wallet() { connect(ledger.data(), &Ledger::accountResult, this, [&]() { auto wallet = DependencyManager::get(); + auto ledger = DependencyManager::get(); auto walletScriptingInterface = DependencyManager::get(); uint status; - if (_mustRegenerateKeypair) { + if (_mustRegenerateKeypair || (!_passphrase->isEmpty() && _publicKeys.count() == 0)) { + qCDebug(commerce) << "Regenerating keys and resetting user_hfc_account. _mustRegenerateKeypair:" + << _mustRegenerateKeypair << "_publicKeys.count():" << _publicKeys.count(); _mustRegenerateKeypair = false; resetKeysOnly(); + ledger->reset(); generateKeyPair(); } From af1180255ead9d31ea88e9c23ee313f5fe339429 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 8 Nov 2017 11:45:40 -0800 Subject: [PATCH 148/183] fixes from code review --- .../render-utils/src/CauterizedMeshPartPayload.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp index 983832e9c8..3bb2aa2ef9 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp @@ -21,17 +21,7 @@ CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer model, int mes : ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform) {} void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices, const std::vector& cauterizedClusterMatrices) { - - // Once computed the cluster matrices, update the buffer(s) - if (clusterMatrices.size() > 1) { - if (!_clusterBuffer) { - _clusterBuffer = std::make_shared(clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) clusterMatrices.data()); - } else { - _clusterBuffer->setSubData(0, clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) clusterMatrices.data()); - } - } + ModelMeshPartPayload::updateClusterBuffer(clusterMatrices); if (cauterizedClusterMatrices.size() > 1) { if (!_cauterizedClusterBuffer) { From 6685b74c2a9e73a6e7a19e52e02842ee5cd50fd9 Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 8 Nov 2017 21:23:50 +0100 Subject: [PATCH 149/183] Remove checking of empty model url and add sanity for checking modelUrl field existing --- libraries/avatars/src/AvatarData.cpp | 8 +++++--- libraries/avatars/src/AvatarData.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 877bcd9353..bd313ac133 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2223,11 +2223,13 @@ glm::vec3 variantToVec3(const QVariant& var) { return result; } -void AttachmentData::fromVariant(const QVariant& variant) { +bool AttachmentData::fromVariant(const QVariant& variant) { + bool isValid = false; auto map = variant.toMap(); if (map.contains("modelUrl")) { auto urlString = map["modelUrl"].toString(); modelURL = urlString; + isValid = true; } if (map.contains("jointName")) { jointName = map["jointName"].toString(); @@ -2244,6 +2246,7 @@ void AttachmentData::fromVariant(const QVariant& variant) { if (map.contains("soft")) { isSoft = map["soft"].toBool(); } + return isValid; } QVariantList AvatarData::getAttachmentsVariant() const { @@ -2259,8 +2262,7 @@ void AvatarData::setAttachmentsVariant(const QVariantList& variant) { newAttachments.reserve(variant.size()); for (const auto& attachmentVar : variant) { AttachmentData attachment; - attachment.fromVariant(attachmentVar); - if (!attachment.modelURL.isEmpty()) { + if (attachment.fromVariant(attachmentVar)) { newAttachments.append(attachment); } } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 89fe270af1..fcfeaf7741 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -903,7 +903,7 @@ public: void fromJson(const QJsonObject& json); QVariant toVariant() const; - void fromVariant(const QVariant& variant); + bool fromVariant(const QVariant& variant); }; QDataStream& operator<<(QDataStream& out, const AttachmentData& attachment); From 3190fe1f325dd7851a605abc6df7d9fc88ad7745 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 8 Nov 2017 11:44:21 -0800 Subject: [PATCH 150/183] Use keyfilepath instead of cached public keys --- .../qml/hifi/commerce/wallet/WalletHome.qml | 4 ++ interface/src/commerce/Ledger.cpp | 4 +- interface/src/commerce/QmlCommerce.cpp | 5 +++ interface/src/commerce/QmlCommerce.h | 1 + interface/src/commerce/Wallet.cpp | 45 +++++++++++-------- 5 files changed, 39 insertions(+), 20 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index fd7ce0fdfd..44d3d54f58 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -43,6 +43,10 @@ Item { calculatePendingAndInvalidated(); } + + if (transactionHistoryModel.count === 0) { + commerce.setMustRegenerateKeypair(true); + } refreshTimer.start(); } } diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 01c11347fd..519c906fd8 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -94,7 +94,9 @@ void Ledger::receiveAtSuccess(QNetworkReply& reply) { QByteArray response = reply.readAll(); QJsonObject data = QJsonDocument::fromJson(response).object(); - if (data["status"] == "fail") { // Not on "The List" for receiving HFC + // ZRF FIXME! Change to something like `data["status"] == fail` + // Not on "The List" for receiving HFC + if (true) { wallet->setMustRegenerateKeypair(true); } } diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index f29e46d843..ebd2d9ae7c 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -57,6 +57,11 @@ void QmlCommerce::getWalletAuthenticatedStatus() { emit walletAuthenticatedStatusResult(wallet->walletIsAuthenticatedWithPassphrase()); } +void QmlCommerce::setMustRegenerateKeypair(const bool& val) { + auto wallet = DependencyManager::get(); + wallet->setMustRegenerateKeypair(val); +} + void QmlCommerce::getSecurityImage() { auto wallet = DependencyManager::get(); wallet->getSecurityImage(); diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index d4f4aa35d2..a4e2ab8f42 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -54,6 +54,7 @@ protected: Q_INVOKABLE void getKeyFilePathIfExists(); Q_INVOKABLE void getSecurityImage(); Q_INVOKABLE void getWalletAuthenticatedStatus(); + Q_INVOKABLE void setMustRegenerateKeypair(const bool& val); Q_INVOKABLE void chooseSecurityImage(const QString& imageFile); Q_INVOKABLE void setPassphrase(const QString& passphrase); diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index fa72d02cca..07861d0633 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -328,9 +328,9 @@ Wallet::Wallet() { auto walletScriptingInterface = DependencyManager::get(); uint status; - if (_mustRegenerateKeypair || (!_passphrase->isEmpty() && _publicKeys.count() == 0)) { + if (_mustRegenerateKeypair || getKeyFilePath() == "") { qCDebug(commerce) << "Regenerating keys and resetting user_hfc_account. _mustRegenerateKeypair:" - << _mustRegenerateKeypair << "_publicKeys.count():" << _publicKeys.count(); + << _mustRegenerateKeypair << "keyFilePath:" << getKeyFilePath(); _mustRegenerateKeypair = false; resetKeysOnly(); ledger->reset(); @@ -535,25 +535,32 @@ bool Wallet::generateKeyPair() { // FIXME: initialize OpenSSL elsewhere soon initialize(); - qCInfo(commerce) << "Generating keypair."; - auto keyPair = generateRSAKeypair(); - - writeBackupInstructions(); - - // TODO: redo this soon -- need error checking and so on - writeSecurityImage(_securityImage, keyFilePath()); + qCInfo(commerce) << "Generating keypair..."; + QPair keyPair = generateRSAKeypair(); QString oldKey = _publicKeys.count() == 0 ? "" : _publicKeys.last(); - QString key = keyPair.first->toBase64(); - _publicKeys.push_back(key); - qCDebug(commerce) << "public key:" << key; + if (keyPair.first) { + writeBackupInstructions(); - // It's arguable whether we want to change the receiveAt every time, but: - // 1. It's certainly needed the first time, when createIfNeeded answers true. - // 2. It is maximally private, and we can step back from that later if desired. - // 3. It maximally exercises all the machinery, so we are most likely to surface issues now. - auto ledger = DependencyManager::get(); - QString machineFingerprint = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); - return ledger->receiveAt(key, oldKey, machineFingerprint); + // TODO: redo this soon -- need error checking and so on + if (_securityImage) { + writeSecurityImage(_securityImage, keyFilePath()); + } + + QString key = keyPair.first->toBase64(); + _publicKeys.push_back(key); + qCDebug(commerce) << "public key:" << key; + + // It's arguable whether we want to change the receiveAt every time, but: + // 1. It's certainly needed the first time, when createIfNeeded answers true. + // 2. It is maximally private, and we can step back from that later if desired. + // 3. It maximally exercises all the machinery, so we are most likely to surface issues now. + auto ledger = DependencyManager::get(); + QString machineFingerprint = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); + return ledger->receiveAt(key, oldKey, machineFingerprint); + } else { + qCDebug(commerce) << "Failure generating keys!"; + return false; + } } QStringList Wallet::listPublicKeys() { From 7995f50fab0cc1cd945b3deb572567ea2cb74c45 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 8 Nov 2017 12:52:53 -0800 Subject: [PATCH 151/183] Fix seeding --- interface/src/commerce/Ledger.cpp | 2 +- interface/src/commerce/Wallet.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 519c906fd8..b344e00430 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -111,7 +111,7 @@ bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key, const QSt } QJsonObject transaction; - transaction["hfc_key"] = hfc_key; + transaction["public_key"] = hfc_key; transaction["machine_fingerprint"] = machine_fingerprint; QJsonDocument transactionDoc{ transaction }; auto transactionString = transactionDoc.toJson(QJsonDocument::Compact); diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 07861d0633..05c356cea9 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -333,8 +333,8 @@ Wallet::Wallet() { << _mustRegenerateKeypair << "keyFilePath:" << getKeyFilePath(); _mustRegenerateKeypair = false; resetKeysOnly(); - ledger->reset(); - generateKeyPair(); + ledger->reset(); // Hits `reset_user_hfc_account` endpoint + generateKeyPair(); // Hits `receive_at` endpoint } if (wallet->getKeyFilePath() == "" || !wallet->getSecurityImage()) { From 02625a6e28d63c0f6fb7f488eb3b1d310a3d8703 Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 8 Nov 2017 21:53:42 +0100 Subject: [PATCH 152/183] Remove script from engine --- scripts/developer/debugging/debugWindow.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/developer/debugging/debugWindow.js b/scripts/developer/debugging/debugWindow.js index 4390cf1f77..068efb351b 100644 --- a/scripts/developer/debugging/debugWindow.js +++ b/scripts/developer/debugging/debugWindow.js @@ -15,6 +15,7 @@ var scriptData = ScriptDiscoveryService.getRunning(); var scripts = scriptData.filter(function (datum) { return datum.name === 'debugWindow.js'; }); if (scripts.length >= 2) { //2nd instance of the script is too much + ScriptDiscoveryService.stopScript(scripts[1].url); return; } From 38fde43009e4221030b89285791f9e397d6f2548 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 8 Nov 2017 13:19:47 -0800 Subject: [PATCH 153/183] ...simplify your life --- .../qml/hifi/commerce/wallet/WalletHome.qml | 4 -- interface/src/commerce/Ledger.cpp | 13 +--- interface/src/commerce/QmlCommerce.cpp | 5 -- interface/src/commerce/QmlCommerce.h | 1 - interface/src/commerce/Wallet.cpp | 61 +++++++------------ interface/src/commerce/Wallet.h | 5 -- 6 files changed, 22 insertions(+), 67 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index 44d3d54f58..fd7ce0fdfd 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -43,10 +43,6 @@ Item { calculatePendingAndInvalidated(); } - - if (transactionHistoryModel.count === 0) { - commerce.setMustRegenerateKeypair(true); - } refreshTimer.start(); } } diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index b344e00430..49ae1bc18c 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -43,6 +43,7 @@ QJsonObject Ledger::failResponse(const QString& label, QNetworkReply& reply) { #define FailHandler(NAME) void Ledger::NAME##Failure(QNetworkReply& reply) { emit NAME##Result(failResponse(#NAME, reply)); } #define Handler(NAME) ApiHandler(NAME) FailHandler(NAME) Handler(buy) +Handler(receiveAt) Handler(balance) Handler(inventory) @@ -89,18 +90,6 @@ void Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, cons signedSend("transaction", transactionString, hfc_key, "buy", "buySuccess", "buyFailure", controlled_failure); } -void Ledger::receiveAtSuccess(QNetworkReply& reply) { - auto wallet = DependencyManager::get(); - QByteArray response = reply.readAll(); - QJsonObject data = QJsonDocument::fromJson(response).object(); - - // ZRF FIXME! Change to something like `data["status"] == fail` - // Not on "The List" for receiving HFC - if (true) { - wallet->setMustRegenerateKeypair(true); - } -} -void Ledger::receiveAtFailure(QNetworkReply& reply) { failResponse("receiveAt", reply); } bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key, const QString& machine_fingerprint) { auto accountManager = DependencyManager::get(); if (!accountManager->isLoggedIn()) { diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index ebd2d9ae7c..f29e46d843 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -57,11 +57,6 @@ void QmlCommerce::getWalletAuthenticatedStatus() { emit walletAuthenticatedStatusResult(wallet->walletIsAuthenticatedWithPassphrase()); } -void QmlCommerce::setMustRegenerateKeypair(const bool& val) { - auto wallet = DependencyManager::get(); - wallet->setMustRegenerateKeypair(val); -} - void QmlCommerce::getSecurityImage() { auto wallet = DependencyManager::get(); wallet->getSecurityImage(); diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index a4e2ab8f42..d4f4aa35d2 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -54,7 +54,6 @@ protected: Q_INVOKABLE void getKeyFilePathIfExists(); Q_INVOKABLE void getSecurityImage(); Q_INVOKABLE void getWalletAuthenticatedStatus(); - Q_INVOKABLE void setMustRegenerateKeypair(const bool& val); Q_INVOKABLE void chooseSecurityImage(const QString& imageFile); Q_INVOKABLE void setPassphrase(const QString& passphrase); diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 05c356cea9..9bc8dc9e43 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -324,19 +324,9 @@ Wallet::Wallet() { connect(ledger.data(), &Ledger::accountResult, this, [&]() { auto wallet = DependencyManager::get(); - auto ledger = DependencyManager::get(); auto walletScriptingInterface = DependencyManager::get(); uint status; - if (_mustRegenerateKeypair || getKeyFilePath() == "") { - qCDebug(commerce) << "Regenerating keys and resetting user_hfc_account. _mustRegenerateKeypair:" - << _mustRegenerateKeypair << "keyFilePath:" << getKeyFilePath(); - _mustRegenerateKeypair = false; - resetKeysOnly(); - ledger->reset(); // Hits `reset_user_hfc_account` endpoint - generateKeyPair(); // Hits `receive_at` endpoint - } - if (wallet->getKeyFilePath() == "" || !wallet->getSecurityImage()) { status = (uint)WalletStatus::WALLET_STATUS_NOT_SET_UP; } else if (!wallet->walletIsAuthenticatedWithPassphrase()) { @@ -535,32 +525,25 @@ bool Wallet::generateKeyPair() { // FIXME: initialize OpenSSL elsewhere soon initialize(); - qCInfo(commerce) << "Generating keypair..."; - QPair keyPair = generateRSAKeypair(); + qCInfo(commerce) << "Generating keypair."; + auto keyPair = generateRSAKeypair(); + + writeBackupInstructions(); + + // TODO: redo this soon -- need error checking and so on + writeSecurityImage(_securityImage, keyFilePath()); QString oldKey = _publicKeys.count() == 0 ? "" : _publicKeys.last(); - if (keyPair.first) { - writeBackupInstructions(); + QString key = keyPair.first->toBase64(); + _publicKeys.push_back(key); + qCDebug(commerce) << "public key:" << key; - // TODO: redo this soon -- need error checking and so on - if (_securityImage) { - writeSecurityImage(_securityImage, keyFilePath()); - } - - QString key = keyPair.first->toBase64(); - _publicKeys.push_back(key); - qCDebug(commerce) << "public key:" << key; - - // It's arguable whether we want to change the receiveAt every time, but: - // 1. It's certainly needed the first time, when createIfNeeded answers true. - // 2. It is maximally private, and we can step back from that later if desired. - // 3. It maximally exercises all the machinery, so we are most likely to surface issues now. - auto ledger = DependencyManager::get(); - QString machineFingerprint = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); - return ledger->receiveAt(key, oldKey, machineFingerprint); - } else { - qCDebug(commerce) << "Failure generating keys!"; - return false; - } + // It's arguable whether we want to change the receiveAt every time, but: + // 1. It's certainly needed the first time, when createIfNeeded answers true. + // 2. It is maximally private, and we can step back from that later if desired. + // 3. It maximally exercises all the machinery, so we are most likely to surface issues now. + auto ledger = DependencyManager::get(); + QString machineFingerprint = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); + return ledger->receiveAt(key, oldKey, machineFingerprint); } QStringList Wallet::listPublicKeys() { @@ -678,13 +661,9 @@ QString Wallet::getKeyFilePath() { } } -void Wallet::resetKeysOnly() { +void Wallet::reset() { _publicKeys.clear(); - QFile keyFile(keyFilePath()); - keyFile.remove(); -} -void Wallet::reset() { delete _securityImage; _securityImage = nullptr; @@ -692,7 +671,9 @@ void Wallet::reset() { updateImageProvider(); _passphrase->clear(); - resetKeysOnly(); + + QFile keyFile(keyFilePath()); + keyFile.remove(); } bool Wallet::writeWallet(const QString& newPassphrase) { RSA* keys = readKeys(keyFilePath().toStdString().c_str()); diff --git a/interface/src/commerce/Wallet.h b/interface/src/commerce/Wallet.h index f0f13aaf6e..ed145df451 100644 --- a/interface/src/commerce/Wallet.h +++ b/interface/src/commerce/Wallet.h @@ -49,7 +49,6 @@ public: bool walletIsAuthenticatedWithPassphrase(); bool changePassphrase(const QString& newPassphrase); - void resetKeysOnly(); void reset(); void getWalletStatus(); @@ -60,8 +59,6 @@ public: WALLET_STATUS_READY }; - void setMustRegenerateKeypair(const bool& val) { _mustRegenerateKeypair = val; } - signals: void securityImageResult(bool exists); void keyFilePathIfExistsResult(const QString& path); @@ -86,8 +83,6 @@ private: bool writeBackupInstructions(); void account(); - - bool _mustRegenerateKeypair { false }; }; #endif // hifi_Wallet_h From 45e58b93e5f7931015bf053316e68b5e6388b4e3 Mon Sep 17 00:00:00 2001 From: MissLiviRose Date: Wed, 8 Nov 2017 14:23:49 -0800 Subject: [PATCH 154/183] add skeleton scale change signal so scripts can detect scaling change --- interface/src/avatar/MyAvatar.cpp | 1 + interface/src/avatar/MyAvatar.h | 1 + 2 files changed, 2 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0fceba82f0..76205bdde9 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2189,6 +2189,7 @@ void MyAvatar::clampScaleChangeToDomainLimits(float desiredScale) { setTargetScale(clampedTargetScale); qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); + emit(scaleChanged()); } float MyAvatar::getDomainMinScale() { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 303a395a47..288e6dd638 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -620,6 +620,7 @@ signals: void dominantHandChanged(const QString& hand); void sensorToWorldScaleChanged(float sensorToWorldScale); void attachmentsChanged(); + void scaleChanged(); private: From 796388dfb47d70080c1e0f59a35b939dc4e951a6 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 8 Nov 2017 14:50:15 -0800 Subject: [PATCH 155/183] reverted a line to match current master --- libraries/ui/src/OffscreenUi.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 96272c4f1f..297ed9ca50 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -720,8 +720,7 @@ QString OffscreenUi::fileDialog(const QVariantMap& properties) { return QString(); } qCDebug(uiLogging) << result.toString(); - // originally was result.toUrl().toLocalFile();, but toLocalFile() is not working - return result.toString(); + return result.toUrl().toLocalFile(); } ModalDialogListener* OffscreenUi::fileDialogAsync(const QVariantMap& properties) { From 33b6a13a4d67a1d9b09c0746a9d2f9c0000f16d2 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 8 Nov 2017 15:21:36 -0800 Subject: [PATCH 156/183] Revert 11728 and fix marketplace JS injection - should revisit --- scripts/system/html/js/marketplacesInject.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index dc0c610ace..4b127baef8 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -89,7 +89,7 @@ window.location = "https://clara.io/library?gameCheck=true&public=true"; }); $('#exploreHifiMarketplace').on('click', function () { - window.location = metaverseServerURL + "/marketplace"; + window.location = "http://www.highfidelity.com/marketplace"; }); } @@ -612,9 +612,9 @@ var HIFI_ITEM_PAGE = 3; var pageType = DIRECTORY; - if (location.href.indexOf(metaverseServerURL + "/") !== -1) { pageType = HIFI; } + if (location.href.indexOf("highfidelity.com/") !== -1) { pageType = HIFI; } if (location.href.indexOf("clara.io/") !== -1) { pageType = CLARA; } - if (location.href.indexOf(metaverseServerURL + "/marketplace/items/") !== -1) { pageType = HIFI_ITEM_PAGE; } + if (location.href.indexOf("highfidelity.com/marketplace/items/") !== -1) { pageType = HIFI_ITEM_PAGE; } injectCommonCode(pageType === DIRECTORY); switch (pageType) { From 45b9a150dca0954fccb817a6c3f0582ae95c2dc5 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 8 Nov 2017 15:21:48 -0800 Subject: [PATCH 157/183] updated blocks url refs in application to fix download issue --- interface/src/Application.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4f051697ad..b21588958e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2693,7 +2693,7 @@ bool Application::importFromZIP(const QString& filePath) { qDebug() << "A zip file has been dropped in: " << filePath; QUrl empty; // handle Blocks download from Marketplace - if (filePath.contains("vr.google.com/downloads")) { + if (filePath.contains("poly.google.com/downloads")) { addAssetToWorldFromURL(filePath); } else { qApp->getFileDownloadInterface()->runUnzip(filePath, empty, true, true, false); @@ -6235,7 +6235,7 @@ void Application::addAssetToWorldFromURL(QString url) { if (url.contains("filename")) { filename = url.section("filename=", 1, 1); // Filename is in "?filename=" parameter at end of URL. } - if (url.contains("vr.google.com/downloads")) { + if (url.contains("poly.google.com/downloads")) { filename = url.section('/', -1); if (url.contains("noDownload")) { filename.remove(".zip?noDownload=false"); @@ -6270,7 +6270,7 @@ void Application::addAssetToWorldFromURLRequestFinished() { if (url.contains("filename")) { filename = url.section("filename=", 1, 1); // Filename is in "?filename=" parameter at end of URL. } - if (url.contains("vr.google.com/downloads")) { + if (url.contains("poly.google.com/downloads")) { filename = url.section('/', -1); if (url.contains("noDownload")) { filename.remove(".zip?noDownload=false"); From dac2ae19a427fc64450c129cd7481d145102d463 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Wed, 8 Nov 2017 12:24:16 -0500 Subject: [PATCH 158/183] [Case 6569] Add protection for dynamic vs static collision type (details below). When creating a model, it was possible to elect Exact collision with the dynamic property even though this combination is prohibited. This combination would silently fail rather than notifying the user of the error. This commit implements safeguards against the invalid combination: * If the user elects the Exact collision type and the dynamic field is unchecked, then dynamic field is disabled. * If the user elects a different collision type and the dynamic filed is unchecked, then the dynamic field is enabled. * If the user has checked the dynamic field and subsequently elects the Exact collision type, then the selection is void and the previous collision selection is retained; however, an error dialog is presented informing the user of the error. Changes Committed: modified: interface/resources/qml/hifi/tablet/NewModelDialog.qml --- .../qml/hifi/tablet/NewModelDialog.qml | 49 ++++++++++++++++--- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/NewModelDialog.qml b/interface/resources/qml/hifi/tablet/NewModelDialog.qml index 47d28486a9..e6459fe7bb 100644 --- a/interface/resources/qml/hifi/tablet/NewModelDialog.qml +++ b/interface/resources/qml/hifi/tablet/NewModelDialog.qml @@ -11,8 +11,11 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 +import QtQuick.Dialogs 1.2 as OriginalDialogs + import "../../styles-uit" import "../../controls-uit" +import "../dialogs" Rectangle { id: newModelDialog @@ -25,6 +28,15 @@ Rectangle { property bool punctuationMode: false property bool keyboardRasied: false + function errorMessageBox(message) { + return desktop.messageBox({ + icon: hifi.icons.warning, + defaultButton: OriginalDialogs.StandardButton.Ok, + title: "Error", + text: message + }); + } + Item { id: column1 anchors.rightMargin: 10 @@ -98,7 +110,6 @@ Rectangle { CheckBox { id: dynamic text: qsTr("Dynamic") - } Row { @@ -139,15 +150,39 @@ Rectangle { ComboBox { id: collisionType + + property int priorIndex: 0 + property string staticMeshCollisionText: "Exact - All polygons" + property var collisionArray: ["No Collision", + "Basic - Whole model", + "Good - Sub-meshes", + staticMeshCollisionText, + "Box", + "Sphere"] + width: 200 z: 100 transformOrigin: Item.Center - model: ["No Collision", - "Basic - Whole model", - "Good - Sub-meshes", - "Exact - All polygons", - "Box", - "Sphere"] + model: collisionArray + + onCurrentIndexChanged: { + if (collisionArray[currentIndex] === staticMeshCollisionText) { + + if (dynamic.checked) { + currentIndex = priorIndex; + + errorMessageBox("Models with Automatic Collisions set to \"" + staticMeshCollisionText + "\" cannot be dynamic."); + //--EARLY EXIT--( Can't have a static mesh model that's dynamic ) + return; + } + + dynamic.enabled = false; + } else { + dynamic.enabled = true; + } + + priorIndex = currentIndex; + } } Row { From a057cb914f65c37b3ac7b4a823488c9068ae8e1c Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Wed, 8 Nov 2017 14:18:04 -0500 Subject: [PATCH 159/183] [Case 6569] Fixes clipping of cancel button by window edge. Changes Committed: modified: interface/resources/qml/hifi/tablet/NewModelDialog.qml --- interface/resources/qml/hifi/tablet/NewModelDialog.qml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/NewModelDialog.qml b/interface/resources/qml/hifi/tablet/NewModelDialog.qml index e6459fe7bb..da77464325 100644 --- a/interface/resources/qml/hifi/tablet/NewModelDialog.qml +++ b/interface/resources/qml/hifi/tablet/NewModelDialog.qml @@ -128,6 +128,7 @@ Rectangle { Text { id: text2 width: 160 + x: dynamic.width / 2 color: "#ffffff" text: qsTr("Models with automatic collisions set to 'Exact' cannot be dynamic, and should not be used as floors") wrapMode: Text.WordWrap @@ -190,10 +191,10 @@ Rectangle { width: 200 height: 400 spacing: 5 - - anchors { - rightMargin: 15 - } + + anchors.horizontalCenter: column3.horizontalCenter + anchors.horizontalCenterOffset: -20 + Button { id: button1 text: qsTr("Add") From 0e90c92cf5038c732cc2449fd39a4b840da9eee6 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Wed, 8 Nov 2017 18:35:12 -0500 Subject: [PATCH 160/183] [Case 6569] Minor: Break up line to pass column count guidelines. Changes Committed: modified: interface/resources/qml/hifi/tablet/NewModelDialog.qml --- interface/resources/qml/hifi/tablet/NewModelDialog.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/NewModelDialog.qml b/interface/resources/qml/hifi/tablet/NewModelDialog.qml index da77464325..3debc8b9e7 100644 --- a/interface/resources/qml/hifi/tablet/NewModelDialog.qml +++ b/interface/resources/qml/hifi/tablet/NewModelDialog.qml @@ -172,7 +172,8 @@ Rectangle { if (dynamic.checked) { currentIndex = priorIndex; - errorMessageBox("Models with Automatic Collisions set to \"" + staticMeshCollisionText + "\" cannot be dynamic."); + errorMessageBox("Models with Automatic Collisions set to \"" + + staticMeshCollisionText + "\" cannot be dynamic."); //--EARLY EXIT--( Can't have a static mesh model that's dynamic ) return; } From c1b5d009934ba5f8529807abd4bf2d5e96b58547 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 8 Nov 2017 15:41:24 -0800 Subject: [PATCH 161/183] Converted 'Background Blend' control to a slider. --- scripts/system/html/entityProperties.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 7fdeee67d3..0b96b59ddb 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -587,8 +587,8 @@

- - + +
From 5c7ebc0af3151e3fe93117f39565fc30751b0b89 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 8 Nov 2017 16:44:05 -0800 Subject: [PATCH 162/183] Converted 'Glare Angle' control to a slider. --- scripts/system/html/entityProperties.html | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 0b96b59ddb..dba6b7e792 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -587,8 +587,11 @@

- - + + + + +
@@ -612,8 +615,11 @@

- - + + + +
+
From 7cb9514feb96eb5440f42001009f17a040cd58f3 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 8 Nov 2017 16:50:44 -0800 Subject: [PATCH 163/183] Converted 'Glare Angle' control to a slider. --- scripts/system/html/entityProperties.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index dba6b7e792..9453b476ee 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -557,8 +557,8 @@
- < - /div> + +
From 19b7c6e025113eceeb40d2b1fbb1ce39543a011e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 8 Nov 2017 17:14:14 -0800 Subject: [PATCH 164/183] Remove machine fingerprint from receiveAt --- interface/src/commerce/Ledger.cpp | 10 ++-------- interface/src/commerce/Ledger.h | 2 +- interface/src/commerce/Wallet.cpp | 4 +--- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 49ae1bc18c..904847cb5f 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -90,7 +90,7 @@ void Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, cons signedSend("transaction", transactionString, hfc_key, "buy", "buySuccess", "buyFailure", controlled_failure); } -bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key, const QString& machine_fingerprint) { +bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key) { auto accountManager = DependencyManager::get(); if (!accountManager->isLoggedIn()) { qCWarning(commerce) << "Cannot set receiveAt when not logged in."; @@ -99,13 +99,7 @@ bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key, const QSt return false; // We know right away that we will fail, so tell the caller. } - QJsonObject transaction; - transaction["public_key"] = hfc_key; - transaction["machine_fingerprint"] = machine_fingerprint; - QJsonDocument transactionDoc{ transaction }; - auto transactionString = transactionDoc.toJson(QJsonDocument::Compact); - - signedSend("transaction", transactionString, old_key, "receive_at", "receiveAtSuccess", "receiveAtFailure"); + signedSend("public_key", hfc_key.toUtf8(), old_key, "receive_at", "receiveAtSuccess", "receiveAtFailure"); return true; // Note that there may still be an asynchronous signal of failure that callers might be interested in. } diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 54f3f780f3..42eb0ffc49 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -26,7 +26,7 @@ class Ledger : public QObject, public Dependency { public: void buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const bool controlled_failure = false); - bool receiveAt(const QString& hfc_key, const QString& old_key, const QString& machine_fingerprint); + bool receiveAt(const QString& hfc_key, const QString& old_key); void balance(const QStringList& keys); void inventory(const QStringList& keys); void history(const QStringList& keys); diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 9bc8dc9e43..85632ff8f1 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -16,7 +16,6 @@ #include "ui/ImageProvider.h" #include "scripting/HMDScriptingInterface.h" -#include #include #include #include @@ -542,8 +541,7 @@ bool Wallet::generateKeyPair() { // 2. It is maximally private, and we can step back from that later if desired. // 3. It maximally exercises all the machinery, so we are most likely to surface issues now. auto ledger = DependencyManager::get(); - QString machineFingerprint = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); - return ledger->receiveAt(key, oldKey, machineFingerprint); + return ledger->receiveAt(key, oldKey); } QStringList Wallet::listPublicKeys() { From 6d019b43029d579ea1f01502f13b9b743492a5dd Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 8 Nov 2017 18:16:42 -0800 Subject: [PATCH 165/183] Update the audio codecs --- cmake/externals/hifiAudioCodec/CMakeLists.txt | 76 +++++++++---------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/cmake/externals/hifiAudioCodec/CMakeLists.txt b/cmake/externals/hifiAudioCodec/CMakeLists.txt index a30396c6fd..808a6174ca 100644 --- a/cmake/externals/hifiAudioCodec/CMakeLists.txt +++ b/cmake/externals/hifiAudioCodec/CMakeLists.txt @@ -5,43 +5,41 @@ set(EXTERNAL_NAME hifiAudioCodec) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -if (NOT ANDROID) - - if (WIN32 OR APPLE) - ExternalProject_Add( - ${EXTERNAL_NAME} - URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-1.zip - URL_MD5 23ec3fe51eaa155ea159a4971856fc13 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - LOG_DOWNLOAD 1 - ) - else () - ExternalProject_Add( - ${EXTERNAL_NAME} - URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-linux.zip - URL_MD5 7d37914a18aa4de971d2f45dd3043bde - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - LOG_DOWNLOAD 1 - ) - endif() - - # Hide this external target (for ide users) - set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") - - ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) - - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL) - - if (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/audio.lib CACHE TYPE INTERNAL) - elseif(APPLE) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL) - elseif(NOT ANDROID) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL) - endif() - +if (WIN32) + set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-win-2.0.zip) + set(DOWNLOAD_MD5 9199d4dbd6b16bed736b235efe980e67) +elseif (APPLE) + set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-mac-2.0.zip) + set(DOWNLOAD_MD5 21649881e7d5dc94f922179be96f76ba) +elseif (UNIX) + set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-linux-2.0.zip) + set(DOWNLOAD_MD5 988194f22f8d064c53d548259f426dce) +elseif (ANDROID) + set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-android-2.0.zip) + set(DOWNLOAD_MD5 aef2a852600d498d58aa586668191683) +else() + return() +endif() + +ExternalProject_Add( + ${EXTERNAL_NAME} + URL ${DOWNLOAD_URL} + URL_MD5 ${DOWNLOAD_MD5} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 +) + +# Hide this external target (for ide users) +set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") + +ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL) + +if (WIN32) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/audio.lib CACHE TYPE INTERNAL) +else() + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL) endif() From 4f7ed38e98e2c49a3764a608dabaee7cbb8bfaaa Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 9 Nov 2017 11:26:08 +0100 Subject: [PATCH 166/183] Fixed potential link errors on Mac --- libraries/render-utils/src/BackgroundStage.cpp | 1 + libraries/render-utils/src/BackgroundStage.h | 2 +- libraries/render-utils/src/HazeStage.cpp | 1 + libraries/render-utils/src/HazeStage.h | 2 +- libraries/render-utils/src/LightStage.cpp | 1 + libraries/render-utils/src/LightStage.h | 2 +- libraries/render/src/render/HighlightStage.cpp | 1 + libraries/render/src/render/HighlightStage.h | 2 +- libraries/render/src/render/TransitionStage.cpp | 1 + libraries/render/src/render/TransitionStage.h | 2 +- 10 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/BackgroundStage.cpp b/libraries/render-utils/src/BackgroundStage.cpp index 2ea3683c4a..2d2c0ed150 100644 --- a/libraries/render-utils/src/BackgroundStage.cpp +++ b/libraries/render-utils/src/BackgroundStage.cpp @@ -14,6 +14,7 @@ #include std::string BackgroundStage::_stageName { "BACKGROUND_STAGE"}; +const BackgroundStage::Index BackgroundStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX }; BackgroundStage::Index BackgroundStage::findBackground(const BackgroundPointer& background) const { auto found = _backgroundMap.find(background); diff --git a/libraries/render-utils/src/BackgroundStage.h b/libraries/render-utils/src/BackgroundStage.h index eab7c94f0d..4e0e09db5b 100644 --- a/libraries/render-utils/src/BackgroundStage.h +++ b/libraries/render-utils/src/BackgroundStage.h @@ -27,7 +27,7 @@ public: static const std::string& getName() { return _stageName; } using Index = render::indexed_container::Index; - static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX }; + static const Index INVALID_INDEX; static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } using BackgroundPointer = model::SunSkyStagePointer; diff --git a/libraries/render-utils/src/HazeStage.cpp b/libraries/render-utils/src/HazeStage.cpp index 7a12ee3c8a..016282d16f 100644 --- a/libraries/render-utils/src/HazeStage.cpp +++ b/libraries/render-utils/src/HazeStage.cpp @@ -14,6 +14,7 @@ #include std::string HazeStage::_stageName { "HAZE_STAGE"}; +const HazeStage::Index HazeStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX }; FetchHazeStage::FetchHazeStage() { _haze = std::make_shared(); diff --git a/libraries/render-utils/src/HazeStage.h b/libraries/render-utils/src/HazeStage.h index 102f299d8f..c355f06644 100644 --- a/libraries/render-utils/src/HazeStage.h +++ b/libraries/render-utils/src/HazeStage.h @@ -28,7 +28,7 @@ public: static const std::string& getName() { return _stageName; } using Index = render::indexed_container::Index; - static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX }; + static const Index INVALID_INDEX; static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } using HazePointer = model::HazePointer; diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 079c63f367..c280abfeaf 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -14,6 +14,7 @@ #include "LightStage.h" std::string LightStage::_stageName { "LIGHT_STAGE"}; +const LightStage::Index LightStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX }; LightStage::LightStage() { } diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 66d73c9a6e..c26f504658 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -32,7 +32,7 @@ public: static const std::string& getName() { return _stageName; } using Index = render::indexed_container::Index; - static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX }; + static const Index INVALID_INDEX; static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } using LightPointer = model::LightPointer; diff --git a/libraries/render/src/render/HighlightStage.cpp b/libraries/render/src/render/HighlightStage.cpp index 6821504649..ade3844321 100644 --- a/libraries/render/src/render/HighlightStage.cpp +++ b/libraries/render/src/render/HighlightStage.cpp @@ -3,6 +3,7 @@ using namespace render; std::string HighlightStage::_name("Highlight"); +const HighlightStage::Index HighlightStage::INVALID_INDEX{ render::indexed_container::INVALID_INDEX }; HighlightStage::Index HighlightStage::addHighlight(const std::string& selectionName, const HighlightStyle& style) { Highlight outline{ selectionName, style }; diff --git a/libraries/render/src/render/HighlightStage.h b/libraries/render/src/render/HighlightStage.h index 7600f1f724..b35fff654c 100644 --- a/libraries/render/src/render/HighlightStage.h +++ b/libraries/render/src/render/HighlightStage.h @@ -35,7 +35,7 @@ namespace render { static const std::string& getName() { return _name; } using Index = render::indexed_container::Index; - static const Index INVALID_INDEX{ render::indexed_container::INVALID_INDEX }; + static const Index INVALID_INDEX; using HighlightIdList = render::indexed_container::Indices; static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } diff --git a/libraries/render/src/render/TransitionStage.cpp b/libraries/render/src/render/TransitionStage.cpp index 33ef829c64..9ddc72f4db 100644 --- a/libraries/render/src/render/TransitionStage.cpp +++ b/libraries/render/src/render/TransitionStage.cpp @@ -5,6 +5,7 @@ using namespace render; std::string TransitionStage::_name("Transition"); +const TransitionStage::Index TransitionStage::INVALID_INDEX{ indexed_container::INVALID_INDEX }; TransitionStage::Index TransitionStage::addTransition(ItemID itemId, Transition::Type type, ItemID boundId) { Transition transition; diff --git a/libraries/render/src/render/TransitionStage.h b/libraries/render/src/render/TransitionStage.h index 226d531d8b..1d10a5dedb 100644 --- a/libraries/render/src/render/TransitionStage.h +++ b/libraries/render/src/render/TransitionStage.h @@ -25,7 +25,7 @@ namespace render { static const std::string& getName() { return _name; } using Index = indexed_container::Index; - static const Index INVALID_INDEX{ indexed_container::INVALID_INDEX }; + static const Index INVALID_INDEX; using TransitionIdList = indexed_container::Indices; static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } From 5507bcea3c0e1e90bfc1abf9b2c9251ce42b3568 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 9 Nov 2017 10:34:01 -0800 Subject: [PATCH 167/183] Remove hack for missing inttypes.h header on VS2010 --- libraries/avatars/src/AvatarData.h | 14 -------------- libraries/octree/src/OctreeQuery.h | 14 -------------- 2 files changed, 28 deletions(-) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 89fe270af1..d8169bb8f7 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -15,21 +15,7 @@ #include #include #include - -/* VS2010 defines stdint.h, but not inttypes.h */ -#if defined(_MSC_VER) -typedef signed char int8_t; -typedef signed short int16_t; -typedef signed int int32_t; -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef signed long long int64_t; -typedef unsigned long long quint64; -#define PRId64 "I64d" -#else #include -#endif #include #include diff --git a/libraries/octree/src/OctreeQuery.h b/libraries/octree/src/OctreeQuery.h index 81a63a696c..fc9ea525e6 100644 --- a/libraries/octree/src/OctreeQuery.h +++ b/libraries/octree/src/OctreeQuery.h @@ -12,21 +12,7 @@ #ifndef hifi_OctreeQuery_h #define hifi_OctreeQuery_h -/* VS2010 defines stdint.h, but not inttypes.h */ -#if defined(_MSC_VER) -typedef signed char int8_t; -typedef signed short int16_t; -typedef signed int int32_t; -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef signed long long int64_t; -typedef unsigned long long quint64; -#define PRId64 "I64d" -#else #include -#endif - #include #include From 9a1386bf0d9c1ee157f6b4ec199eb2c9c3479b87 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 9 Nov 2017 10:34:52 -0800 Subject: [PATCH 168/183] Fix build errors on Linux --- cmake/externals/hifiAudioCodec/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/hifiAudioCodec/CMakeLists.txt b/cmake/externals/hifiAudioCodec/CMakeLists.txt index 808a6174ca..298f666304 100644 --- a/cmake/externals/hifiAudioCodec/CMakeLists.txt +++ b/cmake/externals/hifiAudioCodec/CMakeLists.txt @@ -13,7 +13,7 @@ elseif (APPLE) set(DOWNLOAD_MD5 21649881e7d5dc94f922179be96f76ba) elseif (UNIX) set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-linux-2.0.zip) - set(DOWNLOAD_MD5 988194f22f8d064c53d548259f426dce) + set(DOWNLOAD_MD5 67fb7755f9bcafb98a9fceea53bc7481) elseif (ANDROID) set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-android-2.0.zip) set(DOWNLOAD_MD5 aef2a852600d498d58aa586668191683) From 9724a5e5b83d98e591e24b2f23110b025657a6ae Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 9 Nov 2017 10:53:36 -0800 Subject: [PATCH 169/183] Fix for address sanitizer warning This fixes a potential null pointer dereference. --- libraries/animation/src/Rig.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index acf7bf81d8..3dad4e3fb6 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -303,7 +303,9 @@ void Rig::setModelOffset(const glm::mat4& modelOffsetMat) { _rigToGeometryTransform = glm::inverse(_geometryToRigTransform); // rebuild cached default poses - buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses); + if (_animSkeleton) { + buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses); + } } } From 10f484c668263fa15855e220448680c68e816942 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 9 Nov 2017 12:21:23 -0700 Subject: [PATCH 170/183] 6944 Avatar scale is saved across domains --- interface/src/avatar/MyAvatar.cpp | 14 +++++++++++++- interface/src/avatar/MyAvatar.h | 4 ++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 76205bdde9..0dfcf93a65 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -135,7 +135,7 @@ MyAvatar::MyAvatar(QThread* thread) : connect(&domainHandler, &DomainHandler::settingsReceived, this, &MyAvatar::restrictScaleFromDomainSettings); // when we leave a domain we lift whatever restrictions that domain may have placed on our scale - connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &MyAvatar::clearScaleRestriction); + connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &MyAvatar::leaveDomain); _bodySensorMatrix = deriveBodyFromHMDSensor(); @@ -2279,6 +2279,18 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings settings.endGroup(); } +void MyAvatar::leaveDomain() { + clearScaleRestriction(); + saveAvatarScale(); +} + +void MyAvatar::saveAvatarScale() { + Settings settings; + settings.beginGroup("Avatar"); + settings.setValue("scale", _targetScale); + settings.endGroup(); +} + void MyAvatar::clearScaleRestriction() { _domainMinimumScale = MIN_AVATAR_SCALE; _domainMaximumScale = MAX_AVATAR_SCALE; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 288e6dd638..9133b967fa 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -561,6 +561,8 @@ public slots: float getDomainMinScale(); float getDomainMaxScale(); + void leaveDomain(); + void setGravity(float gravity); float getGravity(); @@ -638,6 +640,8 @@ private: virtual int parseDataFromBuffer(const QByteArray& buffer) override; virtual glm::vec3 getSkeletonPosition() const override; + void saveAvatarScale(); + glm::vec3 getScriptedMotorVelocity() const { return _scriptedMotorVelocity; } float getScriptedMotorTimescale() const { return _scriptedMotorTimescale; } QString getScriptedMotorFrame() const; From 224386317d41549df7001080bc98dbfd72f9555d Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 9 Nov 2017 11:29:48 -0800 Subject: [PATCH 171/183] send overlay visibility through transaction --- interface/src/ui/overlays/Base3DOverlay.cpp | 9 +++++++- interface/src/ui/overlays/Base3DOverlay.h | 2 ++ interface/src/ui/overlays/Circle3DOverlay.cpp | 4 ++-- interface/src/ui/overlays/Cube3DOverlay.cpp | 2 +- interface/src/ui/overlays/Grid3DOverlay.cpp | 2 +- interface/src/ui/overlays/Image3DOverlay.cpp | 2 +- interface/src/ui/overlays/Line3DOverlay.cpp | 2 +- .../src/ui/overlays/Rectangle3DOverlay.cpp | 23 ++++--------------- .../src/ui/overlays/Rectangle3DOverlay.h | 3 --- interface/src/ui/overlays/Shape3DOverlay.cpp | 2 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- interface/src/ui/overlays/Text3DOverlay.cpp | 2 +- interface/src/ui/overlays/Web3DOverlay.cpp | 2 +- 13 files changed, 24 insertions(+), 33 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 42425932df..794c6e39ed 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -280,13 +280,16 @@ void Base3DOverlay::update(float duration) { if (render::Item::isValidID(itemID)) { // Capture the render transform value in game loop before auto latestTransform = evalRenderTransform(); + bool latestVisible = getVisible(); _renderTransformDirty = false; render::ScenePointer scene = qApp->getMain3DScene(); render::Transaction transaction; - transaction.updateItem(itemID, [latestTransform](Overlay& data) { + transaction.updateItem(itemID, [latestTransform, latestVisible](Overlay& data) { auto overlay3D = dynamic_cast(&data); if (overlay3D) { + // TODO: overlays need to communicate all relavent render properties through transactions overlay3D->setRenderTransform(latestTransform); + overlay3D->setRenderVisible(latestVisible); } }); scene->enqueueTransaction(transaction); @@ -306,6 +309,10 @@ void Base3DOverlay::setRenderTransform(const Transform& transform) { _renderTransform = transform; } +void Base3DOverlay::setRenderVisible(bool visible) { + _renderVisible = visible; +} + SpatialParentTree* Base3DOverlay::getParentTree() const { auto entityTreeRenderer = qApp->getEntities(); EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 436cfbf97b..891edfce67 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -76,8 +76,10 @@ protected: virtual void parentDeleted() override; mutable Transform _renderTransform; + mutable bool _renderVisible; virtual Transform evalRenderTransform(); virtual void setRenderTransform(const Transform& transform); + void setRenderVisible(bool visible); const Transform& getRenderTransform() const { return _renderTransform; } float _lineWidth; diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 536b2c764f..69ce331c99 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -59,7 +59,7 @@ Circle3DOverlay::~Circle3DOverlay() { } } void Circle3DOverlay::render(RenderArgs* args) { - if (!_visible) { + if (!_renderVisible) { return; // do nothing if we're not visible } @@ -259,7 +259,7 @@ void Circle3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Circle3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit(); + auto builder = render::ShapeKey::Builder().withoutCullFace(); if (isTransparent()) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index b6df1dbc31..caa9a1b397 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -44,7 +44,7 @@ Cube3DOverlay::~Cube3DOverlay() { } void Cube3DOverlay::render(RenderArgs* args) { - if (!_visible) { + if (!_renderVisible) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index ca275368cb..6fd132b531 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -53,7 +53,7 @@ AABox Grid3DOverlay::getBounds() const { } void Grid3DOverlay::render(RenderArgs* args) { - if (!_visible) { + if (!_renderVisible) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 313d71fc40..a8ae293c83 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -60,7 +60,7 @@ void Image3DOverlay::update(float deltatime) { } void Image3DOverlay::render(RenderArgs* args) { - if (!_visible || !getParentVisible() || !_texture || !_texture->isLoaded()) { + if (!_renderVisible || !getParentVisible() || !_texture || !_texture->isLoaded()) { return; } diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index bdb35d4f49..82920827e1 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -123,7 +123,7 @@ AABox Line3DOverlay::getBounds() const { } void Line3DOverlay::render(RenderArgs* args) { - if (!_visible) { + if (!_renderVisible) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index 47d47b76a5..f2e324206d 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -23,7 +23,6 @@ Rectangle3DOverlay::Rectangle3DOverlay() : for (size_t i = 0; i < _rectGeometryIds.size(); ++i) { _rectGeometryIds[i] = geometryCache->allocateID(); } - qDebug() << "Building rect3d overlay"; } Rectangle3DOverlay::Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay) : @@ -34,11 +33,9 @@ Rectangle3DOverlay::Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOver for (size_t i = 0; i < _rectGeometryIds.size(); ++i) { _rectGeometryIds[i] = geometryCache->allocateID(); } - qDebug() << "Building rect3d overlay"; } Rectangle3DOverlay::~Rectangle3DOverlay() { - qDebug() << "Destryoing rect3d overlay"; auto geometryCache = DependencyManager::get(); if (geometryCache) { geometryCache->releaseID(_geometryCacheID); @@ -49,7 +46,7 @@ Rectangle3DOverlay::~Rectangle3DOverlay() { } void Rectangle3DOverlay::render(RenderArgs* args) { - if (!_visible) { + if (!_renderVisible) { return; // do nothing if we're not visible } @@ -58,18 +55,11 @@ void Rectangle3DOverlay::render(RenderArgs* args) { const float MAX_COLOR = 255.0f; glm::vec4 rectangleColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); - glm::vec3 position = getPosition(); - glm::vec2 dimensions = getDimensions(); - glm::vec2 halfDimensions = dimensions * 0.5f; - glm::quat rotation = getRotation(); - auto batch = args->_batch; - if (batch) { - // FIXME Start using the _renderTransform instead of calling for Transform and Dimensions from here, do the custom things needed in evalRenderTransform() - Transform transform; - transform.setTranslation(position); - transform.setRotation(rotation); + Transform transform = getRenderTransform(); + glm::vec2 halfDimensions = transform.getScale() * 0.5f; + transform.setScale(1.0f); batch->setModelTransform(transform); auto geometryCache = DependencyManager::get(); @@ -124,8 +114,3 @@ void Rectangle3DOverlay::setProperties(const QVariantMap& properties) { Rectangle3DOverlay* Rectangle3DOverlay::createClone() const { return new Rectangle3DOverlay(this); } - -Transform Rectangle3DOverlay::evalRenderTransform() { - return getTransform(); -} - diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.h b/interface/src/ui/overlays/Rectangle3DOverlay.h index a26ed524fc..645553ed38 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.h +++ b/interface/src/ui/overlays/Rectangle3DOverlay.h @@ -29,9 +29,6 @@ public: virtual Rectangle3DOverlay* createClone() const override; -protected: - Transform evalRenderTransform() override; - private: int _geometryCacheID; std::array _rectGeometryIds; diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index a3b51d40bf..bd8e6a9728 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -24,7 +24,7 @@ Shape3DOverlay::Shape3DOverlay(const Shape3DOverlay* Shape3DOverlay) : } void Shape3DOverlay::render(RenderArgs* args) { - if (!_visible) { + if (!_renderVisible) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index c9fc25b252..2013e5689a 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -27,7 +27,7 @@ Sphere3DOverlay::Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay) : } void Sphere3DOverlay::render(RenderArgs* args) { - if (!_visible) { + if (!_renderVisible) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index d8188cf6dc..1cbc73304b 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -92,7 +92,7 @@ void Text3DOverlay::update(float deltatime) { } void Text3DOverlay::render(RenderArgs* args) { - if (!_visible || !getParentVisible()) { + if (!_renderVisible || !getParentVisible()) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 42d0ea0f12..d418a79fbf 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -268,7 +268,7 @@ Q_INVOKABLE int Web3DOverlay::deviceIdByTouchPoint(qreal x, qreal y) { } void Web3DOverlay::render(RenderArgs* args) { - if (!_visible || !getParentVisible()) { + if (!_renderVisible || !getParentVisible()) { return; } From c324f342b4bae05044f9c072127dc8c009b85761 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 9 Nov 2017 13:39:13 -0800 Subject: [PATCH 172/183] Fix to check ANDROID before UNIX --- cmake/externals/hifiAudioCodec/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/externals/hifiAudioCodec/CMakeLists.txt b/cmake/externals/hifiAudioCodec/CMakeLists.txt index 298f666304..e3ba36a440 100644 --- a/cmake/externals/hifiAudioCodec/CMakeLists.txt +++ b/cmake/externals/hifiAudioCodec/CMakeLists.txt @@ -11,12 +11,12 @@ if (WIN32) elseif (APPLE) set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-mac-2.0.zip) set(DOWNLOAD_MD5 21649881e7d5dc94f922179be96f76ba) -elseif (UNIX) - set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-linux-2.0.zip) - set(DOWNLOAD_MD5 67fb7755f9bcafb98a9fceea53bc7481) elseif (ANDROID) set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-android-2.0.zip) set(DOWNLOAD_MD5 aef2a852600d498d58aa586668191683) +elseif (UNIX) + set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-linux-2.0.zip) + set(DOWNLOAD_MD5 67fb7755f9bcafb98a9fceea53bc7481) else() return() endif() From 355b465109cfa92dd49d944d8d5b32e89526436b Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 9 Nov 2017 16:05:53 -0700 Subject: [PATCH 173/183] make leaveDomain slot private --- interface/src/avatar/MyAvatar.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 9133b967fa..e4e8f8d02c 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -561,8 +561,6 @@ public slots: float getDomainMinScale(); float getDomainMaxScale(); - void leaveDomain(); - void setGravity(float gravity); float getGravity(); @@ -624,6 +622,9 @@ signals: void attachmentsChanged(); void scaleChanged(); +private slots: + void leaveDomain(); + private: bool requiresSafeLanding(const glm::vec3& positionIn, glm::vec3& positionOut); From 9188ae9fb5ded91917cc251fdd6cdb5a7d1d6cc5 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 9 Nov 2017 16:26:37 -0800 Subject: [PATCH 174/183] fix laser end not disappearing --- interface/src/ui/overlays/Base3DOverlay.cpp | 15 ++++++++++----- interface/src/ui/overlays/Base3DOverlay.h | 7 +++++-- interface/src/ui/overlays/Line3DOverlay.cpp | 2 +- interface/src/ui/overlays/Planar3DOverlay.cpp | 2 +- interface/src/ui/overlays/Volume3DOverlay.cpp | 2 +- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 794c6e39ed..d157e29959 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -265,7 +265,7 @@ void Base3DOverlay::locationChanged(bool tellPhysics) { SpatiallyNestable::locationChanged(tellPhysics); // Force the actual update of the render transform through the notify call - notifyRenderTransformChange(); + notifyRenderVariableChange(); } void Base3DOverlay::parentDeleted() { @@ -275,13 +275,13 @@ void Base3DOverlay::parentDeleted() { void Base3DOverlay::update(float duration) { // In Base3DOverlay, if its location or bound changed, the renderTrasnformDirty flag is true. // then the correct transform used for rendering is computed in the update transaction and assigned. - if (_renderTransformDirty) { + if (_renderVariableDirty) { auto itemID = getRenderItemID(); if (render::Item::isValidID(itemID)) { // Capture the render transform value in game loop before auto latestTransform = evalRenderTransform(); bool latestVisible = getVisible(); - _renderTransformDirty = false; + _renderVariableDirty = false; render::ScenePointer scene = qApp->getMain3DScene(); render::Transaction transaction; transaction.updateItem(itemID, [latestTransform, latestVisible](Overlay& data) { @@ -297,8 +297,8 @@ void Base3DOverlay::update(float duration) { } } -void Base3DOverlay::notifyRenderTransformChange() const { - _renderTransformDirty = true; +void Base3DOverlay::notifyRenderVariableChange() const { + _renderVariableDirty = true; } Transform Base3DOverlay::evalRenderTransform() { @@ -318,3 +318,8 @@ SpatialParentTree* Base3DOverlay::getParentTree() const { EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; return entityTree.get(); } + +void Base3DOverlay::setVisible(bool visible) { + Parent::setVisible(visible); + notifyRenderVariableChange(); +} \ No newline at end of file diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 891edfce67..83c5873260 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -18,11 +18,14 @@ class Base3DOverlay : public Overlay, public SpatiallyNestable { Q_OBJECT + using Parent = Overlay; public: Base3DOverlay(); Base3DOverlay(const Base3DOverlay* base3DOverlay); + void setVisible(bool visible) override; + virtual OverlayID getOverlayID() const override { return OverlayID(getID().toString()); } void setOverlayID(OverlayID overlayID) override { setID(overlayID); } @@ -56,7 +59,7 @@ public: void update(float deltatime) override; - void notifyRenderTransformChange() const; + void notifyRenderVariableChange() const; void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; @@ -89,7 +92,7 @@ protected: bool _drawInFront; bool _drawHUDLayer; bool _isGrabbable { false }; - mutable bool _renderTransformDirty{ true }; + mutable bool _renderVariableDirty { true }; QString _name; }; diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index 82920827e1..5ef820b2e0 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -96,7 +96,7 @@ void Line3DOverlay::setEnd(const glm::vec3& end) { } else { _direction = glm::vec3(0.0f); } - notifyRenderTransformChange(); + notifyRenderVariableChange(); } void Line3DOverlay::setLocalEnd(const glm::vec3& localEnd) { diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index ac3fe66ddc..a9f0bfe2f1 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -37,7 +37,7 @@ AABox Planar3DOverlay::getBounds() const { void Planar3DOverlay::setDimensions(const glm::vec2& value) { _dimensions = value; - notifyRenderTransformChange(); + notifyRenderVariableChange(); } void Planar3DOverlay::setProperties(const QVariantMap& properties) { diff --git a/interface/src/ui/overlays/Volume3DOverlay.cpp b/interface/src/ui/overlays/Volume3DOverlay.cpp index 8aa8490937..e5a418cce5 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.cpp +++ b/interface/src/ui/overlays/Volume3DOverlay.cpp @@ -28,7 +28,7 @@ AABox Volume3DOverlay::getBounds() const { void Volume3DOverlay::setDimensions(const glm::vec3& value) { _localBoundingBox.setBox(-value / 2.0f, value); - notifyRenderTransformChange(); + notifyRenderVariableChange(); } void Volume3DOverlay::setProperties(const QVariantMap& properties) { From ba4c0f189e9600921efa5c4107858775b04b6de3 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 10 Nov 2017 10:25:29 -0800 Subject: [PATCH 175/183] code review feedback removed discontinuity in safeDeltaTime, which is used to prevent division by zero. --- interface/src/LODManager.cpp | 3 ++- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 8f01296e1c..01ccbd0d9a 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -54,7 +54,8 @@ void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float delta float renderTime = batchTime + OVERLAY_AND_SWAP_TIME_BUDGET; float maxTime = glm::max(renderTime, engineRunTime); const float BLEND_TIMESCALE = 0.3f; // sec - const float safeDeltaTime = (deltaTimeSec == 0.0f) ? 0.001f : deltaTimeSec; + const float MIN_DELTA_TIME = 0.001f; + const float safeDeltaTime = glm::max(deltaTimeSec, MIN_DELTA_TIME); float blend = BLEND_TIMESCALE / safeDeltaTime; if (blend > 1.0f) { blend = 1.0f; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 2335095056..49d2431098 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -453,7 +453,8 @@ void Avatar::applyPositionDelta(const glm::vec3& delta) { void Avatar::measureMotionDerivatives(float deltaTime) { PerformanceTimer perfTimer("derivatives"); // linear - const float safeDeltaTime = (deltaTime == 0.0f) ? 0.001f : deltaTime; + const float MIN_DELTA_TIME = 0.001f; + const float safeDeltaTime = glm::max(deltaTime, MIN_DELTA_TIME); float invDeltaTime = 1.0f / safeDeltaTime; // Floating point error prevents us from computing velocity in a naive way // (e.g. vel = (pos - oldPos) / dt) so instead we use _positionOffsetAccumulator. From d1318ae99eb48247deea1878e144bf1474c3fcc9 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Fri, 3 Nov 2017 11:51:03 -0700 Subject: [PATCH 176/183] 8495 No mirror camera in HMD mode --- interface/src/Application.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b21588958e..bd31fc398e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4441,7 +4441,7 @@ void Application::cameraModeChanged() { void Application::cameraMenuChanged() { auto menu = Menu::getInstance(); if (menu->isOptionChecked(MenuOption::FullscreenMirror)) { - if (_myCamera.getMode() != CAMERA_MODE_MIRROR) { + if (!isHMDMode() && _myCamera.getMode() != CAMERA_MODE_MIRROR) { _myCamera.setMode(CAMERA_MODE_MIRROR); getMyAvatar()->reset(false, false, false); // to reset any active MyAvatar::FollowHelpers } @@ -7271,6 +7271,10 @@ void Application::updateDisplayMode() { menu->setIsOptionChecked(MenuOption::FirstPerson, true); cameraMenuChanged(); } + + // Remove the mirror camera option from menu if in HMD mode + auto mirrorAction = menu->getActionForOption(MenuOption::FullscreenMirror); + mirrorAction->setVisible(!isHmd); Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } From 8596d78aa63432e069dac144ee9ceb66f8705b52 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 6 Nov 2017 08:03:07 -0700 Subject: [PATCH 177/183] Not posible to change to mirror mode using js --- interface/src/Application.cpp | 7 ++++++- libraries/shared/src/shared/Camera.cpp | 1 + libraries/shared/src/shared/Camera.h | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bd31fc398e..7172a3eab7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4423,7 +4423,12 @@ void Application::cameraModeChanged() { Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true); break; case CAMERA_MODE_MIRROR: - Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, true); + if (isHMDMode()) { + _myCamera.setMode(_myCamera.getLastMode()); + qDebug() << "Mirror mode is not available"; + } else { + Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, true); + } break; case CAMERA_MODE_INDEPENDENT: Menu::getInstance()->setIsOptionChecked(MenuOption::IndependentMode, true); diff --git a/libraries/shared/src/shared/Camera.cpp b/libraries/shared/src/shared/Camera.cpp index ab841c4717..100124a416 100644 --- a/libraries/shared/src/shared/Camera.cpp +++ b/libraries/shared/src/shared/Camera.cpp @@ -85,6 +85,7 @@ void Camera::setOrientation(const glm::quat& orientation) { } void Camera::setMode(CameraMode mode) { + _lastMode = _mode; _mode = mode; emit modeUpdated(modeToString(mode)); } diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index 3ad08bd719..11d4cf4254 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -56,6 +56,7 @@ public: void update(); CameraMode getMode() const { return _mode; } + CameraMode getLastMode() const { return _lastMode; } void setMode(CameraMode m); void loadViewFrustum(ViewFrustum& frustum) const; @@ -123,6 +124,7 @@ private: void decompose(); CameraMode _mode{ CAMERA_MODE_THIRD_PERSON }; + CameraMode _lastMode{ _mode }; glm::mat4 _transform; glm::mat4 _projection; From 5d4a3b65e473a0ead7b06c1f48017a573b3eb794 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 9 Nov 2017 18:27:16 -0700 Subject: [PATCH 178/183] Allow script to change to mirror camera in HMD --- interface/src/Application.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7172a3eab7..bd31fc398e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4423,12 +4423,7 @@ void Application::cameraModeChanged() { Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true); break; case CAMERA_MODE_MIRROR: - if (isHMDMode()) { - _myCamera.setMode(_myCamera.getLastMode()); - qDebug() << "Mirror mode is not available"; - } else { - Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, true); - } + Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, true); break; case CAMERA_MODE_INDEPENDENT: Menu::getInstance()->setIsOptionChecked(MenuOption::IndependentMode, true); From 7af1a5ca6999f74283f22f4700ddf5cd17ca7512 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 13 Nov 2017 06:10:17 -0700 Subject: [PATCH 179/183] clean up unused lastmode --- libraries/shared/src/shared/Camera.cpp | 1 - libraries/shared/src/shared/Camera.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/libraries/shared/src/shared/Camera.cpp b/libraries/shared/src/shared/Camera.cpp index 100124a416..ab841c4717 100644 --- a/libraries/shared/src/shared/Camera.cpp +++ b/libraries/shared/src/shared/Camera.cpp @@ -85,7 +85,6 @@ void Camera::setOrientation(const glm::quat& orientation) { } void Camera::setMode(CameraMode mode) { - _lastMode = _mode; _mode = mode; emit modeUpdated(modeToString(mode)); } diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index 11d4cf4254..3ad08bd719 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -56,7 +56,6 @@ public: void update(); CameraMode getMode() const { return _mode; } - CameraMode getLastMode() const { return _lastMode; } void setMode(CameraMode m); void loadViewFrustum(ViewFrustum& frustum) const; @@ -124,7 +123,6 @@ private: void decompose(); CameraMode _mode{ CAMERA_MODE_THIRD_PERSON }; - CameraMode _lastMode{ _mode }; glm::mat4 _transform; glm::mat4 _projection; From 05a38a78c517db0b3c646eac24ca9b1cb7824d57 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Nov 2017 14:08:27 -0800 Subject: [PATCH 180/183] don't send octree data without first query --- assignment-client/src/octree/OctreeSendThread.cpp | 5 +++-- libraries/octree/src/OctreeQuery.h | 2 +- libraries/octree/src/OctreeQueryNode.cpp | 6 ++++++ libraries/octree/src/OctreeQueryNode.h | 6 ++++++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 89e3d403fc..024071db0a 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -82,8 +82,9 @@ bool OctreeSendThread::process() { if (auto node = _node.lock()) { OctreeQueryNode* nodeData = static_cast(node->getLinkedData()); - // Sometimes the node data has not yet been linked, in which case we can't really do anything - if (nodeData && !nodeData->isShuttingDown()) { + // If we don't have the OctreeQueryNode or it's uninitialized because we haven't received + // a query yet from the client then we can't send an entity data packet + if (nodeData && nodeData->hasReceivedFirstQuery() && !nodeData->isShuttingDown()) { bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); packetDistributor(node, nodeData, viewFrustumChanged); } diff --git a/libraries/octree/src/OctreeQuery.h b/libraries/octree/src/OctreeQuery.h index fc9ea525e6..bbd0350baf 100644 --- a/libraries/octree/src/OctreeQuery.h +++ b/libraries/octree/src/OctreeQuery.h @@ -31,7 +31,7 @@ public: virtual ~OctreeQuery() {} int getBroadcastData(unsigned char* destinationBuffer); - int parseData(ReceivedMessage& message) override; + virtual int parseData(ReceivedMessage& message) override; // getters for camera details const glm::vec3& getCameraPosition() const { return _cameraPosition; } diff --git a/libraries/octree/src/OctreeQueryNode.cpp b/libraries/octree/src/OctreeQueryNode.cpp index c26b4ce77b..941bb6b536 100644 --- a/libraries/octree/src/OctreeQueryNode.cpp +++ b/libraries/octree/src/OctreeQueryNode.cpp @@ -18,6 +18,12 @@ #include #include +int OctreeQueryNode::parseData(ReceivedMessage& message) { + // set our flag to indicate that we've parsed for this query at least once + _hasReceivedFirstQuery = true; + + return OctreeQuery::parseData(message); +} void OctreeQueryNode::nodeKilled() { _isShuttingDown = true; diff --git a/libraries/octree/src/OctreeQueryNode.h b/libraries/octree/src/OctreeQueryNode.h index fd89a89949..fac118c628 100644 --- a/libraries/octree/src/OctreeQueryNode.h +++ b/libraries/octree/src/OctreeQueryNode.h @@ -35,6 +35,8 @@ public: void init(); // called after creation to set up some virtual items virtual PacketType getMyPacketType() const = 0; + virtual int parseData(ReceivedMessage& message) override; + void resetOctreePacket(); // resets octree packet to after "V" header void writeToPacket(const unsigned char* buffer, unsigned int bytes); // writes to end of packet @@ -106,6 +108,8 @@ public: bool shouldForceFullScene() const { return _shouldForceFullScene; } void setShouldForceFullScene(bool shouldForceFullScene) { _shouldForceFullScene = shouldForceFullScene; } + bool hasReceivedFirstQuery() const { return _hasReceivedFirstQuery; } + private: OctreeQueryNode(const OctreeQueryNode &); OctreeQueryNode& operator= (const OctreeQueryNode&); @@ -153,6 +157,8 @@ private: QJsonObject _lastCheckJSONParameters; bool _shouldForceFullScene { false }; + + bool _hasReceivedFirstQuery { false }; }; #endif // hifi_OctreeQueryNode_h From 557ee458ecf01cbfcd44a8d3d3574e065c51bcc6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Nov 2017 17:06:46 -0800 Subject: [PATCH 181/183] wait for node active socket before constructing packets --- assignment-client/src/octree/OctreeSendThread.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 024071db0a..3ae653307f 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -82,9 +82,12 @@ bool OctreeSendThread::process() { if (auto node = _node.lock()) { OctreeQueryNode* nodeData = static_cast(node->getLinkedData()); - // If we don't have the OctreeQueryNode or it's uninitialized because we haven't received - // a query yet from the client then we can't send an entity data packet - if (nodeData && nodeData->hasReceivedFirstQuery() && !nodeData->isShuttingDown()) { + // If we don't have the OctreeQueryNode at all + // or it's uninitialized because we haven't received a query yet from the client + // or we don't know where we should send packets for this node + // or we're shutting down + // then we can't send an entity data packet + if (nodeData && nodeData->hasReceivedFirstQuery() && node->getActiveSocket() && !nodeData->isShuttingDown()) { bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); packetDistributor(node, nodeData, viewFrustumChanged); } From 9f9c1e2d97e702d7fcf8685e36a8bf1431e5d3b4 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 15 Nov 2017 15:04:24 -0700 Subject: [PATCH 182/183] 9267 Fix not restoring animations after changing view modes --- libraries/animation/src/Rig.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index f06156874b..78aa1f4ba8 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -179,6 +179,11 @@ void Rig::restoreRoleAnimation(const QString& role) { } else { qCWarning(animation) << "Rig::restoreRoleAnimation could not find role " << role; } + + auto statesIter = _roleAnimStates.find(role); + if (statesIter != _roleAnimStates.end()) { + _roleAnimStates.erase(statesIter); + } } } else { qCWarning(animation) << "Rig::overrideRoleAnimation avatar not ready yet"; From 0755e4aa214031b95733a6dcd6c69478bb178110 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 16 Nov 2017 08:53:12 -0800 Subject: [PATCH 183/183] Fix for black screen on HMD derived display plugins --- interface/src/Application.cpp | 3 +++ interface/src/Application.h | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bd31fc398e..4b99d50761 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1825,6 +1825,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Preload Tablet sounds DependencyManager::get()->preloadSounds(); + _pendingIdleEvent = false; + _pendingRenderEvent = false; + qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); } diff --git a/interface/src/Application.h b/interface/src/Application.h index fbfb3979be..19a6dfdac1 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -708,7 +708,7 @@ private: friend class RenderEventHandler; - std::atomic _pendingIdleEvent { false }; - std::atomic _pendingRenderEvent { false }; + std::atomic _pendingIdleEvent { true }; + std::atomic _pendingRenderEvent { true }; }; #endif // hifi_Application_h