From b2925c5843ef5da8b40eb59adb8c12c94903f1c2 Mon Sep 17 00:00:00 2001
From: Dante Ruiz
Date: Tue, 24 Apr 2018 13:32:30 -0700
Subject: [PATCH 01/51] fixing attachments not being visible when coming out of
first person
---
interface/src/avatar/MyAvatar.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp
index 249a765d92..e288528be9 100755
--- a/interface/src/avatar/MyAvatar.cpp
+++ b/interface/src/avatar/MyAvatar.cpp
@@ -2037,12 +2037,12 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) {
_attachmentData[i].jointName.compare("RightEye", Qt::CaseInsensitive) == 0 ||
_attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 ||
_attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) {
-
+ uint32_t renderTagBits = shouldDrawHead ? render::ItemKey::TAG_BITS_0 : render::ItemKey::TAG_BITS_NONE;
_attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene(),
- render::ItemKey::TAG_BITS_NONE, true);
+ renderTagBits, false);
- _attachmentModels[i]->setCanCastShadow(shouldDrawHead, qApp->getMain3DScene(),
- render::ItemKey::TAG_BITS_NONE, true);
+ _attachmentModels[i]->setCanCastShadow(shouldDrawHead, qApp->getMain3DScene(),
+ renderTagBits, false);
}
}
}
From 29fce488e479460437db366fdc2f5edb22e800bf Mon Sep 17 00:00:00 2001
From: Dante Ruiz
Date: Tue, 24 Apr 2018 14:00:52 -0700
Subject: [PATCH 02/51] make some changes
---
interface/src/avatar/MyAvatar.cpp | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp
index e288528be9..367042bcf9 100755
--- a/interface/src/avatar/MyAvatar.cpp
+++ b/interface/src/avatar/MyAvatar.cpp
@@ -2037,12 +2037,14 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) {
_attachmentData[i].jointName.compare("RightEye", Qt::CaseInsensitive) == 0 ||
_attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 ||
_attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) {
- uint32_t renderTagBits = shouldDrawHead ? render::ItemKey::TAG_BITS_0 : render::ItemKey::TAG_BITS_NONE;
- _attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene(),
- renderTagBits, false);
+ uint8_t modelRenderTagBits = shouldDrawHead ? render::ItemKey::TAG_BITS_0 : render::ItemKey::TAG_BITS_NONE;
+ modelRenderTagBits |= render::ItemKey::TAG_BITS_1;
+ _attachmentModels[i]->setVisibleInScene(true, qApp->getMain3DScene(),
+ modelRenderTagBits, false);
- _attachmentModels[i]->setCanCastShadow(shouldDrawHead, qApp->getMain3DScene(),
- renderTagBits, false);
+ uint8_t castShadowRenderTagBits = render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1;
+ _attachmentModels[i]->setCanCastShadow(true, qApp->getMain3DScene(),
+ castShadowRenderTagBits, false);
}
}
}
From 496b638a885ef34cf66fe541e925aa61cef37b59 Mon Sep 17 00:00:00 2001
From: Ryan Huffman
Date: Thu, 26 Apr 2018 14:31:31 -0700
Subject: [PATCH 03/51] Fix log file directory not being capped at 50MB
---
libraries/shared/src/shared/FileLogger.cpp | 35 +++++++++++-----------
1 file changed, 17 insertions(+), 18 deletions(-)
diff --git a/libraries/shared/src/shared/FileLogger.cpp b/libraries/shared/src/shared/FileLogger.cpp
index 8ceb378574..4f4a9ab6dd 100644
--- a/libraries/shared/src/shared/FileLogger.cpp
+++ b/libraries/shared/src/shared/FileLogger.cpp
@@ -36,17 +36,15 @@ protected:
private:
const FileLogger& _logger;
QMutex _fileMutex;
- uint64_t _lastRollTime;
+ std::chrono::system_clock::time_point _lastRollTime;
};
-
-
static const QString FILENAME_FORMAT = "hifi-log_%1%2.txt";
static const QString DATETIME_FORMAT = "yyyy-MM-dd_hh.mm.ss";
static const QString LOGS_DIRECTORY = "Logs";
-static const QString IPADDR_WILDCARD = "[0-9]*.[0-9]*.[0-9]*.[0-9]*";
-static const QString DATETIME_WILDCARD = "20[0-9][0-9]-[0,1][0-9]-[0-3][0-9]_[0-2][0-9].[0-6][0-9].[0-6][0-9]";
-static const QString FILENAME_WILDCARD = "hifi-log_" + IPADDR_WILDCARD + "_" + DATETIME_WILDCARD + ".txt";
+static const QString DATETIME_WILDCARD = "20[0-9][0-9]-[01][0-9]-[0-3][0-9]_[0-2][0-9]\\.[0-6][0-9]\\.[0-6][0-9]";
+static const QString SESSION_WILDCARD = "[0-9a-z]{8}(-[0-9a-z]{4}){3}-[0-9a-z]{12}";
+static QRegExp LOG_FILENAME_REGEX { "hifi-log_" + DATETIME_WILDCARD + "(_" + SESSION_WILDCARD + ")?\.txt" };
static QUuid SESSION_ID;
// Max log size is 512 KB. We send log files to our crash reporter, so we want to keep this relatively
@@ -104,20 +102,21 @@ void FilePersistThread::rollFileIfNecessary(QFile& file, bool notifyListenersIfR
_lastRollTime = now;
}
- QStringList nameFilters;
- nameFilters << FILENAME_WILDCARD;
- QDir logQDir(FileUtils::standardPath(LOGS_DIRECTORY));
- logQDir.setNameFilters(nameFilters);
- logQDir.setSorting(QDir::Time);
- QFileInfoList filesInDir = logQDir.entryInfoList();
+ QDir logDir(FileUtils::standardPath(LOGS_DIRECTORY));
+ logDir.setSorting(QDir::Time);
+ logDir.setFilter(QDir::Files);
qint64 totalSizeOfDir = 0;
- foreach(QFileInfo dirItm, filesInDir){
- if (totalSizeOfDir < MAX_LOG_DIR_SIZE){
- totalSizeOfDir += dirItm.size();
- } else {
- QFile file(dirItm.filePath());
- file.remove();
+ QFileInfoList filesInDir = logDir.entryInfoList();
+ for (auto& fileInfo : filesInDir) {
+ if (!LOG_FILENAME_REGEX.exactMatch(fileInfo.fileName())) {
+ continue;
+ }
+ totalSizeOfDir += fileInfo.size();
+ if (totalSizeOfDir > MAX_LOG_DIR_SIZE){
+ qDebug() << "Removing log file: " << fileInfo.fileName();
+ QFile oldLogFile(fileInfo.filePath());
+ oldLogFile.remove();
}
}
}
From 1448f3959ebe541fe9457e70b2aae0e0598e6b04 Mon Sep 17 00:00:00 2001
From: Simon Walton
Date: Thu, 26 Apr 2018 17:11:17 -0700
Subject: [PATCH 04/51] Add a utility function to dump ConnectionStats
---
.../networking/src/udt/ConnectionStats.cpp | 29 +++++++++++++++++++
.../networking/src/udt/ConnectionStats.h | 3 ++
2 files changed, 32 insertions(+)
diff --git a/libraries/networking/src/udt/ConnectionStats.cpp b/libraries/networking/src/udt/ConnectionStats.cpp
index e7efe3d5af..46d88e680f 100644
--- a/libraries/networking/src/udt/ConnectionStats.cpp
+++ b/libraries/networking/src/udt/ConnectionStats.cpp
@@ -9,6 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
+#include
#include "ConnectionStats.h"
using namespace udt;
@@ -112,3 +113,31 @@ void ConnectionStats::recordPacketSendPeriod(int sample) {
_currentSample.packetSendPeriod = sample;
_total.packetSendPeriod = (int)((_total.packetSendPeriod * EWMA_PREVIOUS_SAMPLES_WEIGHT) + (sample * EWMA_CURRENT_SAMPLE_WEIGHT));
}
+
+QDebug& operator<<(QDebug&& debug, const udt::ConnectionStats::Stats& stats) {
+ debug << "Connection stats:\n";
+#define HIFI_LOG_EVENT(x) << " " #x " events: " << stats.events[ConnectionStats::Stats::Event::x] << "\n"
+ debug
+ HIFI_LOG_EVENT(SentACK)
+ HIFI_LOG_EVENT(ReceivedACK)
+ HIFI_LOG_EVENT(ProcessedACK)
+ HIFI_LOG_EVENT(SentLightACK)
+ HIFI_LOG_EVENT(ReceivedLightACK)
+ HIFI_LOG_EVENT(SentACK2)
+ HIFI_LOG_EVENT(ReceivedACK2)
+ HIFI_LOG_EVENT(SentNAK)
+ HIFI_LOG_EVENT(ReceivedNAK)
+ HIFI_LOG_EVENT(SentTimeoutNAK)
+ HIFI_LOG_EVENT(ReceivedTimeoutNAK)
+ HIFI_LOG_EVENT(Retransmission)
+ HIFI_LOG_EVENT(Duplicate)
+ ;
+#undef HIFI_LOG_EVENT
+
+ debug << " Sent packets: " << stats.sentPackets;
+ debug << "\n Received packets: " << stats.receivedPackets;
+ debug << "\n Sent util bytes: " << stats.sentUtilBytes;
+ debug << "\n Sent bytes: " << stats.sentBytes;
+ debug << "\n Received bytes: " << stats.receivedBytes << "\n";
+ return debug;
+}
diff --git a/libraries/networking/src/udt/ConnectionStats.h b/libraries/networking/src/udt/ConnectionStats.h
index 84cd6b2486..7ec7b163ee 100644
--- a/libraries/networking/src/udt/ConnectionStats.h
+++ b/libraries/networking/src/udt/ConnectionStats.h
@@ -101,4 +101,7 @@ private:
}
+class QDebug;
+QDebug& operator<<(QDebug&& debug, const udt::ConnectionStats::Stats& stats);
+
#endif // hifi_ConnectionStats_h
From 2cc3ed6287afbd5df4cb65a6f42f6389671eeabe Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Sat, 28 Apr 2018 20:00:28 +1200
Subject: [PATCH 05/51] List which contexts each namespace and object is
available in
---
interface/src/AvatarBookmarks.h | 4 ++++
interface/src/LODManager.h | 5 ++++-
interface/src/SpeechRecognizer.h | 3 +++
interface/src/audio/AudioScope.h | 4 ++++
interface/src/avatar/AvatarManager.h | 3 +++
interface/src/devices/DdeFaceTracker.h | 3 +++
interface/src/raypick/PickScriptingInterface.h | 4 ++++
interface/src/raypick/PointerScriptingInterface.h | 3 +++
.../src/scripting/AccountServicesScriptingInterface.h | 3 +++
interface/src/scripting/Audio.h | 8 +++++++-
interface/src/scripting/ClipboardScriptingInterface.h | 3 +++
.../src/scripting/ControllerScriptingInterface.h | 5 ++++-
.../src/scripting/GooglePolyScriptingInterface.h | 3 +++
interface/src/scripting/HMDScriptingInterface.h | 6 +++++-
interface/src/scripting/MenuScriptingInterface.h | 3 +++
interface/src/scripting/SelectionScriptingInterface.h | 3 +++
interface/src/scripting/SettingsScriptingInterface.h | 3 +++
interface/src/scripting/WindowScriptingInterface.h | 6 +++++-
interface/src/ui/AvatarInputs.h | 4 ++++
interface/src/ui/overlays/ContextOverlayInterface.h | 3 ---
interface/src/ui/overlays/Overlays.h | 4 ++++
libraries/animation/src/AnimationCache.h | 4 ++++
libraries/audio-client/src/AudioIOStats.h | 8 ++++++++
libraries/audio/src/SoundCache.h | 5 +++++
.../src/controllers/impl/MappingBuilderProxy.h | 5 ++++-
.../src/controllers/impl/RouteBuilderProxy.h | 3 +++
.../src/display-plugins/CompositorHelper.h | 4 ++++
libraries/entities/src/EntityScriptingInterface.h | 6 ++++++
.../graphics-scripting/GraphicsScriptingInterface.h | 3 +++
.../src/model-networking/ModelCache.h | 3 +++
.../src/model-networking/TextureCache.h | 3 +++
libraries/networking/src/AddressManager.h | 5 +++++
libraries/networking/src/MessagesClient.h | 5 +++++
libraries/networking/src/ResourceCache.h | 6 ++++++
libraries/script-engine/src/AssetScriptingInterface.h | 5 +++++
libraries/script-engine/src/Quat.h | 6 ++++++
.../script-engine/src/RecordingScriptingInterface.h | 4 ++++
libraries/script-engine/src/SceneScriptingInterface.h | 8 ++++++++
libraries/script-engine/src/ScriptEngine.h | 6 ++++++
libraries/script-engine/src/ScriptEngines.h | 4 ++++
libraries/script-engine/src/ScriptUUID.h | 6 ++++++
libraries/script-engine/src/ScriptsModel.h | 3 +++
libraries/script-engine/src/ScriptsModelFilter.h | 3 +++
libraries/script-engine/src/UsersScriptingInterface.h | 7 ++++++-
libraries/script-engine/src/Vec3.h | 6 ++++++
libraries/shared/src/DebugDraw.h | 5 +++++
libraries/shared/src/PathUtils.h | 4 ++++
libraries/shared/src/RegisteredMetaTypes.h | 6 ++++++
libraries/shared/src/shared/Camera.h | 4 ++++
libraries/ui/src/ui/TabletScriptingInterface.h | 11 +++++++++++
50 files changed, 221 insertions(+), 10 deletions(-)
diff --git a/interface/src/AvatarBookmarks.h b/interface/src/AvatarBookmarks.h
index 177e6e493e..7b47ea8af7 100644
--- a/interface/src/AvatarBookmarks.h
+++ b/interface/src/AvatarBookmarks.h
@@ -18,6 +18,10 @@
/**jsdoc
* This API helps manage adding and deleting avatar bookmarks.
* @namespace AvatarBookmarks
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
*/
class AvatarBookmarks: public Bookmarks, public Dependency {
diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h
index e8737d92ae..889fff3153 100644
--- a/interface/src/LODManager.h
+++ b/interface/src/LODManager.h
@@ -10,8 +10,11 @@
//
/**jsdoc
- * The LOD class manages your Level of Detail functions within interface
+ * The LODManager API manages your Level of Detail functions within interface.
* @namespace LODManager
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
#ifndef hifi_LODManager_h
diff --git a/interface/src/SpeechRecognizer.h b/interface/src/SpeechRecognizer.h
index d5f9031cfc..b22ab73837 100644
--- a/interface/src/SpeechRecognizer.h
+++ b/interface/src/SpeechRecognizer.h
@@ -24,6 +24,9 @@
/**jsdoc
* @namespace SpeechRecognizer
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
class SpeechRecognizer : public QObject, public Dependency {
Q_OBJECT
diff --git a/interface/src/audio/AudioScope.h b/interface/src/audio/AudioScope.h
index ff8bfda6dd..41cee8d17d 100644
--- a/interface/src/audio/AudioScope.h
+++ b/interface/src/audio/AudioScope.h
@@ -28,6 +28,10 @@ class AudioScope : public QObject, public Dependency {
/**jsdoc
* The AudioScope API helps control the Audio Scope features in Interface
* @namespace AudioScope
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {number} scopeInput Read-only.
* @property {number} scopeOutputLeft Read-only.
* @property {number} scopeOutputRight Read-only.
diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h
index d2655914d2..7f5aa00466 100644
--- a/interface/src/avatar/AvatarManager.h
+++ b/interface/src/avatar/AvatarManager.h
@@ -30,6 +30,9 @@
/**jsdoc
* The AvatarManager API has properties and methods which manage Avatars within the same domain.
* @namespace AvatarManager
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
class AvatarManager : public AvatarHashMap {
diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h
index d4af0bbd37..4fe36b582e 100644
--- a/interface/src/devices/DdeFaceTracker.h
+++ b/interface/src/devices/DdeFaceTracker.h
@@ -29,6 +29,9 @@
/**jsdoc
* The FaceTracker API helps manage facial tracking hardware.
* @namespace FaceTracker
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
class DdeFaceTracker : public FaceTracker, public Dependency {
diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h
index f2cd9287a5..2568dd8457 100644
--- a/interface/src/raypick/PickScriptingInterface.h
+++ b/interface/src/raypick/PickScriptingInterface.h
@@ -18,6 +18,10 @@
* The Picks API lets you create and manage objects for repeatedly calculating intersections in different ways.
*
* @namespace Picks
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property PICK_NOTHING {number} A filter flag. Don't intersect with anything.
* @property PICK_ENTITIES {number} A filter flag. Include entities when intersecting.
* @property PICK_OVERLAYS {number} A filter flag. Include overlays when intersecting.
diff --git a/interface/src/raypick/PointerScriptingInterface.h b/interface/src/raypick/PointerScriptingInterface.h
index 1cc7b56503..e7acfd4037 100644
--- a/interface/src/raypick/PointerScriptingInterface.h
+++ b/interface/src/raypick/PointerScriptingInterface.h
@@ -19,6 +19,9 @@
* Pointers can also be configured to automatically generate PointerEvents.
*
* @namespace Pointers
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
class PointerScriptingInterface : public QObject, public Dependency {
diff --git a/interface/src/scripting/AccountServicesScriptingInterface.h b/interface/src/scripting/AccountServicesScriptingInterface.h
index d38a84d8fa..5774ee1da5 100644
--- a/interface/src/scripting/AccountServicesScriptingInterface.h
+++ b/interface/src/scripting/AccountServicesScriptingInterface.h
@@ -38,6 +38,9 @@ class AccountServicesScriptingInterface : public QObject {
/**jsdoc
* The AccountServices API contains helper functions related to user connectivity
*
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @namespace AccountServices
* @property {string} username Read-only.
* @property {boolean} loggedIn Read-only.
diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h
index c77d1522b5..f0a4328c2f 100644
--- a/interface/src/scripting/Audio.h
+++ b/interface/src/scripting/Audio.h
@@ -27,8 +27,14 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable {
/**jsdoc
* The Audio API features tools to help control audio contexts and settings.
- *
+ *
* @namespace Audio
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-server-entity
+ * @hifi-assignment-client
+ *
* @property {boolean} muted
* @property {boolean} noiseReduction
* @property {number} inputVolume
diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h
index cce300e831..32b8c64a7d 100644
--- a/interface/src/scripting/ClipboardScriptingInterface.h
+++ b/interface/src/scripting/ClipboardScriptingInterface.h
@@ -21,6 +21,9 @@
* The Clipboard API enables you to export and import entities to and from JSON files.
*
* @namespace Clipboard
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
class ClipboardScriptingInterface : public QObject {
Q_OBJECT
diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h
index f19caa8478..42bb648abf 100644
--- a/interface/src/scripting/ControllerScriptingInterface.h
+++ b/interface/src/scripting/ControllerScriptingInterface.h
@@ -145,7 +145,10 @@ class ScriptEngine;
*
* @namespace Controller
*
- * @property {Controller.Actions} Actions - Predefined actions on Interface and the user's avatar. These can be used as end
+ * @hifi-interface
+ * @hifi-client-entity
+ *
+ * @property {Controller.Actions} Actions - Predefined actions on Interface and the user's avatar. These can be used as end
* points in a {@link RouteObject} mapping. A synonym for Controller.Hardware.Actions
.
* Read-only.
* Default mappings are provided from the Controller.Hardware.Keyboard
and Controller.Standard
to
diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h
index 5c37b394fa..fb5aed9759 100644
--- a/interface/src/scripting/GooglePolyScriptingInterface.h
+++ b/interface/src/scripting/GooglePolyScriptingInterface.h
@@ -18,6 +18,9 @@
/**jsdoc
* The GooglePoly API allows you to interact with Google Poly models direct from inside High Fidelity.
* @namespace GooglePoly
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
class GooglePolyScriptingInterface : public QObject, public Dependency {
diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h
index 9b2482e73a..d2a272851f 100644
--- a/interface/src/scripting/HMDScriptingInterface.h
+++ b/interface/src/scripting/HMDScriptingInterface.h
@@ -28,7 +28,11 @@ class QScriptEngine;
* The HMD API provides access to the HMD used in VR display mode.
*
* @namespace HMD
- * @property {Vec3} position - The position of the HMD if currently in VR display mode, otherwise
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
+ * @property {Vec3} position - The position of the HMD if currently in VR display mode, otherwise
* {@link Vec3(0)|Vec3.ZERO}. Read-only.
* @property {Quat} orientation - The orientation of the HMD if currently in VR display mode, otherwise
* {@link Quat(0)|Quat.IDENTITY}. Read-only.
diff --git a/interface/src/scripting/MenuScriptingInterface.h b/interface/src/scripting/MenuScriptingInterface.h
index 649c444eaf..81cf775de8 100644
--- a/interface/src/scripting/MenuScriptingInterface.h
+++ b/interface/src/scripting/MenuScriptingInterface.h
@@ -32,6 +32,9 @@ class MenuItemProperties;
* If a menu item doesn't belong to a group it is always displayed.
*
* @namespace Menu
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
/**
diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h
index 71ff41248a..df92250c28 100644
--- a/interface/src/scripting/SelectionScriptingInterface.h
+++ b/interface/src/scripting/SelectionScriptingInterface.h
@@ -86,6 +86,9 @@ protected:
* The Selection
API provides a means of grouping together avatars, entities, and overlays in named lists.
* @namespace Selection
*
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @example Outline an entity when it is grabbed by a controller.
* // Create a box and copy the following text into the entity's "Script URL" field.
* (function () {
diff --git a/interface/src/scripting/SettingsScriptingInterface.h b/interface/src/scripting/SettingsScriptingInterface.h
index 9e0271601b..32d868bb24 100644
--- a/interface/src/scripting/SettingsScriptingInterface.h
+++ b/interface/src/scripting/SettingsScriptingInterface.h
@@ -18,6 +18,9 @@
/**jsdoc
* The Settings API provides a facility to store and retrieve values that persist between Interface runs.
* @namespace Settings
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
class SettingsScriptingInterface : public QObject {
diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h
index 0b766d2097..348882e0f8 100644
--- a/interface/src/scripting/WindowScriptingInterface.h
+++ b/interface/src/scripting/WindowScriptingInterface.h
@@ -28,7 +28,11 @@
* physics.
*
* @namespace Window
- * @property {number} innerWidth - The width of the drawable area of the Interface window (i.e., without borders or other
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
+ * @property {number} innerWidth - The width of the drawable area of the Interface window (i.e., without borders or other
* chrome), in pixels. Read-only.
* @property {number} innerHeight - The height of the drawable area of the Interface window (i.e., without borders or other
* chrome), in pixels. Read-only.
diff --git a/interface/src/ui/AvatarInputs.h b/interface/src/ui/AvatarInputs.h
index a9d1509770..e67d35e59f 100644
--- a/interface/src/ui/AvatarInputs.h
+++ b/interface/src/ui/AvatarInputs.h
@@ -26,6 +26,10 @@ class AvatarInputs : public QObject {
/**jsdoc
* API to help manage your Avatar's input
* @namespace AvatarInputs
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {boolean} cameraEnabled Read-only.
* @property {boolean} cameraMuted Read-only.
* @property {boolean} isHMD Read-only.
diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h
index b80a3a70fb..808c3a4ee3 100644
--- a/interface/src/ui/overlays/ContextOverlayInterface.h
+++ b/interface/src/ui/overlays/ContextOverlayInterface.h
@@ -31,9 +31,6 @@
#include "EntityTree.h"
#include "ContextOverlayLogging.h"
-/**jsdoc
-* @namespace ContextOverlay
-*/
class ContextOverlayInterface : public QObject, public Dependency {
Q_OBJECT
diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h
index c2f6e3e693..cf1151b46a 100644
--- a/interface/src/ui/overlays/Overlays.h
+++ b/interface/src/ui/overlays/Overlays.h
@@ -76,6 +76,10 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R
* The Overlays API provides facilities to create and interact with overlays. Overlays are 2D and 3D objects visible only to
* yourself and that aren't persisted to the domain. They are used for UI.
* @namespace Overlays
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {Uuid} keyboardFocusOverlay - Get or set the {@link Overlays.OverlayType|web3d} overlay that has keyboard focus.
* If no overlay has keyboard focus, get returns null
; set to null
or {@link Uuid|Uuid.NULL} to
* clear keyboard focus.
diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h
index 03b37aef2f..4db009f592 100644
--- a/libraries/animation/src/AnimationCache.h
+++ b/libraries/animation/src/AnimationCache.h
@@ -37,6 +37,10 @@ public:
* API to manage animation cache resources.
* @namespace AnimationCache
*
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-assignment-client
+ *
* @property {number} numTotal - Total number of total resources. Read-only.
* @property {number} numCached - Total number of cached resource. Read-only.
* @property {number} sizeTotal - Size in bytes of all resources. Read-only.
diff --git a/libraries/audio-client/src/AudioIOStats.h b/libraries/audio-client/src/AudioIOStats.h
index 89db4942ec..45fcf365da 100644
--- a/libraries/audio-client/src/AudioIOStats.h
+++ b/libraries/audio-client/src/AudioIOStats.h
@@ -41,6 +41,10 @@ class AudioStreamStatsInterface : public QObject {
/**jsdoc
* @class AudioStats.AudioStreamStats
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {number} lossRate Read-only.
* @property {number} lossCount Read-only.
* @property {number} lossRateWindow Read-only.
@@ -185,6 +189,10 @@ class AudioStatsInterface : public QObject {
/**jsdoc
* Audio stats from the client.
* @namespace AudioStats
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {number} pingMs Read-only.
* @property {number} inputReadMsMax Read-only.
* @property {number} inputUnplayedMsMax Read-only.
diff --git a/libraries/audio/src/SoundCache.h b/libraries/audio/src/SoundCache.h
index d8c52635e0..0874cef90e 100644
--- a/libraries/audio/src/SoundCache.h
+++ b/libraries/audio/src/SoundCache.h
@@ -29,6 +29,11 @@ public:
* API to manage sound cache resources.
* @namespace SoundCache
*
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-server-entity
+ * @hifi-assignment-client
+ *
* @property {number} numTotal - Total number of total resources. Read-only.
* @property {number} numCached - Total number of cached resource. Read-only.
* @property {number} sizeTotal - Size in bytes of all resources. Read-only.
diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h
index 86a43c0c13..4521c89afd 100644
--- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h
+++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h
@@ -49,9 +49,12 @@ class UserInputMapper;
* output that already has a route the new route is ignored.
* New mappings override previous mappings: each output is processed using the route in the most recently enabled
* mapping that contains that output.
- *
+ *
*
* @class MappingObject
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
/**jsdoc
diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h
index 0336638068..3204e0502f 100644
--- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h
+++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h
@@ -35,6 +35,9 @@ class ScriptingInterface;
* types.
*
* @class RouteObject
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
// TODO migrate functionality to a RouteBuilder class and make the proxy defer to that
diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h
index bc6ed63363..fb712c26fa 100644
--- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h
+++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h
@@ -174,6 +174,10 @@ private:
/**jsdoc
* @namespace Reticle
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {boolean} allowMouseCapture
* @property {number} depth
* @property {Vec2} maximumPosition
diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h
index d4a8b11453..2491d4bbbd 100644
--- a/libraries/entities/src/EntityScriptingInterface.h
+++ b/libraries/entities/src/EntityScriptingInterface.h
@@ -94,6 +94,12 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra
* Interface has displayed and so knows about.
*
* @namespace Entities
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-server-entity
+ * @hifi-assignment-client
+ *
* @property {Uuid} keyboardFocusEntity - Get or set the {@link Entities.EntityType|Web} entity that has keyboard focus.
* If no entity has keyboard focus, get returns null
; set to null
or {@link Uuid|Uuid.NULL} to
* clear keyboard focus.
diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h
index 526352804b..8b76491229 100644
--- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h
+++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h
@@ -24,6 +24,9 @@
/**jsdoc
* The experimental Graphics API (experimental) lets you query and manage certain graphics-related structures (like underlying meshes and textures) from scripting.
* @namespace Graphics
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
class GraphicsScriptingInterface : public QObject, public QScriptable, public Dependency {
diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h
index 9532f39ce0..cda825e5fb 100644
--- a/libraries/model-networking/src/model-networking/ModelCache.h
+++ b/libraries/model-networking/src/model-networking/ModelCache.h
@@ -144,6 +144,9 @@ public:
* API to manage model cache resources.
* @namespace ModelCache
*
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {number} numTotal - Total number of total resources. Read-only.
* @property {number} numCached - Total number of cached resource. Read-only.
* @property {number} sizeTotal - Size in bytes of all resources. Read-only.
diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h
index 3f46dc3074..ef911103c3 100644
--- a/libraries/model-networking/src/model-networking/TextureCache.h
+++ b/libraries/model-networking/src/model-networking/TextureCache.h
@@ -151,6 +151,9 @@ public:
* API to manage texture cache resources.
* @namespace TextureCache
*
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {number} numTotal - Total number of total resources. Read-only.
* @property {number} numCached - Total number of cached resource. Read-only.
* @property {number} sizeTotal - Size in bytes of all resources. Read-only.
diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h
index 94eff46bda..94fb25812f 100644
--- a/libraries/networking/src/AddressManager.h
+++ b/libraries/networking/src/AddressManager.h
@@ -33,6 +33,11 @@ const QString GET_PLACE = "/api/v1/places/%1";
* The location API provides facilities related to your current location in the metaverse.
*
* @namespace location
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-assignment-client
+ *
* @property {Uuid} domainID - A UUID uniquely identifying the domain you're visiting. Is {@link Uuid|Uuid.NULL} if you're not
* connected to the domain or are in a serverless domain.
* Read-only.
diff --git a/libraries/networking/src/MessagesClient.h b/libraries/networking/src/MessagesClient.h
index 6ef3777d8c..f2ccfe33f4 100644
--- a/libraries/networking/src/MessagesClient.h
+++ b/libraries/networking/src/MessagesClient.h
@@ -37,6 +37,11 @@
*
*
* @namespace Messages
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-server-entity
+ * @hifi-assignment-client
*/
class MessagesClient : public QObject, public Dependency {
Q_OBJECT
diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h
index 609483bc56..799d2c7f59 100644
--- a/libraries/networking/src/ResourceCache.h
+++ b/libraries/networking/src/ResourceCache.h
@@ -89,6 +89,12 @@ class ScriptableResource : public QObject {
/**jsdoc
* @constructor Resource
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-server-entity
+ * @hifi-assignment-client
+ *
* @property {string} url - URL of this resource.
* @property {Resource.State} state - Current loading state.
*/
diff --git a/libraries/script-engine/src/AssetScriptingInterface.h b/libraries/script-engine/src/AssetScriptingInterface.h
index 5cb1136b74..eb9a628ae3 100644
--- a/libraries/script-engine/src/AssetScriptingInterface.h
+++ b/libraries/script-engine/src/AssetScriptingInterface.h
@@ -27,6 +27,11 @@
/**jsdoc
* The Assets API allows you to communicate with the Asset Browser.
* @namespace Assets
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-server-entity
+ * @hifi-assignment-client
*/
class AssetScriptingInterface : public BaseAssetScriptingInterface, QScriptable {
Q_OBJECT
diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h
index e6e395d9bf..254757dece 100644
--- a/libraries/script-engine/src/Quat.h
+++ b/libraries/script-engine/src/Quat.h
@@ -35,6 +35,12 @@
* of gimbal lock.
* @namespace Quat
* @variation 0
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-server-entity
+ * @hifi-assignment-client
+ *
* @property IDENTITY {Quat} { x: 0, y: 0, z: 0, w: 1 }
: The identity rotation, i.e., no rotation.
* Read-only.
* @example
Print the IDENTITY
value.
diff --git a/libraries/script-engine/src/RecordingScriptingInterface.h b/libraries/script-engine/src/RecordingScriptingInterface.h
index 0e4f90b928..29d9b31049 100644
--- a/libraries/script-engine/src/RecordingScriptingInterface.h
+++ b/libraries/script-engine/src/RecordingScriptingInterface.h
@@ -25,6 +25,10 @@ class QScriptValue;
/**jsdoc
* @namespace Recording
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-assignment-client
*/
class RecordingScriptingInterface : public QObject, public Dependency {
Q_OBJECT
diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h
index c69cd7090d..fdfbc6f6c0 100644
--- a/libraries/script-engine/src/SceneScriptingInterface.h
+++ b/libraries/script-engine/src/SceneScriptingInterface.h
@@ -112,6 +112,10 @@ namespace SceneScripting {
/**jsdoc
* @class Scene.Stage
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {string} backgroundMode
* @property {Scene.Stage.KeyLight} keyLight
* @property {Scene.Stage.Location} location
@@ -171,6 +175,10 @@ namespace SceneScripting {
/**jsdoc
* @namespace Scene
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {boolean} shouldRenderAvatars
* @property {boolean} shouldRenderEntities
* @property {Scene.Stage} stage
diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h
index 63a4ba4f90..af4d04a706 100644
--- a/libraries/script-engine/src/ScriptEngine.h
+++ b/libraries/script-engine/src/ScriptEngine.h
@@ -89,6 +89,12 @@ public:
/**jsdoc
* @namespace Script
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-server-entity
+ * @hifi-assignment-client
+ *
* @property {string} context
*/
class ScriptEngine : public BaseScriptEngine, public EntitiesScriptEngineProvider {
diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h
index 1200168420..da6fe521c9 100644
--- a/libraries/script-engine/src/ScriptEngines.h
+++ b/libraries/script-engine/src/ScriptEngines.h
@@ -29,6 +29,10 @@ class ScriptEngine;
/**jsdoc
* @namespace ScriptDiscoveryService
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {string} debugScriptUrl
* @property {string} defaultScriptsPath
* @property {ScriptsModel} scriptsModel
diff --git a/libraries/script-engine/src/ScriptUUID.h b/libraries/script-engine/src/ScriptUUID.h
index 303a871d1d..9b61f451c5 100644
--- a/libraries/script-engine/src/ScriptUUID.h
+++ b/libraries/script-engine/src/ScriptUUID.h
@@ -23,6 +23,12 @@
* hexadecimal digits.
*
* @namespace Uuid
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-server-entity
+ * @hifi-assignment-client
+ *
* @property NULL {Uuid} The null UUID, {00000000-0000-0000-0000-000000000000}
.
*/
diff --git a/libraries/script-engine/src/ScriptsModel.h b/libraries/script-engine/src/ScriptsModel.h
index a4ffc192f9..2466347baa 100644
--- a/libraries/script-engine/src/ScriptsModel.h
+++ b/libraries/script-engine/src/ScriptsModel.h
@@ -68,6 +68,9 @@ public:
* Has properties and functions below in addition to those of
* http://doc.qt.io/qt-5/qabstractitemmodel.html.
* @class ScriptsModel
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
class ScriptsModel : public QAbstractItemModel {
Q_OBJECT
diff --git a/libraries/script-engine/src/ScriptsModelFilter.h b/libraries/script-engine/src/ScriptsModelFilter.h
index 26efde02e8..05a76334bb 100644
--- a/libraries/script-engine/src/ScriptsModelFilter.h
+++ b/libraries/script-engine/src/ScriptsModelFilter.h
@@ -20,6 +20,9 @@
* Has properties and functions per
* http://doc.qt.io/qt-5/qsortfilterproxymodel.html.
* @class ScriptsModelFilter
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
class ScriptsModelFilter : public QSortFilterProxyModel {
Q_OBJECT
diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h
index 6728c471f6..f214c3f11c 100644
--- a/libraries/script-engine/src/UsersScriptingInterface.h
+++ b/libraries/script-engine/src/UsersScriptingInterface.h
@@ -18,7 +18,12 @@
/**jsdoc
* @namespace Users
- * @property {boolean} canKick - true
if the domain server allows the node or avatar to kick (ban) avatars,
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-assignment-client
+ *
+ * @property {boolean} canKick - true
if the domain server allows the node or avatar to kick (ban) avatars,
* otherwise false
. Read-only.
* @property {boolean} requestsDomainListData - true
if the avatar requests extra data from the mixers (such as
* positional data of an avatar you've ignored). Read-only.
diff --git a/libraries/script-engine/src/Vec3.h b/libraries/script-engine/src/Vec3.h
index 635f2a530c..eb9438c5c2 100644
--- a/libraries/script-engine/src/Vec3.h
+++ b/libraries/script-engine/src/Vec3.h
@@ -47,6 +47,12 @@
*
* @namespace Vec3
* @variation 0
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-server-entity
+ * @hifi-assignment-client
+ *
* @property {Vec3} UNIT_X - { x: 1, y: 0, z: 0 }
: Unit vector in the x-axis direction. Read-only.
* @property {Vec3} UNIT_Y - { x: 0, y: 1, z: 0 }
: Unit vector in the y-axis direction. Read-only.
* @property {Vec3} UNIT_Z - { x: 0, y: 0, z: 1 }
: Unit vector in the z-axis direction. Read-only.
diff --git a/libraries/shared/src/DebugDraw.h b/libraries/shared/src/DebugDraw.h
index 64327585fb..7dd19415c9 100644
--- a/libraries/shared/src/DebugDraw.h
+++ b/libraries/shared/src/DebugDraw.h
@@ -25,6 +25,11 @@
* Helper functions to render ephemeral debug markers and lines.
* DebugDraw markers and lines are only visible locally, they are not visible by other users.
* @namespace DebugDraw
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-server-entity
+ * @hifi-assignment-client
*/
class DebugDraw : public QObject {
Q_OBJECT
diff --git a/libraries/shared/src/PathUtils.h b/libraries/shared/src/PathUtils.h
index d879ac968d..fc933b6b8c 100644
--- a/libraries/shared/src/PathUtils.h
+++ b/libraries/shared/src/PathUtils.h
@@ -22,6 +22,10 @@
* The Paths API provides absolute paths to the scripts and resources directories.
*
* @namespace Paths
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @deprecated The Paths API is deprecated. Use {@link Script.resolvePath} and {@link Script.resourcesPath} instead.
* @readonly
* @property {string} defaultScripts - The path to the scripts directory. Read-only.
diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h
index 689d1a3f42..467d6374a5 100644
--- a/libraries/shared/src/RegisteredMetaTypes.h
+++ b/libraries/shared/src/RegisteredMetaTypes.h
@@ -361,6 +361,12 @@ using MeshPointer = std::shared_ptr;
/**jsdoc
* A handle for a mesh in an entity, such as returned by {@link Entities.getMeshes}.
* @class MeshProxy
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-server-entity
+ * @hifi-assignment-client
+ *
* @deprecated Use the {@link Graphics} API instead.
*/
class MeshProxy : public QObject {
diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h
index ea2e9cddab..32e753d0f9 100644
--- a/libraries/shared/src/shared/Camera.h
+++ b/libraries/shared/src/shared/Camera.h
@@ -40,6 +40,10 @@ class Camera : public QObject {
* The Camera API provides access to the "camera" that defines your view in desktop and HMD display modes.
*
* @namespace Camera
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property position {Vec3} The position of the camera. You can set this value only when the camera is in independent mode.
* @property orientation {Quat} The orientation of the camera. You can set this value only when the camera is in independent
* mode.
diff --git a/libraries/ui/src/ui/TabletScriptingInterface.h b/libraries/ui/src/ui/TabletScriptingInterface.h
index bab15fc7b6..e74b846f02 100644
--- a/libraries/ui/src/ui/TabletScriptingInterface.h
+++ b/libraries/ui/src/ui/TabletScriptingInterface.h
@@ -40,6 +40,9 @@ class OffscreenQmlSurface;
/**jsdoc
* @namespace Tablet
+ *
+ * @hifi-interface
+ * @hifi-client-entity
*/
class TabletScriptingInterface : public QObject, public Dependency {
Q_OBJECT
@@ -176,6 +179,10 @@ Q_DECLARE_METATYPE(TabletButtonsProxyModel*);
/**jsdoc
* @class TabletProxy
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {string} name - Name of this tablet. Read-only.
* @property {boolean} toolbarMode - Used to transition this tablet into and out of toolbar mode.
* When tablet is in toolbar mode, all its buttons will appear in a floating toolbar.
@@ -410,6 +417,10 @@ Q_DECLARE_METATYPE(TabletProxy*);
/**jsdoc
* @class TabletButtonProxy
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ *
* @property {Uuid} uuid - Uniquely identifies this button. Read-only.
* @property {TabletButtonProxy.ButtonProperties} properties
*/
From 5ab16302cac5a63f6ac3aa084850a145b43f4785 Mon Sep 17 00:00:00 2001
From: Atlante45
Date: Tue, 24 Apr 2018 15:09:30 -0700
Subject: [PATCH 06/51] Keep CrashpadClient around
---
interface/src/Crashpad.cpp | 25 +++++++++++--------------
1 file changed, 11 insertions(+), 14 deletions(-)
diff --git a/interface/src/Crashpad.cpp b/interface/src/Crashpad.cpp
index e39cd42d81..27b6f4b937 100644
--- a/interface/src/Crashpad.cpp
+++ b/interface/src/Crashpad.cpp
@@ -11,6 +11,8 @@
#include "Crashpad.h"
+#include
+
#include
#if HAS_CRASHPAD
@@ -20,7 +22,7 @@
#include
#include
-#include
+#include
#include
#include
@@ -28,28 +30,26 @@
#include
#include
+#include
+
using namespace crashpad;
static const std::string BACKTRACE_URL { CMAKE_BACKTRACE_URL };
static const std::string BACKTRACE_TOKEN { CMAKE_BACKTRACE_TOKEN };
-static std::wstring gIPCPipe;
-
extern QString qAppFileName();
std::mutex annotationMutex;
crashpad::SimpleStringDictionary* crashpadAnnotations { nullptr };
-#include
+
+std::unique_ptr client;
LONG WINAPI vectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) {
if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_HEAP_CORRUPTION ||
pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_BUFFER_OVERRUN) {
- CrashpadClient client;
- if (gIPCPipe.length()) {
- client.SetHandlerIPCPipe(gIPCPipe);
- }
- client.DumpAndCrash(pExceptionInfo);
+ assert(client);
+ client->DumpAndCrash(pExceptionInfo);
}
return EXCEPTION_CONTINUE_SEARCH;
@@ -60,7 +60,7 @@ bool startCrashHandler() {
return false;
}
- CrashpadClient client;
+ client.reset(new CrashpadClient());
std::vector arguments;
std::map annotations;
@@ -96,12 +96,9 @@ bool startCrashHandler() {
// Enable automated uploads.
database->GetSettings()->SetUploadsEnabled(true);
- bool result = client.StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true);
- gIPCPipe = client.GetHandlerIPCPipe();
-
AddVectoredExceptionHandler(0, vectoredExceptionHandler);
- return result;
+ return client->StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true);
}
void setCrashAnnotation(std::string name, std::string value) {
From 250806252e526889820549e6ac13ce259a340ebd Mon Sep 17 00:00:00 2001
From: Atlante45
Date: Tue, 24 Apr 2018 15:09:30 -0700
Subject: [PATCH 07/51] Don't use unique_ptr to store CrashpadClient
---
interface/src/Crashpad.cpp | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/interface/src/Crashpad.cpp b/interface/src/Crashpad.cpp
index 27b6f4b937..45f1d0778f 100644
--- a/interface/src/Crashpad.cpp
+++ b/interface/src/Crashpad.cpp
@@ -39,16 +39,17 @@ static const std::string BACKTRACE_TOKEN { CMAKE_BACKTRACE_TOKEN };
extern QString qAppFileName();
+CrashpadClient* client { nullptr };
std::mutex annotationMutex;
crashpad::SimpleStringDictionary* crashpadAnnotations { nullptr };
-
-std::unique_ptr client;
-
LONG WINAPI vectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) {
+ if (!client) {
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_HEAP_CORRUPTION ||
pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_BUFFER_OVERRUN) {
- assert(client);
client->DumpAndCrash(pExceptionInfo);
}
@@ -60,7 +61,8 @@ bool startCrashHandler() {
return false;
}
- client.reset(new CrashpadClient());
+ assert(!client);
+ client = new CrashpadClient();
std::vector arguments;
std::map annotations;
From 73cea112eefa7541a05394426f74e0652cb07efb Mon Sep 17 00:00:00 2001
From: Ryan Huffman
Date: Thu, 26 Apr 2018 15:49:34 -0700
Subject: [PATCH 08/51] Update FilePersistThread to use std::chrono instead of
usecTimestampNow
---
libraries/shared/src/shared/FileLogger.cpp | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/libraries/shared/src/shared/FileLogger.cpp b/libraries/shared/src/shared/FileLogger.cpp
index 4f4a9ab6dd..1e17ee9e7c 100644
--- a/libraries/shared/src/shared/FileLogger.cpp
+++ b/libraries/shared/src/shared/FileLogger.cpp
@@ -44,7 +44,7 @@ static const QString DATETIME_FORMAT = "yyyy-MM-dd_hh.mm.ss";
static const QString LOGS_DIRECTORY = "Logs";
static const QString DATETIME_WILDCARD = "20[0-9][0-9]-[01][0-9]-[0-3][0-9]_[0-2][0-9]\\.[0-6][0-9]\\.[0-6][0-9]";
static const QString SESSION_WILDCARD = "[0-9a-z]{8}(-[0-9a-z]{4}){3}-[0-9a-z]{12}";
-static QRegExp LOG_FILENAME_REGEX { "hifi-log_" + DATETIME_WILDCARD + "(_" + SESSION_WILDCARD + ")?\.txt" };
+static QRegExp LOG_FILENAME_REGEX { "hifi-log_" + DATETIME_WILDCARD + "(_" + SESSION_WILDCARD + ")?\\.txt" };
static QUuid SESSION_ID;
// Max log size is 512 KB. We send log files to our crash reporter, so we want to keep this relatively
@@ -52,8 +52,7 @@ static QUuid SESSION_ID;
static const qint64 MAX_LOG_SIZE = 512 * 1024;
// Max log files found in the log directory is 100.
static const qint64 MAX_LOG_DIR_SIZE = 512 * 1024 * 100;
-// Max log age is 1 hour
-static const uint64_t MAX_LOG_AGE_USECS = USECS_PER_SECOND * 3600;
+static const std::chrono::minutes MAX_LOG_AGE { 60 };
static FilePersistThread* _persistThreadInstance;
@@ -84,23 +83,22 @@ FilePersistThread::FilePersistThread(const FileLogger& logger) : _logger(logger)
if (file.exists()) {
rollFileIfNecessary(file, false);
}
- _lastRollTime = usecTimestampNow();
+ _lastRollTime = std::chrono::system_clock::now();
}
void FilePersistThread::rollFileIfNecessary(QFile& file, bool notifyListenersIfRolled) {
- uint64_t now = usecTimestampNow();
- if ((file.size() > MAX_LOG_SIZE) || (now - _lastRollTime) > MAX_LOG_AGE_USECS) {
+ auto now = std::chrono::system_clock::now();
+ if ((file.size() > MAX_LOG_SIZE) || (now - _lastRollTime) > MAX_LOG_AGE) {
QString newFileName = getLogRollerFilename();
if (file.copy(newFileName)) {
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
file.close();
- qCDebug(shared) << "Rolled log file:" << newFileName;
if (notifyListenersIfRolled) {
emit rollingLogFile(newFileName);
}
- _lastRollTime = now;
+ _lastRollTime = std::chrono::system_clock::now();
}
QDir logDir(FileUtils::standardPath(LOGS_DIRECTORY));
@@ -128,7 +126,7 @@ bool FilePersistThread::processQueueItems(const Queue& messages) {
rollFileIfNecessary(file);
if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
QTextStream out(&file);
- foreach(const QString& message, messages) {
+ for (const QString& message : messages) {
out << message;
}
}
From f3fe1f3e58386363ddb2e2b5a48e5a08bd73f4c3 Mon Sep 17 00:00:00 2001
From: Clement
Date: Mon, 30 Apr 2018 13:51:53 -0700
Subject: [PATCH 09/51] Force crash helpers not inlined
---
libraries/shared/src/CrashHelpers.cpp | 77 +++++++++++++++++++++++++++
libraries/shared/src/CrashHelpers.h | 66 +++--------------------
2 files changed, 83 insertions(+), 60 deletions(-)
create mode 100644 libraries/shared/src/CrashHelpers.cpp
diff --git a/libraries/shared/src/CrashHelpers.cpp b/libraries/shared/src/CrashHelpers.cpp
new file mode 100644
index 0000000000..f8ca90bc4c
--- /dev/null
+++ b/libraries/shared/src/CrashHelpers.cpp
@@ -0,0 +1,77 @@
+//
+// CrashHelpers.cpp
+// libraries/shared/src
+//
+// Created by Clement Brisset on 4/30/18.
+// Copyright 2018 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 "CrashHelpers.h"
+
+namespace crash {
+
+class B;
+class A {
+public:
+ A(B* b) : _b(b) { }
+ ~A();
+ virtual void virtualFunction() = 0;
+
+private:
+ B* _b;
+};
+
+class B : public A {
+public:
+ B() : A(this) { }
+ virtual void virtualFunction() override { }
+};
+
+A::~A() {
+ _b->virtualFunction();
+}
+
+void pureVirtualCall() {
+ qCDebug(shared) << "About to make a pure virtual call";
+ B b;
+}
+
+void doubleFree() {
+ qCDebug(shared) << "About to double delete memory";
+ int* blah = new int(200);
+ delete blah;
+ delete blah;
+}
+
+void nullDeref() {
+ qCDebug(shared) << "About to dereference a null pointer";
+ int* p = nullptr;
+ *p = 1;
+}
+
+void doAbort() {
+ qCDebug(shared) << "About to abort";
+ abort();
+}
+
+void outOfBoundsVectorCrash() {
+ qCDebug(shared) << "std::vector out of bounds crash!";
+ std::vector v;
+ v[0] = 42;
+}
+
+void newFault() {
+ qCDebug(shared) << "About to crash inside new fault";
+
+ // Force crash with multiple large allocations
+ while (true) {
+ const size_t GIGABYTE = 1024 * 1024 * 1024;
+ new char[GIGABYTE];
+ }
+
+}
+
+}
diff --git a/libraries/shared/src/CrashHelpers.h b/libraries/shared/src/CrashHelpers.h
index 1cc6749182..ad988c8906 100644
--- a/libraries/shared/src/CrashHelpers.h
+++ b/libraries/shared/src/CrashHelpers.h
@@ -18,66 +18,12 @@
namespace crash {
-class B;
-class A {
-public:
- A(B* b) : _b(b) { }
- ~A();
- virtual void virtualFunction() = 0;
-
-private:
- B* _b;
-};
-
-class B : public A {
-public:
- B() : A(this) { }
- virtual void virtualFunction() override { }
-};
-
-A::~A() {
- _b->virtualFunction();
-}
-
-void pureVirtualCall() {
- qCDebug(shared) << "About to make a pure virtual call";
- B b;
-}
-
-void doubleFree() {
- qCDebug(shared) << "About to double delete memory";
- int* blah = new int(200);
- delete blah;
- delete blah;
-}
-
-void nullDeref() {
- qCDebug(shared) << "About to dereference a null pointer";
- int* p = nullptr;
- *p = 1;
-}
-
-void doAbort() {
- qCDebug(shared) << "About to abort";
- abort();
-}
-
-void outOfBoundsVectorCrash() {
- qCDebug(shared) << "std::vector out of bounds crash!";
- std::vector v;
- v[0] = 42;
-}
-
-void newFault() {
- qCDebug(shared) << "About to crash inside new fault";
-
- // Force crash with multiple large allocations
- while (true) {
- const size_t GIGABYTE = 1024 * 1024 * 1024;
- new char[GIGABYTE];
- }
-
-}
+void pureVirtualCall();
+void doubleFree();
+void nullDeref();
+void doAbort();
+void outOfBoundsVectorCrash();
+void newFault();
}
From 0653f49efe1b2ff75c4f8ad7ef4045d89b2c02f4 Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Wed, 2 May 2018 09:31:24 +1200
Subject: [PATCH 10/51] Remove deprecated location.domainId from API
location.domainID is available, instead.
---
libraries/networking/src/AddressManager.h | 3 ---
1 file changed, 3 deletions(-)
diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h
index 94eff46bda..95bf0c18a8 100644
--- a/libraries/networking/src/AddressManager.h
+++ b/libraries/networking/src/AddressManager.h
@@ -36,8 +36,6 @@ const QString GET_PLACE = "/api/v1/places/%1";
* @property {Uuid} domainID - A UUID uniquely identifying the domain you're visiting. Is {@link Uuid|Uuid.NULL} if you're not
* connected to the domain or are in a serverless domain.
* Read-only.
- * @property {Uuid} domainId - Synonym for domainId
. Read-only. Deprecated: This property
- * is deprecated and will soon be removed.
* @property {string} hostname - The name of the domain for your current metaverse address (e.g., "AvatarIsland"
,
* localhost
, or an IP address). Is blank if you're in a serverless domain.
* Read-only.
@@ -68,7 +66,6 @@ class AddressManager : public QObject, public Dependency {
Q_PROPERTY(QString pathname READ currentPath)
Q_PROPERTY(QString placename READ getPlaceName)
Q_PROPERTY(QString domainID READ getDomainID)
- Q_PROPERTY(QString domainId READ getDomainID)
public:
using PositionGetter = std::function;
using OrientationGetter = std::function;
From 49fad3d8685dc7a5d430b27574ee4b7525d0c7d8 Mon Sep 17 00:00:00 2001
From: Clement
Date: Fri, 13 Apr 2018 18:01:54 -0700
Subject: [PATCH 11/51] EntityServer traversal aware of all ViewFrustums
---
.../src/entities/EntityPriorityQueue.cpp | 23 +++-
.../src/entities/EntityPriorityQueue.h | 16 ++-
.../src/entities/EntityTreeSendThread.cpp | 100 +++++++--------
.../src/entities/EntityTreeSendThread.h | 3 +-
.../src/octree/OctreeHeadlessViewer.cpp | 9 +-
.../src/octree/OctreeSendThread.cpp | 6 +-
.../src/scripts/EntityScriptServer.cpp | 1 -
interface/src/Application.cpp | 10 +-
libraries/entities/src/DiffTraversal.cpp | 121 +++++++++++++-----
libraries/entities/src/DiffTraversal.h | 20 +--
libraries/octree/src/Octree.h | 1 -
libraries/octree/src/OctreeQuery.cpp | 107 +++++++---------
libraries/octree/src/OctreeQuery.h | 63 +++------
libraries/octree/src/OctreeQueryNode.cpp | 111 +++++++---------
libraries/octree/src/OctreeQueryNode.h | 9 +-
libraries/octree/src/OctreeUtils.cpp | 9 +-
libraries/octree/src/OctreeUtils.h | 3 +
libraries/shared/src/ViewFrustum.cpp | 4 +-
libraries/shared/src/ViewFrustum.h | 2 +-
19 files changed, 322 insertions(+), 296 deletions(-)
diff --git a/assignment-client/src/entities/EntityPriorityQueue.cpp b/assignment-client/src/entities/EntityPriorityQueue.cpp
index 999a05f2e2..a38d537649 100644
--- a/assignment-client/src/entities/EntityPriorityQueue.cpp
+++ b/assignment-client/src/entities/EntityPriorityQueue.cpp
@@ -15,7 +15,7 @@ const float PrioritizedEntity::DO_NOT_SEND = -1.0e-6f;
const float PrioritizedEntity::FORCE_REMOVE = -1.0e-5f;
const float PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY = 1.0f;
-void ConicalView::set(const ViewFrustum& viewFrustum) {
+void ConicalViewFrustum::set(const ViewFrustum& viewFrustum) {
// The ConicalView has two parts: a central sphere (same as ViewFrustum) and a circular cone that bounds the frustum part.
// Why? Because approximate intersection tests are much faster to compute for a cone than for a frustum.
_position = viewFrustum.getPosition();
@@ -31,7 +31,7 @@ void ConicalView::set(const ViewFrustum& viewFrustum) {
_radius = viewFrustum.getCenterRadius();
}
-float ConicalView::computePriority(const AACube& cube) const {
+float ConicalViewFrustum::computePriority(const AACube& cube) const {
glm::vec3 p = cube.calcCenter() - _position; // position of bounding sphere in view-frame
float d = glm::length(p); // distance to center of bounding sphere
float r = 0.5f * cube.getScale(); // radius of bounding sphere
@@ -51,3 +51,22 @@ float ConicalView::computePriority(const AACube& cube) const {
}
return PrioritizedEntity::DO_NOT_SEND;
}
+
+
+void ConicalView::set(const DiffTraversal::View& view) {
+ auto size = view.viewFrustums.size();
+ _conicalViewFrustums.resize(size);
+ for (size_t i = 0; i < size; ++i) {
+ _conicalViewFrustums[i].set(view.viewFrustums[i]);
+ }
+}
+
+float ConicalView::computePriority(const AACube& cube) const {
+ float priority = PrioritizedEntity::DO_NOT_SEND;
+
+ for (const auto& view : _conicalViewFrustums) {
+ priority = std::max(priority, view.computePriority(cube));
+ }
+
+ return priority;
+}
diff --git a/assignment-client/src/entities/EntityPriorityQueue.h b/assignment-client/src/entities/EntityPriorityQueue.h
index e308d9b549..4068b4dc4b 100644
--- a/assignment-client/src/entities/EntityPriorityQueue.h
+++ b/assignment-client/src/entities/EntityPriorityQueue.h
@@ -15,16 +15,17 @@
#include
#include
+#include
#include
const float SQRT_TWO_OVER_TWO = 0.7071067811865f;
const float DEFAULT_VIEW_RADIUS = 10.0f;
// ConicalView is an approximation of a ViewFrustum for fast calculation of sort priority.
-class ConicalView {
+class ConicalViewFrustum {
public:
- ConicalView() {}
- ConicalView(const ViewFrustum& viewFrustum) { set(viewFrustum); }
+ ConicalViewFrustum() {}
+ ConicalViewFrustum(const ViewFrustum& viewFrustum) { set(viewFrustum); }
void set(const ViewFrustum& viewFrustum);
float computePriority(const AACube& cube) const;
private:
@@ -35,6 +36,15 @@ private:
float _radius { DEFAULT_VIEW_RADIUS };
};
+class ConicalView {
+public:
+ ConicalView() {}
+ void set(const DiffTraversal::View& view);
+ float computePriority(const AACube& cube) const;
+private:
+ std::vector _conicalViewFrustums;
+};
+
// PrioritizedEntity is a placeholder in a sorted queue.
class PrioritizedEntity {
public:
diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp
index 4aa52922c0..d14d31bd09 100644
--- a/assignment-client/src/entities/EntityTreeSendThread.cpp
+++ b/assignment-client/src/entities/EntityTreeSendThread.cpp
@@ -103,11 +103,25 @@ void EntityTreeSendThread::preDistributionProcessing() {
void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
bool viewFrustumChanged, bool isFullScene) {
if (viewFrustumChanged || _traversal.finished()) {
- ViewFrustum viewFrustum;
- nodeData->copyCurrentViewFrustum(viewFrustum);
EntityTreeElementPointer root = std::dynamic_pointer_cast(_myServer->getOctree()->getRoot());
+
+
+ DiffTraversal::View newView;
+
+ ViewFrustum viewFrustum;
+ if (nodeData->hasMainViewFrustum()) {
+ nodeData->copyCurrentMainViewFrustum(viewFrustum);
+ newView.viewFrustums.push_back(viewFrustum);
+ }
+ if (nodeData->hasSecondaryViewFrustum()) {
+ nodeData->copyCurrentSecondaryViewFrustum(viewFrustum);
+ newView.viewFrustums.push_back(viewFrustum);
+ }
+
int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
- startNewTraversal(viewFrustum, root, lodLevelOffset, nodeData->getUsesFrustum());
+ newView.lodScaleFactor = powf(2.0f, lodLevelOffset);
+
+ startNewTraversal(newView, root);
// 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
@@ -116,8 +130,6 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
_sendQueue.swap(prevSendQueue);
_entitiesInQueue.clear();
// Re-add elements from previous traversal if they still need to be sent
- float lodScaleFactor = _traversal.getCurrentLODScaleFactor();
- glm::vec3 viewPosition = _traversal.getCurrentView().getPosition();
while (!prevSendQueue.empty()) {
EntityItemPointer entity = prevSendQueue.top().getEntity();
bool forceRemove = prevSendQueue.top().shouldForceRemove();
@@ -127,12 +139,10 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
bool success = false;
AACube cube = entity->getQueryAACube(success);
if (success) {
- if (_traversal.getCurrentView().cubeIntersectsKeyhole(cube)) {
+ if (_traversal.getCurrentView().intersects(cube)) {
float priority = _conicalView.computePriority(cube);
if (priority != PrioritizedEntity::DO_NOT_SEND) {
- float distance = glm::distance(cube.calcCenter(), viewPosition) + MIN_VISIBLE_DISTANCE;
- float angularDiameter = cube.getScale() / distance;
- if (angularDiameter > MIN_ENTITY_ANGULAR_DIAMETER * lodScaleFactor) {
+ if (_traversal.getCurrentView().isBigEnough(cube)) {
_sendQueue.push(PrioritizedEntity(entity, priority));
_entitiesInQueue.insert(entity.get());
}
@@ -215,10 +225,9 @@ bool EntityTreeSendThread::addDescendantsToExtraFlaggedEntities(const QUuid& fil
return hasNewChild || hasNewDescendants;
}
-void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root, int32_t lodLevelOffset,
- bool usesViewFrustum) {
+void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root) {
- DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset, usesViewFrustum);
+ DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root);
// there are three types of traversal:
//
// (1) FirstTime = at login --> find everything in view
@@ -236,11 +245,9 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
case DiffTraversal::First:
// When we get to a First traversal, clear the _knownState
_knownState.clear();
- if (usesViewFrustum) {
- float lodScaleFactor = _traversal.getCurrentLODScaleFactor();
- glm::vec3 viewPosition = _traversal.getCurrentView().getPosition();
- _traversal.setScanCallback([=](DiffTraversal::VisibleElement& next) {
- next.element->forEachEntity([=](EntityItemPointer entity) {
+ if (view.usesViewFrustums()) {
+ _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
+ next.element->forEachEntity([&](EntityItemPointer entity) {
// Bail early if we've already checked this entity this frame
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
return;
@@ -248,14 +255,12 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
bool success = false;
AACube cube = entity->getQueryAACube(success);
if (success) {
- if (_traversal.getCurrentView().cubeIntersectsKeyhole(cube)) {
+ if (_traversal.getCurrentView().intersects(cube)) {
// Check the size of the entity, it's possible that a "too small to see" entity is included in a
// larger octree cell because of its position (for example if it crosses the boundary of a cell it
// pops to the next higher cell. So we want to check to see that the entity is large enough to be seen
// before we consider including it.
- float distance = glm::distance(cube.calcCenter(), viewPosition) + MIN_VISIBLE_DISTANCE;
- float angularDiameter = cube.getScale() / distance;
- if (angularDiameter > MIN_ENTITY_ANGULAR_DIAMETER * lodScaleFactor) {
+ if (_traversal.getCurrentView().isBigEnough(cube)) {
float priority = _conicalView.computePriority(cube);
_sendQueue.push(PrioritizedEntity(entity, priority));
_entitiesInQueue.insert(entity.get());
@@ -269,7 +274,7 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
});
} else {
_traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
- next.element->forEachEntity([this](EntityItemPointer entity) {
+ next.element->forEachEntity([&](EntityItemPointer entity) {
// Bail early if we've already checked this entity this frame
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
return;
@@ -281,13 +286,11 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
}
break;
case DiffTraversal::Repeat:
- if (usesViewFrustum) {
- float lodScaleFactor = _traversal.getCurrentLODScaleFactor();
- glm::vec3 viewPosition = _traversal.getCurrentView().getPosition();
- _traversal.setScanCallback([=](DiffTraversal::VisibleElement& next) {
+ if (view.usesViewFrustums()) {
+ _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
uint64_t startOfCompletedTraversal = _traversal.getStartOfCompletedTraversal();
if (next.element->getLastChangedContent() > startOfCompletedTraversal) {
- next.element->forEachEntity([=](EntityItemPointer entity) {
+ next.element->forEachEntity([&](EntityItemPointer entity) {
// Bail early if we've already checked this entity this frame
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
return;
@@ -297,11 +300,10 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
bool success = false;
AACube cube = entity->getQueryAACube(success);
if (success) {
- if (next.intersection == ViewFrustum::INSIDE || _traversal.getCurrentView().cubeIntersectsKeyhole(cube)) {
+ if (next.intersection == ViewFrustum::INSIDE ||
+ _traversal.getCurrentView().intersects(cube)) {
// See the DiffTraversal::First case for an explanation of the "entity is too small" check
- float distance = glm::distance(cube.calcCenter(), viewPosition) + MIN_VISIBLE_DISTANCE;
- float angularDiameter = cube.getScale() / distance;
- if (angularDiameter > MIN_ENTITY_ANGULAR_DIAMETER * lodScaleFactor) {
+ if (_traversal.getCurrentView().isBigEnough(cube)) {
float priority = _conicalView.computePriority(cube);
_sendQueue.push(PrioritizedEntity(entity, priority));
_entitiesInQueue.insert(entity.get());
@@ -325,7 +327,7 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
_traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
uint64_t startOfCompletedTraversal = _traversal.getStartOfCompletedTraversal();
if (next.element->getLastChangedContent() > startOfCompletedTraversal) {
- next.element->forEachEntity([this](EntityItemPointer entity) {
+ next.element->forEachEntity([&](EntityItemPointer entity) {
// Bail early if we've already checked this entity this frame
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
return;
@@ -343,13 +345,9 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
}
break;
case DiffTraversal::Differential:
- assert(usesViewFrustum);
- float lodScaleFactor = _traversal.getCurrentLODScaleFactor();
- glm::vec3 viewPosition = _traversal.getCurrentView().getPosition();
- float completedLODScaleFactor = _traversal.getCompletedLODScaleFactor();
- glm::vec3 completedViewPosition = _traversal.getCompletedView().getPosition();
- _traversal.setScanCallback([=] (DiffTraversal::VisibleElement& next) {
- next.element->forEachEntity([=](EntityItemPointer entity) {
+ assert(view.usesViewFrustums());
+ _traversal.setScanCallback([this] (DiffTraversal::VisibleElement& next) {
+ next.element->forEachEntity([&](EntityItemPointer entity) {
// Bail early if we've already checked this entity this frame
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
return;
@@ -359,25 +357,19 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
bool success = false;
AACube cube = entity->getQueryAACube(success);
if (success) {
- if (_traversal.getCurrentView().cubeIntersectsKeyhole(cube)) {
+ if (_traversal.getCurrentView().intersects(cube)) {
// See the DiffTraversal::First case for an explanation of the "entity is too small" check
- float distance = glm::distance(cube.calcCenter(), viewPosition) + MIN_VISIBLE_DISTANCE;
- float angularDiameter = cube.getScale() / distance;
- if (angularDiameter > MIN_ENTITY_ANGULAR_DIAMETER * lodScaleFactor) {
- if (!_traversal.getCompletedView().cubeIntersectsKeyhole(cube)) {
+ if (_traversal.getCurrentView().isBigEnough(cube)) {
+ if (!_traversal.getCompletedView().intersects(cube)) {
float priority = _conicalView.computePriority(cube);
_sendQueue.push(PrioritizedEntity(entity, priority));
_entitiesInQueue.insert(entity.get());
- } else {
+ } else if (!_traversal.getCompletedView().isBigEnough(cube)) {
// If this entity was skipped last time because it was too small, we still need to send it
- distance = glm::distance(cube.calcCenter(), completedViewPosition) + MIN_VISIBLE_DISTANCE;
- angularDiameter = cube.getScale() / distance;
- if (angularDiameter <= MIN_ENTITY_ANGULAR_DIAMETER * completedLODScaleFactor) {
- // this object was skipped in last completed traversal
- float priority = _conicalView.computePriority(cube);
- _sendQueue.push(PrioritizedEntity(entity, priority));
- _entitiesInQueue.insert(entity.get());
- }
+ // this object was skipped in last completed traversal
+ float priority = _conicalView.computePriority(cube);
+ _sendQueue.push(PrioritizedEntity(entity, priority));
+ _entitiesInQueue.insert(entity.get());
}
}
}
@@ -506,7 +498,7 @@ void EntityTreeSendThread::editingEntityPointer(const EntityItemPointer& entity)
AACube cube = entity->getQueryAACube(success);
if (success) {
// We can force a removal from _knownState if the current view is used and entity is out of view
- if (_traversal.doesCurrentUseViewFrustum() && !_traversal.getCurrentView().cubeIntersectsKeyhole(cube)) {
+ if (_traversal.doesCurrentUseViewFrustum() && !_traversal.getCurrentView().intersects(cube)) {
_sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::FORCE_REMOVE, true));
_entitiesInQueue.insert(entity.get());
}
diff --git a/assignment-client/src/entities/EntityTreeSendThread.h b/assignment-client/src/entities/EntityTreeSendThread.h
index 1e2bd15429..5ea723c8b2 100644
--- a/assignment-client/src/entities/EntityTreeSendThread.h
+++ b/assignment-client/src/entities/EntityTreeSendThread.h
@@ -41,8 +41,7 @@ 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 DiffTraversal::View& viewFrustum, EntityTreeElementPointer root);
bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override;
void preDistributionProcessing() override;
diff --git a/assignment-client/src/octree/OctreeHeadlessViewer.cpp b/assignment-client/src/octree/OctreeHeadlessViewer.cpp
index d3b20fb623..4f022ae838 100644
--- a/assignment-client/src/octree/OctreeHeadlessViewer.cpp
+++ b/assignment-client/src/octree/OctreeHeadlessViewer.cpp
@@ -23,14 +23,7 @@ void OctreeHeadlessViewer::queryOctree() {
char serverType = getMyNodeType();
PacketType packetType = getMyQueryMessageType();
- _octreeQuery.setCameraPosition(_viewFrustum.getPosition());
- _octreeQuery.setCameraOrientation(_viewFrustum.getOrientation());
- _octreeQuery.setCameraFov(_viewFrustum.getFieldOfView());
- _octreeQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio());
- _octreeQuery.setCameraNearClip(_viewFrustum.getNearClip());
- _octreeQuery.setCameraFarClip(_viewFrustum.getFarClip());
- _octreeQuery.setCameraEyeOffsetPosition(glm::vec3());
- _octreeQuery.setCameraCenterRadius(_viewFrustum.getCenterRadius());
+ _octreeQuery.setMainViewFrustum(_viewFrustum);
_octreeQuery.setOctreeSizeScale(_voxelSizeScale);
_octreeQuery.setBoundaryLevelAdjust(_boundaryLevelAdjust);
diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp
index de49bd461c..40c052659d 100644
--- a/assignment-client/src/octree/OctreeSendThread.cpp
+++ b/assignment-client/src/octree/OctreeSendThread.cpp
@@ -330,8 +330,9 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
} else {
// we aren't forcing a full scene, check if something else suggests we should
isFullScene = nodeData->haveJSONParametersChanged() ||
- (nodeData->getUsesFrustum()
- && ((!viewFrustumChanged && nodeData->getViewFrustumJustStoppedChanging()) || nodeData->hasLodChanged()));
+ (nodeData->hasMainViewFrustum() &&
+ (nodeData->getViewFrustumJustStoppedChanging() ||
+ nodeData->hasLodChanged()));
}
if (nodeData->isPacketWaiting()) {
@@ -445,7 +446,6 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre
params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) {
_myServer->trackSend(dataID, dataEdited, _nodeUuid);
};
- nodeData->copyCurrentViewFrustum(params.viewFrustum);
bool somethingToSend = true; // assume we have something
bool hadSomething = hasSomethingToSend(nodeData);
diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp
index d242b393bf..eea8e8b470 100644
--- a/assignment-client/src/scripts/EntityScriptServer.cpp
+++ b/assignment-client/src/scripts/EntityScriptServer.cpp
@@ -294,7 +294,6 @@ void EntityScriptServer::run() {
queryJSONParameters[EntityJSONQueryProperties::FLAGS_PROPERTY] = queryFlags;
// setup the JSON parameters so that OctreeQuery does not use a frustum and uses our JSON filter
- _entityViewer.getOctreeQuery().setUsesFrustum(false);
_entityViewer.getOctreeQuery().setJSONParameters(queryJSONParameters);
entityScriptingInterface->setEntityTree(_entityViewer.getTree());
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index cd4562da54..d1d44aa706 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -5791,14 +5791,8 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType) {
ViewFrustum viewFrustum;
copyViewFrustum(viewFrustum);
- _octreeQuery.setCameraPosition(viewFrustum.getPosition());
- _octreeQuery.setCameraOrientation(viewFrustum.getOrientation());
- _octreeQuery.setCameraFov(viewFrustum.getFieldOfView());
- _octreeQuery.setCameraAspectRatio(viewFrustum.getAspectRatio());
- _octreeQuery.setCameraNearClip(viewFrustum.getNearClip());
- _octreeQuery.setCameraFarClip(viewFrustum.getFarClip());
- _octreeQuery.setCameraEyeOffsetPosition(glm::vec3());
- _octreeQuery.setCameraCenterRadius(viewFrustum.getCenterRadius());
+ _octreeQuery.setMainViewFrustum(viewFrustum);
+
auto lodManager = DependencyManager::get();
_octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale());
_octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust());
diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp
index 764c420197..11f37728df 100644
--- a/libraries/entities/src/DiffTraversal.cpp
+++ b/libraries/entities/src/DiffTraversal.cpp
@@ -37,15 +37,14 @@ void DiffTraversal::Waypoint::getNextVisibleElementFirstTime(DiffTraversal::Visi
EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex);
++_nextIndex;
if (nextElement) {
- if (!view.usesViewFrustum) {
+ const auto& cube = nextElement->getAACube();
+ if (!view.usesViewFrustums()) {
// No LOD truncation if we aren't using the view frustum
next.element = nextElement;
return;
- } else if (view.viewFrustum.cubeIntersectsKeyhole(nextElement->getAACube())) {
+ } else if (view.intersects(cube)) {
// check for LOD truncation
- float distance = glm::distance(view.viewFrustum.getPosition(), nextElement->getAACube().calcCenter()) + MIN_VISIBLE_DISTANCE;
- float angularDiameter = nextElement->getAACube().getScale() / distance;
- if (angularDiameter > MIN_ELEMENT_ANGULAR_DIAMETER * view.lodScaleFactor) {
+ if (view.isBigEnough(cube, MIN_ELEMENT_ANGULAR_DIAMETER)) {
next.element = nextElement;
return;
}
@@ -76,17 +75,16 @@ void DiffTraversal::Waypoint::getNextVisibleElementRepeat(
EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex);
++_nextIndex;
if (nextElement && nextElement->getLastChanged() > lastTime) {
- if (!view.usesViewFrustum) {
+ if (!view.usesViewFrustums()) {
// No LOD truncation if we aren't using the view frustum
next.element = nextElement;
next.intersection = ViewFrustum::INSIDE;
return;
} else {
// check for LOD truncation
- float distance = glm::distance(view.viewFrustum.getPosition(), nextElement->getAACube().calcCenter()) + MIN_VISIBLE_DISTANCE;
- float angularDiameter = nextElement->getAACube().getScale() / distance;
- if (angularDiameter > MIN_ELEMENT_ANGULAR_DIAMETER * view.lodScaleFactor) {
- ViewFrustum::intersection intersection = view.viewFrustum.calculateCubeKeyholeIntersection(nextElement->getAACube());
+ const auto& cube = nextElement->getAACube();
+ if (view.isBigEnough(cube, MIN_ELEMENT_ANGULAR_DIAMETER)) {
+ ViewFrustum::intersection intersection = view.calculateIntersection(cube);
if (intersection != ViewFrustum::OUTSIDE) {
next.element = nextElement;
next.intersection = intersection;
@@ -118,14 +116,13 @@ void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::V
EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex);
++_nextIndex;
if (nextElement) {
- AACube cube = nextElement->getAACube();
// check for LOD truncation
- float distance = glm::distance(view.viewFrustum.getPosition(), cube.calcCenter()) + MIN_VISIBLE_DISTANCE;
- float angularDiameter = cube.getScale() / distance;
- if (angularDiameter > MIN_ELEMENT_ANGULAR_DIAMETER * view.lodScaleFactor) {
- if (view.viewFrustum.calculateCubeKeyholeIntersection(cube) != ViewFrustum::OUTSIDE) {
+ const auto& cube = nextElement->getAACube();
+ if (view.isBigEnough(cube, MIN_ELEMENT_ANGULAR_DIAMETER)) {
+ ViewFrustum::intersection intersection = view.calculateIntersection(cube);
+ if (intersection != ViewFrustum::OUTSIDE) {
next.element = nextElement;
- next.intersection = ViewFrustum::OUTSIDE;
+ next.intersection = intersection;
return;
}
}
@@ -137,13 +134,83 @@ void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::V
next.intersection = ViewFrustum::OUTSIDE;
}
+bool DiffTraversal::View::isBigEnough(const AACube& cube, float minDiameter) const {
+ if (viewFrustums.empty()) {
+ // Everything is big enough when not using view frustums
+ return true;
+ }
+
+ for (const auto& viewFrustum : viewFrustums) {
+ if (isAngularSizeBigEnough(viewFrustum.getPosition(), cube, lodScaleFactor, minDiameter)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool DiffTraversal::View::intersects(const AACube& cube) const {
+ if (viewFrustums.empty()) {
+ // Everything intersects when not using view frustums
+ return true;
+ }
+
+ for (const auto& viewFrustum : viewFrustums) {
+ if (viewFrustum.cubeIntersectsKeyhole(cube)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+ViewFrustum::intersection DiffTraversal::View::calculateIntersection(const AACube& cube) const {
+ if (viewFrustums.empty()) {
+ // Everything is inside when not using view frustums
+ return ViewFrustum::INSIDE;
+ }
+
+ ViewFrustum::intersection intersection = ViewFrustum::OUTSIDE;
+
+ for (const auto& viewFrustum : viewFrustums) {
+ switch (viewFrustum.calculateCubeKeyholeIntersection(cube)) {
+ case ViewFrustum::INSIDE:
+ return ViewFrustum::INSIDE;
+ case ViewFrustum::INTERSECT:
+ intersection = ViewFrustum::INTERSECT;
+ break;
+ default:
+ // DO NOTHING
+ break;
+ }
+ }
+ return intersection;
+}
+
+bool DiffTraversal::View::usesViewFrustums() const {
+ return !viewFrustums.empty();
+}
+
+bool DiffTraversal::View::isVerySimilar(const View& view) const {
+ auto size = view.viewFrustums.size();
+
+ if (view.lodScaleFactor != lodScaleFactor ||
+ viewFrustums.size() != size) {
+ return false;
+ }
+
+ for (size_t i = 0; i < size; ++i) {
+ if (!viewFrustums[i].isVerySimilar(view.viewFrustums[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
DiffTraversal::DiffTraversal() {
const int32_t MIN_PATH_DEPTH = 16;
_path.reserve(MIN_PATH_DEPTH);
}
-DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root,
- int32_t lodLevelOffset, bool usesViewFrustum) {
+DiffTraversal::Type DiffTraversal::prepareNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root) {
assert(root);
// there are three types of traversal:
//
@@ -155,33 +222,29 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFr
//
// _getNextVisibleElementCallback = identifies elements that need to be traversed,
// updates VisibleElement ref argument with pointer-to-element and view-intersection
- // (INSIDE, INTERSECT, or OUTSIDE)
+ // (INSIDE, INTERSECtT, or OUTSIDE)
//
// external code should update the _scanElementCallback after calling prepareNewTraversal
//
- _currentView.usesViewFrustum = usesViewFrustum;
- float lodScaleFactor = powf(2.0f, lodLevelOffset);
Type type;
// If usesViewFrustum changes, treat it as a First traversal
- if (_completedView.startTime == 0 || _currentView.usesViewFrustum != _completedView.usesViewFrustum) {
+ if (_completedView.startTime == 0 || _currentView.usesViewFrustums() != _completedView.usesViewFrustums()) {
type = Type::First;
- _currentView.viewFrustum = viewFrustum;
- _currentView.lodScaleFactor = lodScaleFactor;
+ _currentView.viewFrustums = std::move(view.viewFrustums);
+ _currentView.lodScaleFactor = view.lodScaleFactor;
_getNextVisibleElementCallback = [this](DiffTraversal::VisibleElement& next) {
_path.back().getNextVisibleElementFirstTime(next, _currentView);
};
- } else if (!_currentView.usesViewFrustum ||
- (_completedView.viewFrustum.isVerySimilar(viewFrustum) &&
- lodScaleFactor == _completedView.lodScaleFactor)) {
+ } else if (!_currentView.usesViewFrustums() || _completedView.isVerySimilar(view)) {
type = Type::Repeat;
_getNextVisibleElementCallback = [this](DiffTraversal::VisibleElement& next) {
_path.back().getNextVisibleElementRepeat(next, _completedView, _completedView.startTime);
};
} else {
type = Type::Differential;
- _currentView.viewFrustum = viewFrustum;
- _currentView.lodScaleFactor = lodScaleFactor;
+ _currentView.viewFrustums = std::move(view.viewFrustums);
+ _currentView.lodScaleFactor = view.lodScaleFactor;
_getNextVisibleElementCallback = [this](DiffTraversal::VisibleElement& next) {
_path.back().getNextVisibleElementDifferential(next, _currentView, _completedView);
};
diff --git a/libraries/entities/src/DiffTraversal.h b/libraries/entities/src/DiffTraversal.h
index 69431d8db5..50fe74a75b 100644
--- a/libraries/entities/src/DiffTraversal.h
+++ b/libraries/entities/src/DiffTraversal.h
@@ -30,10 +30,15 @@ public:
// View is a struct with a ViewFrustum and LOD parameters
class View {
public:
- ViewFrustum viewFrustum;
+ bool isBigEnough(const AACube& cube, float minDiameter = MIN_ENTITY_ANGULAR_DIAMETER) const;
+ bool intersects(const AACube& cube) const;
+ bool usesViewFrustums() const;
+ bool isVerySimilar(const View& view) const;
+ ViewFrustum::intersection calculateIntersection(const AACube& cube) const;
+
+ std::vector viewFrustums;
uint64_t startTime { 0 };
float lodScaleFactor { 1.0f };
- bool usesViewFrustum { true };
};
// Waypoint is an bookmark in a "path" of waypoints during a traversal.
@@ -57,15 +62,12 @@ public:
DiffTraversal();
- Type prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset,
- bool usesViewFrustum);
+ Type prepareNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root);
- const ViewFrustum& getCurrentView() const { return _currentView.viewFrustum; }
- const ViewFrustum& getCompletedView() const { return _completedView.viewFrustum; }
+ const View& getCurrentView() const { return _currentView; }
+ const View& getCompletedView() const { return _completedView; }
- bool doesCurrentUseViewFrustum() const { return _currentView.usesViewFrustum; }
- float getCurrentLODScaleFactor() const { return _currentView.lodScaleFactor; }
- float getCompletedLODScaleFactor() const { return _completedView.lodScaleFactor; }
+ bool doesCurrentUseViewFrustum() const { return _currentView.usesViewFrustums(); }
uint64_t getStartOfCompletedTraversal() const { return _completedView.startTime; }
bool finished() const { return _path.empty(); }
diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h
index a2ad834e18..b827ed7cd0 100644
--- a/libraries/octree/src/Octree.h
+++ b/libraries/octree/src/Octree.h
@@ -59,7 +59,6 @@ const int LOW_RES_MOVING_ADJUST = 1;
class EncodeBitstreamParams {
public:
- ViewFrustum viewFrustum;
bool includeExistsBits;
NodeData* nodeData;
diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp
index 18766dd7f6..18e907cb8c 100644
--- a/libraries/octree/src/OctreeQuery.cpp
+++ b/libraries/octree/src/OctreeQuery.cpp
@@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
+#include "OctreeQuery.h"
+
#include
#include
@@ -16,23 +18,11 @@
#include
#include
-#include "OctreeConstants.h"
-#include "OctreeQuery.h"
-
-const float DEFAULT_FOV = 45.0f; // degrees
-const float DEFAULT_ASPECT_RATIO = 1.0f;
-const float DEFAULT_NEAR_CLIP = 0.1f;
-const float DEFAULT_FAR_CLIP = 3.0f;
-
-OctreeQuery::OctreeQuery(bool randomizeConnectionID) :
- _cameraFov(DEFAULT_FOV),
- _cameraAspectRatio(DEFAULT_ASPECT_RATIO),
- _cameraNearClip(DEFAULT_NEAR_CLIP),
- _cameraFarClip(DEFAULT_FAR_CLIP),
- _cameraCenterRadius(DEFAULT_FAR_CLIP)
-{
- _maxQueryPPS = DEFAULT_MAX_OCTREE_PPS;
+using QueryFlags = uint8_t;
+const QueryFlags QUERY_HAS_MAIN_FRUSTUM = 1U << 0;
+const QueryFlags QUERY_HAS_SECONDARY_FRUSTUM = 1U << 1;
+OctreeQuery::OctreeQuery(bool randomizeConnectionID) {
if (randomizeConnectionID) {
// randomize our initial octree query connection ID using random_device
// the connection ID is 16 bits so we take a generated 32 bit value from random device and chop off the top
@@ -47,26 +37,28 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) {
// pack the connection ID so the server can detect when we start a new connection
memcpy(destinationBuffer, &_connectionID, sizeof(_connectionID));
destinationBuffer += sizeof(_connectionID);
-
- // back a boolean (cut to 1 byte) to designate if this query uses the sent view frustum
- memcpy(destinationBuffer, &_usesFrustum, sizeof(_usesFrustum));
- destinationBuffer += sizeof(_usesFrustum);
-
- if (_usesFrustum) {
- // TODO: DRY this up to a shared method
- // that can pack any type given the number of bytes
- // and return the number of bytes to push the pointer
-
- // camera details
- memcpy(destinationBuffer, &_cameraPosition, sizeof(_cameraPosition));
- destinationBuffer += sizeof(_cameraPosition);
- destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _cameraOrientation);
- destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _cameraFov);
- destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _cameraAspectRatio);
- destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraNearClip);
- destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip);
- memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition));
- destinationBuffer += sizeof(_cameraEyeOffsetPosition);
+
+ // flags for wether the frustums are present
+ QueryFlags frustumFlags = 0;
+ if (_hasMainFrustum) {
+ frustumFlags |= QUERY_HAS_MAIN_FRUSTUM;
+ }
+ if (_hasSecondaryFrustum) {
+ frustumFlags |= QUERY_HAS_SECONDARY_FRUSTUM;
+ }
+ memcpy(destinationBuffer, &frustumFlags, sizeof(frustumFlags));
+ destinationBuffer += sizeof(frustumFlags);
+
+ if (_hasMainFrustum) {
+ auto byteArray = _mainViewFrustum.toByteArray();
+ memcpy(destinationBuffer, byteArray.constData(), byteArray.size());
+ destinationBuffer += byteArray.size();
+ }
+
+ if (_hasSecondaryFrustum) {
+ auto byteArray = _secondaryViewFrustum.toByteArray();
+ memcpy(destinationBuffer, byteArray.constData(), byteArray.size());
+ destinationBuffer += byteArray.size();
}
// desired Max Octree PPS
@@ -80,9 +72,6 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) {
// desired boundaryLevelAdjust
memcpy(destinationBuffer, &_boundaryLevelAdjust, sizeof(_boundaryLevelAdjust));
destinationBuffer += sizeof(_boundaryLevelAdjust);
-
- memcpy(destinationBuffer, &_cameraCenterRadius, sizeof(_cameraCenterRadius));
- destinationBuffer += sizeof(_cameraCenterRadius);
// create a QByteArray that holds the binary representation of the JSON parameters
QByteArray binaryParametersDocument;
@@ -110,6 +99,7 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) {
int OctreeQuery::parseData(ReceivedMessage& message) {
const unsigned char* startPosition = reinterpret_cast(message.getRawMessage());
+ const unsigned char* endPosition = startPosition + message.getSize();
const unsigned char* sourceBuffer = startPosition;
// unpack the connection ID
@@ -133,20 +123,23 @@ int OctreeQuery::parseData(ReceivedMessage& message) {
}
// check if this query uses a view frustum
- memcpy(&_usesFrustum, sourceBuffer, sizeof(_usesFrustum));
- sourceBuffer += sizeof(_usesFrustum);
-
- if (_usesFrustum) {
- // unpack camera details
- memcpy(&_cameraPosition, sourceBuffer, sizeof(_cameraPosition));
- sourceBuffer += sizeof(_cameraPosition);
- sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, _cameraOrientation);
- sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_cameraFov);
- sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer,_cameraAspectRatio);
- sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraNearClip);
- sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraFarClip);
- memcpy(&_cameraEyeOffsetPosition, sourceBuffer, sizeof(_cameraEyeOffsetPosition));
- sourceBuffer += sizeof(_cameraEyeOffsetPosition);
+ QueryFlags frustumFlags { 0 };
+ memcpy(&frustumFlags, sourceBuffer, sizeof(frustumFlags));
+ sourceBuffer += sizeof(frustumFlags);
+
+ _hasMainFrustum = frustumFlags & QUERY_HAS_MAIN_FRUSTUM;
+ _hasSecondaryFrustum = frustumFlags & QUERY_HAS_SECONDARY_FRUSTUM;
+
+ if (_hasMainFrustum) {
+ auto bytesLeft = endPosition - sourceBuffer;
+ auto byteArray = QByteArray::fromRawData(reinterpret_cast(sourceBuffer), bytesLeft);
+ sourceBuffer += _mainViewFrustum.fromByteArray(byteArray);
+ }
+
+ if (_hasSecondaryFrustum) {
+ auto bytesLeft = endPosition - sourceBuffer;
+ auto byteArray = QByteArray::fromRawData(reinterpret_cast(sourceBuffer), bytesLeft);
+ sourceBuffer += _secondaryViewFrustum.fromByteArray(byteArray);
}
// desired Max Octree PPS
@@ -161,9 +154,6 @@ int OctreeQuery::parseData(ReceivedMessage& message) {
memcpy(&_boundaryLevelAdjust, sourceBuffer, sizeof(_boundaryLevelAdjust));
sourceBuffer += sizeof(_boundaryLevelAdjust);
- memcpy(&_cameraCenterRadius, sourceBuffer, sizeof(_cameraCenterRadius));
- sourceBuffer += sizeof(_cameraCenterRadius);
-
// check if we have a packed JSON filter
uint16_t binaryParametersBytes;
memcpy(&binaryParametersBytes, sourceBuffer, sizeof(binaryParametersBytes));
@@ -184,8 +174,3 @@ int OctreeQuery::parseData(ReceivedMessage& message) {
return sourceBuffer - startPosition;
}
-
-glm::vec3 OctreeQuery::calculateCameraDirection() const {
- glm::vec3 direction = glm::vec3(_cameraOrientation * glm::vec4(IDENTITY_FORWARD, 0.0f));
- return direction;
-}
diff --git a/libraries/octree/src/OctreeQuery.h b/libraries/octree/src/OctreeQuery.h
index 21ce2e7fac..ef52e29f51 100644
--- a/libraries/octree/src/OctreeQuery.h
+++ b/libraries/octree/src/OctreeQuery.h
@@ -12,16 +12,14 @@
#ifndef hifi_OctreeQuery_h
#define hifi_OctreeQuery_h
-#include
-
-#include
-#include
-
#include
#include
#include
+#include
+
+#include "OctreeConstants.h"
class OctreeQuery : public NodeData {
Q_OBJECT
@@ -30,31 +28,22 @@ public:
OctreeQuery(bool randomizeConnectionID = false);
virtual ~OctreeQuery() {}
+ OctreeQuery(const OctreeQuery&) = delete;
+ OctreeQuery& operator=(const OctreeQuery&) = delete;
+
int getBroadcastData(unsigned char* destinationBuffer);
int parseData(ReceivedMessage& message) override;
- // getters for camera details
- const glm::vec3& getCameraPosition() const { return _cameraPosition; }
- const glm::quat& getCameraOrientation() const { return _cameraOrientation; }
- float getCameraFov() const { return _cameraFov; }
- float getCameraAspectRatio() const { return _cameraAspectRatio; }
- float getCameraNearClip() const { return _cameraNearClip; }
- float getCameraFarClip() const { return _cameraFarClip; }
- const glm::vec3& getCameraEyeOffsetPosition() const { return _cameraEyeOffsetPosition; }
- float getCameraCenterRadius() const { return _cameraCenterRadius; }
+ bool hasMainViewFrustum() const { return _hasMainFrustum; }
+ void setMainViewFrustum(const ViewFrustum& viewFrustum) { _hasMainFrustum = true; _mainViewFrustum = viewFrustum; }
+ void clearMainViewFrustum() { _hasMainFrustum = false; }
+ const ViewFrustum& getMainViewFrustum() const { return _mainViewFrustum; }
- glm::vec3 calculateCameraDirection() const;
+ bool hasSecondaryViewFrustum() const { return _hasSecondaryFrustum; }
+ void setSecondaryViewFrustum(const ViewFrustum& viewFrustum) { _hasSecondaryFrustum = true; _secondaryViewFrustum = viewFrustum; }
+ void clearSecondaryViewFrustum() { _hasSecondaryFrustum = false; }
+ const ViewFrustum& getSecondaryViewFrustum() const { return _secondaryViewFrustum; }
- // setters for camera details
- void setCameraPosition(const glm::vec3& position) { _cameraPosition = position; }
- void setCameraOrientation(const glm::quat& orientation) { _cameraOrientation = orientation; }
- void setCameraFov(float fov) { _cameraFov = fov; }
- void setCameraAspectRatio(float aspectRatio) { _cameraAspectRatio = aspectRatio; }
- void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; }
- void setCameraFarClip(float farClip) { _cameraFarClip = farClip; }
- void setCameraEyeOffsetPosition(const glm::vec3& eyeOffsetPosition) { _cameraEyeOffsetPosition = eyeOffsetPosition; }
- void setCameraCenterRadius(float radius) { _cameraCenterRadius = radius; }
-
// getters/setters for JSON filter
QJsonObject getJSONParameters() { QReadLocker locker { &_jsonParametersLock }; return _jsonParameters; }
void setJSONParameters(const QJsonObject& jsonParameters)
@@ -64,9 +53,6 @@ public:
int getMaxQueryPacketsPerSecond() const { return _maxQueryPPS; }
float getOctreeSizeScale() const { return _octreeElementSizeScale; }
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
-
- bool getUsesFrustum() { return _usesFrustum; }
- void setUsesFrustum(bool usesFrustum) { _usesFrustum = usesFrustum; }
void incrementConnectionID() { ++_connectionID; }
@@ -81,33 +67,22 @@ public slots:
void setBoundaryLevelAdjust(int boundaryLevelAdjust) { _boundaryLevelAdjust = boundaryLevelAdjust; }
protected:
- // camera details for the avatar
- glm::vec3 _cameraPosition { glm::vec3(0.0f) };
- glm::quat _cameraOrientation { glm::quat() };
- float _cameraFov;
- float _cameraAspectRatio;
- float _cameraNearClip;
- float _cameraFarClip;
- float _cameraCenterRadius;
- glm::vec3 _cameraEyeOffsetPosition { glm::vec3(0.0f) };
+ bool _hasMainFrustum { false };
+ ViewFrustum _mainViewFrustum;
+ bool _hasSecondaryFrustum { false };
+ ViewFrustum _secondaryViewFrustum;
// octree server sending items
int _maxQueryPPS = DEFAULT_MAX_OCTREE_PPS;
float _octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE; /// used for LOD calculations
int _boundaryLevelAdjust = 0; /// used for LOD calculations
-
- uint8_t _usesFrustum = true;
+
uint16_t _connectionID; // query connection ID, randomized to start, increments with each new connection to server
QJsonObject _jsonParameters;
QReadWriteLock _jsonParametersLock;
bool _hasReceivedFirstQuery { false };
-
-private:
- // privatize the copy constructor and assignment operator so they cannot be called
- OctreeQuery(const OctreeQuery&);
- OctreeQuery& operator= (const OctreeQuery&);
};
#endif // hifi_OctreeQuery_h
diff --git a/libraries/octree/src/OctreeQueryNode.cpp b/libraries/octree/src/OctreeQueryNode.cpp
index 16542b697e..d6e9343896 100644
--- a/libraries/octree/src/OctreeQueryNode.cpp
+++ b/libraries/octree/src/OctreeQueryNode.cpp
@@ -139,9 +139,14 @@ void OctreeQueryNode::writeToPacket(const unsigned char* buffer, unsigned int by
}
}
-void OctreeQueryNode::copyCurrentViewFrustum(ViewFrustum& viewOut) const {
+void OctreeQueryNode::copyCurrentMainViewFrustum(ViewFrustum& viewOut) const {
QMutexLocker viewLocker(&_viewMutex);
- viewOut = _currentViewFrustum;
+ viewOut = _currentMainViewFrustum;
+}
+
+void OctreeQueryNode::copyCurrentSecondaryViewFrustum(ViewFrustum& viewOut) const {
+ QMutexLocker viewLocker(&_viewMutex);
+ viewOut = _currentSecondaryViewFrustum;
}
bool OctreeQueryNode::updateCurrentViewFrustum() {
@@ -150,70 +155,50 @@ bool OctreeQueryNode::updateCurrentViewFrustum() {
return false;
}
- if (!_usesFrustum) {
+ if (!_hasMainFrustum && !_hasSecondaryFrustum) {
// this client does not use a view frustum so the view frustum for this query has not changed
return false;
- } else {
- bool currentViewFrustumChanged = false;
-
- ViewFrustum newestViewFrustum;
- // get position and orientation details from the camera
- newestViewFrustum.setPosition(getCameraPosition());
- newestViewFrustum.setOrientation(getCameraOrientation());
-
- newestViewFrustum.setCenterRadius(getCameraCenterRadius());
-
- // Also make sure it's got the correct lens details from the camera
- float originalFOV = getCameraFov();
- float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND;
-
- if (0.0f != getCameraAspectRatio() &&
- 0.0f != getCameraNearClip() &&
- 0.0f != getCameraFarClip() &&
- getCameraNearClip() != getCameraFarClip()) {
- newestViewFrustum.setProjection(glm::perspective(
- glm::radians(wideFOV), // hack
- getCameraAspectRatio(),
- getCameraNearClip(),
- getCameraFarClip()));
- newestViewFrustum.calculate();
- }
-
-
- { // if there has been a change, then recalculate
- QMutexLocker viewLocker(&_viewMutex);
- if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
- _currentViewFrustum = newestViewFrustum;
- currentViewFrustumChanged = true;
- }
- }
-
- // Also check for LOD changes from the client
- if (_lodInitialized) {
- if (_lastClientBoundaryLevelAdjust != getBoundaryLevelAdjust()) {
- _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
- _lodChanged = true;
- }
- if (_lastClientOctreeSizeScale != getOctreeSizeScale()) {
- _lastClientOctreeSizeScale = getOctreeSizeScale();
- _lodChanged = true;
- }
- } else {
- _lodInitialized = true;
- _lastClientOctreeSizeScale = getOctreeSizeScale();
- _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
- _lodChanged = false;
- }
-
- // When we first detect that the view stopped changing, we record this.
- // but we don't change it back to false until we've completely sent this
- // scene.
- if (_viewFrustumChanging && !currentViewFrustumChanged) {
- _viewFrustumJustStoppedChanging = true;
- }
- _viewFrustumChanging = currentViewFrustumChanged;
- return currentViewFrustumChanged;
}
+
+ bool currentViewFrustumChanged = false;
+
+ { // if there has been a change, then recalculate
+ QMutexLocker viewLocker(&_viewMutex);
+ if (_hasMainFrustum && !_mainViewFrustum.isVerySimilar(_currentMainViewFrustum)) {
+ _currentMainViewFrustum = _mainViewFrustum;
+ currentViewFrustumChanged = true;
+ }
+ if (_hasSecondaryFrustum && !_secondaryViewFrustum.isVerySimilar(_currentSecondaryViewFrustum)) {
+ _currentSecondaryViewFrustum = _secondaryViewFrustum;
+ currentViewFrustumChanged = true;
+ }
+ }
+
+ // Also check for LOD changes from the client
+ if (_lodInitialized) {
+ if (_lastClientBoundaryLevelAdjust != getBoundaryLevelAdjust()) {
+ _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
+ _lodChanged = true;
+ }
+ if (_lastClientOctreeSizeScale != getOctreeSizeScale()) {
+ _lastClientOctreeSizeScale = getOctreeSizeScale();
+ _lodChanged = true;
+ }
+ } else {
+ _lodInitialized = true;
+ _lastClientOctreeSizeScale = getOctreeSizeScale();
+ _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
+ _lodChanged = false;
+ }
+
+ // When we first detect that the view stopped changing, we record this.
+ // but we don't change it back to false until we've completely sent this
+ // scene.
+ if (_viewFrustumChanging && !currentViewFrustumChanged) {
+ _viewFrustumJustStoppedChanging = true;
+ }
+ _viewFrustumChanging = currentViewFrustumChanged;
+ return currentViewFrustumChanged;
}
void OctreeQueryNode::setViewSent(bool viewSent) {
diff --git a/libraries/octree/src/OctreeQueryNode.h b/libraries/octree/src/OctreeQueryNode.h
index 640a7c7ddc..d8f05c4043 100644
--- a/libraries/octree/src/OctreeQueryNode.h
+++ b/libraries/octree/src/OctreeQueryNode.h
@@ -49,7 +49,8 @@ public:
OctreeElementExtraEncodeData extraEncodeData;
- void copyCurrentViewFrustum(ViewFrustum& viewOut) const;
+ void copyCurrentMainViewFrustum(ViewFrustum& viewOut) const;
+ void copyCurrentSecondaryViewFrustum(ViewFrustum& viewOut) const;
// These are not classic setters because they are calculating and maintaining state
// which is set asynchronously through the network receive
@@ -87,9 +88,6 @@ public:
void setShouldForceFullScene(bool shouldForceFullScene) { _shouldForceFullScene = shouldForceFullScene; }
private:
- OctreeQueryNode(const OctreeQueryNode &);
- OctreeQueryNode& operator= (const OctreeQueryNode&);
-
bool _viewSent { false };
std::unique_ptr _octreePacket;
bool _octreePacketWaiting;
@@ -99,7 +97,8 @@ private:
quint64 _firstSuppressedPacket { usecTimestampNow() };
mutable QMutex _viewMutex { QMutex::Recursive };
- ViewFrustum _currentViewFrustum;
+ ViewFrustum _currentMainViewFrustum;
+ ViewFrustum _currentSecondaryViewFrustum;
bool _viewFrustumChanging { false };
bool _viewFrustumJustStoppedChanging { true };
diff --git a/libraries/octree/src/OctreeUtils.cpp b/libraries/octree/src/OctreeUtils.cpp
index 8980504431..8eaf22e198 100644
--- a/libraries/octree/src/OctreeUtils.cpp
+++ b/libraries/octree/src/OctreeUtils.cpp
@@ -16,6 +16,7 @@
#include
#include
+#include
float calculateRenderAccuracy(const glm::vec3& position,
const AABox& bounds,
@@ -73,4 +74,10 @@ float getOrthographicAccuracySize(float octreeSizeScale, int boundaryLevelAdjust
// Smallest visible element is 1cm
const float smallestSize = 0.01f;
return (smallestSize * MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT) / boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale);
-}
\ No newline at end of file
+}
+
+bool isAngularSizeBigEnough(glm::vec3 position, const AACube& cube, float lodScaleFactor, float minDiameter) {
+ float distance = glm::distance(cube.calcCenter(), position) + MIN_VISIBLE_DISTANCE;
+ float angularDiameter = cube.getScale() / distance;
+ return angularDiameter > minDiameter * lodScaleFactor;
+}
diff --git a/libraries/octree/src/OctreeUtils.h b/libraries/octree/src/OctreeUtils.h
index d5008376ea..58ab366d8d 100644
--- a/libraries/octree/src/OctreeUtils.h
+++ b/libraries/octree/src/OctreeUtils.h
@@ -15,6 +15,7 @@
#include "OctreeConstants.h"
class AABox;
+class AACube;
class QJsonDocument;
/// renderAccuracy represents a floating point "visibility" of an object based on it's view from the camera. At a simple
@@ -36,4 +37,6 @@ const float SQRT_THREE = 1.73205080f;
const float MIN_ENTITY_ANGULAR_DIAMETER = MIN_ELEMENT_ANGULAR_DIAMETER * SQRT_THREE;
const float MIN_VISIBLE_DISTANCE = 0.0001f; // helps avoid divide-by-zero check
+bool isAngularSizeBigEnough(glm::vec3 position, const AACube& cube, float lodScaleFactor, float minDiameter);
+
#endif // hifi_OctreeUtils_h
diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp
index 2a2eebc0a7..f65f5407fd 100644
--- a/libraries/shared/src/ViewFrustum.cpp
+++ b/libraries/shared/src/ViewFrustum.cpp
@@ -134,7 +134,7 @@ const char* ViewFrustum::debugPlaneName (int plane) const {
return "Unknown";
}
-void ViewFrustum::fromByteArray(const QByteArray& input) {
+int ViewFrustum::fromByteArray(const QByteArray& input) {
// From the wire!
glm::vec3 cameraPosition;
@@ -176,6 +176,8 @@ void ViewFrustum::fromByteArray(const QByteArray& input) {
calculate();
}
+
+ return sourceBuffer - startPosition;
}
diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h
index 981aabe70c..70fcb4cc32 100644
--- a/libraries/shared/src/ViewFrustum.h
+++ b/libraries/shared/src/ViewFrustum.h
@@ -147,7 +147,7 @@ public:
void invalidate(); // causes all reasonable intersection tests to fail
QByteArray toByteArray();
- void fromByteArray(const QByteArray& input);
+ int fromByteArray(const QByteArray& input);
private:
glm::mat4 _view;
From 98cf48694e8718887a2a6c1592d8e1171fe38ff2 Mon Sep 17 00:00:00 2001
From: Clement
Date: Mon, 16 Apr 2018 15:27:43 -0700
Subject: [PATCH 12/51] Expose secondary camera to game logic
---
interface/src/Application.cpp | 32 ++++++++++++++++++++++++++++
interface/src/Application.h | 5 +++++
libraries/shared/src/ViewFrustum.cpp | 10 ++++-----
libraries/shared/src/ViewFrustum.h | 1 +
4 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index d1d44aa706..a38f4d022d 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -5532,6 +5532,26 @@ void Application::update(float deltaTime) {
{
QMutexLocker viewLocker(&_viewMutex);
_myCamera.loadViewFrustum(_viewFrustum);
+
+
+ auto renderConfig = _renderEngine->getConfiguration();
+ assert(renderConfig);
+ auto secondaryCamera = dynamic_cast(renderConfig->getConfig("SecondaryCamera"));
+ assert(secondaryCamera);
+
+ if (secondaryCamera->isEnabled()) {
+ _secondaryViewFrustum.setPosition(secondaryCamera->position);
+ _secondaryViewFrustum.setOrientation(secondaryCamera->orientation);
+ _secondaryViewFrustum.setProjection(secondaryCamera->vFoV,
+ secondaryCamera->textureWidth / secondaryCamera->textureHeight,
+ secondaryCamera->nearClipPlaneDistance,
+ secondaryCamera->farClipPlaneDistance);
+ _secondaryViewFrustum.calculate();
+ _hasSecondaryViewFrustum = true;
+ } else {
+ _hasSecondaryViewFrustum = false;
+ }
+
}
quint64 now = usecTimestampNow();
@@ -5793,6 +5813,13 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType) {
copyViewFrustum(viewFrustum);
_octreeQuery.setMainViewFrustum(viewFrustum);
+ if (hasSecondaryViewFrustum()) {
+ copySecondaryViewFrustum(viewFrustum);
+ _octreeQuery.setSecondaryViewFrustum(viewFrustum);
+ } else {
+ _octreeQuery.clearSecondaryViewFrustum();
+ }
+
auto lodManager = DependencyManager::get();
_octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale());
_octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust());
@@ -5876,6 +5903,11 @@ void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const {
viewOut = _displayViewFrustum;
}
+void Application::copySecondaryViewFrustum(ViewFrustum& viewOut) const {
+ QMutexLocker viewLocker(&_viewMutex);
+ viewOut = _secondaryViewFrustum;
+}
+
void Application::resetSensors(bool andReload) {
DependencyManager::get()->reset();
DependencyManager::get()->reset();
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 6d611bc8e2..043a9b52ab 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -178,6 +178,9 @@ public:
// which might be different from the viewFrustum, i.e. shadowmap
// passes, mirror window passes, etc
void copyDisplayViewFrustum(ViewFrustum& viewOut) const;
+ void copySecondaryViewFrustum(ViewFrustum& viewOut) const;
+ bool hasSecondaryViewFrustum() const { return _hasSecondaryViewFrustum; }
+
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
QSharedPointer getEntities() const { return DependencyManager::get(); }
QUndoStack* getUndoStack() { return &_undoStack; }
@@ -554,6 +557,8 @@ private:
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels)
ViewFrustum _displayViewFrustum;
+ ViewFrustum _secondaryViewFrustum;
+ bool _hasSecondaryViewFrustum;
quint64 _lastQueriedTime;
OctreeQuery _octreeQuery { true }; // NodeData derived class for querying octee cells from octree servers
diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp
index f65f5407fd..c2b92aac5f 100644
--- a/libraries/shared/src/ViewFrustum.cpp
+++ b/libraries/shared/src/ViewFrustum.cpp
@@ -75,6 +75,10 @@ void ViewFrustum::setProjection(const glm::mat4& projection) {
_width = _corners[TOP_RIGHT_NEAR].x - _corners[TOP_LEFT_NEAR].x;
}
+void ViewFrustum::setProjection(float cameraFov, float cameraAspectRatio, float cameraNearClip, float cameraFarClip) {
+ setProjection(glm::perspective(glm::radians(cameraFov), cameraAspectRatio, cameraNearClip, cameraFarClip));
+}
+
// ViewFrustum::calculate()
//
// Description: this will calculate the view frustum bounds for a given position and direction
@@ -168,12 +172,8 @@ int ViewFrustum::fromByteArray(const QByteArray& input) {
0.0f != cameraNearClip &&
0.0f != cameraFarClip &&
cameraNearClip != cameraFarClip) {
- setProjection(glm::perspective(
- glm::radians(cameraFov),
- cameraAspectRatio,
- cameraNearClip,
- cameraFarClip));
+ setProjection(cameraFov, cameraAspectRatio, cameraNearClip, cameraFarClip);
calculate();
}
diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h
index 70fcb4cc32..ba8957bba3 100644
--- a/libraries/shared/src/ViewFrustum.h
+++ b/libraries/shared/src/ViewFrustum.h
@@ -48,6 +48,7 @@ public:
// setters for lens attributes
void setProjection(const glm::mat4 & projection);
+ void setProjection(float cameraFov, float cameraAspectRatio, float cameraNearClip, float cameraFarClip);
void setFocalLength(float focalLength) { _focalLength = focalLength; }
bool isPerspective() const;
From 7f67547faef1068a765f0aaba8b10a4a08060d12 Mon Sep 17 00:00:00 2001
From: Clement
Date: Mon, 16 Apr 2018 17:45:11 -0700
Subject: [PATCH 13/51] Update HeadlessViewer to not always send a frustum
---
.../src/octree/OctreeHeadlessViewer.cpp | 13 +++------
.../src/octree/OctreeHeadlessViewer.h | 27 ++++++++-----------
2 files changed, 14 insertions(+), 26 deletions(-)
diff --git a/assignment-client/src/octree/OctreeHeadlessViewer.cpp b/assignment-client/src/octree/OctreeHeadlessViewer.cpp
index 4f022ae838..6d91a134c2 100644
--- a/assignment-client/src/octree/OctreeHeadlessViewer.cpp
+++ b/assignment-client/src/octree/OctreeHeadlessViewer.cpp
@@ -14,25 +14,18 @@
#include
#include
-
-OctreeHeadlessViewer::OctreeHeadlessViewer() {
- _viewFrustum.setProjection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), DEFAULT_ASPECT_RATIO, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
-}
-
void OctreeHeadlessViewer::queryOctree() {
char serverType = getMyNodeType();
PacketType packetType = getMyQueryMessageType();
- _octreeQuery.setMainViewFrustum(_viewFrustum);
- _octreeQuery.setOctreeSizeScale(_voxelSizeScale);
- _octreeQuery.setBoundaryLevelAdjust(_boundaryLevelAdjust);
+ if (_hasViewFrustum) {
+ _octreeQuery.setMainViewFrustum(_viewFrustum);
+ }
auto nodeList = DependencyManager::get();
auto node = nodeList->soloNodeOfType(serverType);
if (node && node->getActiveSocket()) {
- _octreeQuery.setMaxQueryPacketsPerSecond(getMaxPacketsPerSecond());
-
auto queryPacket = NLPacket::create(packetType);
// encode the query data
diff --git a/assignment-client/src/octree/OctreeHeadlessViewer.h b/assignment-client/src/octree/OctreeHeadlessViewer.h
index feb8211c39..dea91ce66f 100644
--- a/assignment-client/src/octree/OctreeHeadlessViewer.h
+++ b/assignment-client/src/octree/OctreeHeadlessViewer.h
@@ -20,9 +20,6 @@
class OctreeHeadlessViewer : public OctreeProcessor {
Q_OBJECT
public:
- OctreeHeadlessViewer();
- virtual ~OctreeHeadlessViewer() {};
-
OctreeQuery& getOctreeQuery() { return _octreeQuery; }
static int parseOctreeStats(QSharedPointer message, SharedNodePointer sourceNode);
@@ -32,34 +29,32 @@ public slots:
void queryOctree();
// setters for camera attributes
- void setPosition(const glm::vec3& position) { _viewFrustum.setPosition(position); }
- void setOrientation(const glm::quat& orientation) { _viewFrustum.setOrientation(orientation); }
- void setCenterRadius(float radius) { _viewFrustum.setCenterRadius(radius); }
- void setKeyholeRadius(float radius) { _viewFrustum.setCenterRadius(radius); } // TODO: remove this legacy support
+ void setPosition(const glm::vec3& position) { _hasViewFrustum = true; _viewFrustum.setPosition(position); }
+ void setOrientation(const glm::quat& orientation) { _hasViewFrustum = true; _viewFrustum.setOrientation(orientation); }
+ void setCenterRadius(float radius) { _hasViewFrustum = true; _viewFrustum.setCenterRadius(radius); }
+ void setKeyholeRadius(float radius) { _hasViewFrustum = true; _viewFrustum.setCenterRadius(radius); } // TODO: remove this legacy support
// setters for LOD and PPS
- void setVoxelSizeScale(float sizeScale) { _voxelSizeScale = sizeScale; }
- void setBoundaryLevelAdjust(int boundaryLevelAdjust) { _boundaryLevelAdjust = boundaryLevelAdjust; }
- void setMaxPacketsPerSecond(int maxPacketsPerSecond) { _maxPacketsPerSecond = maxPacketsPerSecond; }
+ void setVoxelSizeScale(float sizeScale) { _octreeQuery.setOctreeSizeScale(sizeScale) ; }
+ void setBoundaryLevelAdjust(int boundaryLevelAdjust) { _octreeQuery.setBoundaryLevelAdjust(boundaryLevelAdjust); }
+ void setMaxPacketsPerSecond(int maxPacketsPerSecond) { _octreeQuery.setMaxQueryPacketsPerSecond(maxPacketsPerSecond); }
// getters for camera attributes
const glm::vec3& getPosition() const { return _viewFrustum.getPosition(); }
const glm::quat& getOrientation() const { return _viewFrustum.getOrientation(); }
// getters for LOD and PPS
- float getVoxelSizeScale() const { return _voxelSizeScale; }
- int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
- int getMaxPacketsPerSecond() const { return _maxPacketsPerSecond; }
+ float getVoxelSizeScale() const { return _octreeQuery.getOctreeSizeScale(); }
+ int getBoundaryLevelAdjust() const { return _octreeQuery.getBoundaryLevelAdjust(); }
+ int getMaxPacketsPerSecond() const { return _octreeQuery.getMaxQueryPacketsPerSecond(); }
unsigned getOctreeElementsCount() const { return _tree->getOctreeElementsCount(); }
private:
OctreeQuery _octreeQuery;
+ bool _hasViewFrustum { false };
ViewFrustum _viewFrustum;
- float _voxelSizeScale { DEFAULT_OCTREE_SIZE_SCALE };
- int _boundaryLevelAdjust { 0 };
- int _maxPacketsPerSecond { DEFAULT_MAX_OCTREE_PPS };
};
#endif // hifi_OctreeHeadlessViewer_h
From 3862a02ceed3c1779761b039bd9f48dfb6ad11e6 Mon Sep 17 00:00:00 2001
From: Clement
Date: Mon, 16 Apr 2018 18:30:51 -0700
Subject: [PATCH 14/51] DRY traversal scan callbacks
---
.../src/entities/EntityPriorityQueue.cpp | 4 +
.../src/entities/EntityTreeSendThread.cpp | 218 ++++++++----------
libraries/entities/src/DiffTraversal.cpp | 29 ++-
3 files changed, 115 insertions(+), 136 deletions(-)
diff --git a/assignment-client/src/entities/EntityPriorityQueue.cpp b/assignment-client/src/entities/EntityPriorityQueue.cpp
index a38d537649..88dee58f9d 100644
--- a/assignment-client/src/entities/EntityPriorityQueue.cpp
+++ b/assignment-client/src/entities/EntityPriorityQueue.cpp
@@ -62,6 +62,10 @@ void ConicalView::set(const DiffTraversal::View& view) {
}
float ConicalView::computePriority(const AACube& cube) const {
+ if (_conicalViewFrustums.empty()) {
+ return PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY;
+ }
+
float priority = PrioritizedEntity::DO_NOT_SEND;
for (const auto& view : _conicalViewFrustums) {
diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp
index d14d31bd09..a282c4ad4c 100644
--- a/assignment-client/src/entities/EntityTreeSendThread.cpp
+++ b/assignment-client/src/entities/EntityTreeSendThread.cpp
@@ -135,25 +135,27 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
bool forceRemove = prevSendQueue.top().shouldForceRemove();
prevSendQueue.pop();
if (entity) {
- if (!forceRemove) {
+ float priority = PrioritizedEntity::DO_NOT_SEND;
+
+
+ if (forceRemove) {
+ priority = PrioritizedEntity::FORCE_REMOVE;
+ } else {
bool success = false;
AACube cube = entity->getQueryAACube(success);
if (success) {
- if (_traversal.getCurrentView().intersects(cube)) {
- float priority = _conicalView.computePriority(cube);
- if (priority != PrioritizedEntity::DO_NOT_SEND) {
- if (_traversal.getCurrentView().isBigEnough(cube)) {
- _sendQueue.push(PrioritizedEntity(entity, priority));
- _entitiesInQueue.insert(entity.get());
- }
- }
+ const auto& view = _traversal.getCurrentView();
+ if (view.intersects(cube) && view.isBigEnough(cube)) {
+ priority = _conicalView.computePriority(cube);
}
} else {
- _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
- _entitiesInQueue.insert(entity.get());
+ priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY;
}
- } else {
- _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::FORCE_REMOVE, true));
+ }
+
+
+ if (priority != PrioritizedEntity::DO_NOT_SEND) {
+ _sendQueue.emplace(entity, priority, forceRemove);
_entitiesInQueue.insert(entity.get());
}
}
@@ -245,104 +247,79 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
case DiffTraversal::First:
// When we get to a First traversal, clear the _knownState
_knownState.clear();
- if (view.usesViewFrustums()) {
- _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
+ _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
+ next.element->forEachEntity([&](EntityItemPointer entity) {
+ // Bail early if we've already checked this entity this frame
+ if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
+ return;
+ }
+ float priority = PrioritizedEntity::DO_NOT_SEND;
+
+
+ bool success = false;
+ AACube cube = entity->getQueryAACube(success);
+ if (success) {
+ const auto& view = _traversal.getCurrentView();
+ // Check the size of the entity, it's possible that a "too small to see" entity is included in a
+ // larger octree cell because of its position (for example if it crosses the boundary of a cell it
+ // pops to the next higher cell. So we want to check to see that the entity is large enough to be seen
+ // before we consider including it.
+ if ((next.intersection == ViewFrustum::INSIDE || view.intersects(cube)) &&
+ view.isBigEnough(cube)) {
+ priority = _conicalView.computePriority(cube);
+ }
+ } else {
+ priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY;
+ }
+
+
+ if (priority != PrioritizedEntity::DO_NOT_SEND) {
+ _sendQueue.emplace(entity, priority);
+ _entitiesInQueue.insert(entity.get());
+ }
+ });
+ });
+ break;
+ case DiffTraversal::Repeat:
+ _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
+ uint64_t startOfCompletedTraversal = _traversal.getStartOfCompletedTraversal();
+ if (next.element->getLastChangedContent() > startOfCompletedTraversal) {
next.element->forEachEntity([&](EntityItemPointer entity) {
// Bail early if we've already checked this entity this frame
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
return;
}
- bool success = false;
- AACube cube = entity->getQueryAACube(success);
- if (success) {
- if (_traversal.getCurrentView().intersects(cube)) {
- // Check the size of the entity, it's possible that a "too small to see" entity is included in a
- // larger octree cell because of its position (for example if it crosses the boundary of a cell it
- // pops to the next higher cell. So we want to check to see that the entity is large enough to be seen
- // before we consider including it.
- if (_traversal.getCurrentView().isBigEnough(cube)) {
- float priority = _conicalView.computePriority(cube);
- _sendQueue.push(PrioritizedEntity(entity, priority));
- _entitiesInQueue.insert(entity.get());
+ float priority = PrioritizedEntity::DO_NOT_SEND;
+
+
+ auto knownTimestamp = _knownState.find(entity.get());
+ if (knownTimestamp == _knownState.end()) {
+ bool success = false;
+ AACube cube = entity->getQueryAACube(success);
+ if (success) {
+ const auto& view = _traversal.getCurrentView();
+ // See the DiffTraversal::First case for an explanation of the "entity is too small" check
+ if ((next.intersection == ViewFrustum::INSIDE || view.intersects(cube)) &&
+ view.isBigEnough(cube)) {
+ priority = _conicalView.computePriority(cube);
}
+ } else {
+ priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY;
}
- } else {
- _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
+ } else if (entity->getLastEdited() > knownTimestamp->second) {
+ // it is known and it changed --> put it on the queue with any priority
+ // TODO: sort these correctly
+ priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY;
+ }
+
+
+ if (priority != PrioritizedEntity::DO_NOT_SEND) {
+ _sendQueue.emplace(entity, priority);
_entitiesInQueue.insert(entity.get());
}
});
- });
- } else {
- _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
- next.element->forEachEntity([&](EntityItemPointer entity) {
- // Bail early if we've already checked this entity this frame
- if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
- return;
- }
- _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
- _entitiesInQueue.insert(entity.get());
- });
- });
- }
- break;
- case DiffTraversal::Repeat:
- if (view.usesViewFrustums()) {
- _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
- uint64_t startOfCompletedTraversal = _traversal.getStartOfCompletedTraversal();
- if (next.element->getLastChangedContent() > startOfCompletedTraversal) {
- next.element->forEachEntity([&](EntityItemPointer entity) {
- // Bail early if we've already checked this entity this frame
- if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
- return;
- }
- auto knownTimestamp = _knownState.find(entity.get());
- if (knownTimestamp == _knownState.end()) {
- bool success = false;
- AACube cube = entity->getQueryAACube(success);
- if (success) {
- if (next.intersection == ViewFrustum::INSIDE ||
- _traversal.getCurrentView().intersects(cube)) {
- // See the DiffTraversal::First case for an explanation of the "entity is too small" check
- if (_traversal.getCurrentView().isBigEnough(cube)) {
- float priority = _conicalView.computePriority(cube);
- _sendQueue.push(PrioritizedEntity(entity, priority));
- _entitiesInQueue.insert(entity.get());
- }
- }
- } else {
- _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
- _entitiesInQueue.insert(entity.get());
- }
- } else if (entity->getLastEdited() > knownTimestamp->second
- || entity->getLastChangedOnServer() > knownTimestamp->second) {
- // it is known and it changed --> put it on the queue with any priority
- // TODO: sort these correctly
- _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
- _entitiesInQueue.insert(entity.get());
- }
- });
- }
- });
- } else {
- _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
- uint64_t startOfCompletedTraversal = _traversal.getStartOfCompletedTraversal();
- if (next.element->getLastChangedContent() > startOfCompletedTraversal) {
- next.element->forEachEntity([&](EntityItemPointer entity) {
- // Bail early if we've already checked this entity this frame
- if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
- return;
- }
- auto knownTimestamp = _knownState.find(entity.get());
- if (knownTimestamp == _knownState.end()
- || entity->getLastEdited() > knownTimestamp->second
- || entity->getLastChangedOnServer() > knownTimestamp->second) {
- _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
- _entitiesInQueue.insert(entity.get());
- }
- });
- }
- });
- }
+ }
+ });
break;
case DiffTraversal::Differential:
assert(view.usesViewFrustums());
@@ -352,36 +329,35 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
return;
}
+ float priority = PrioritizedEntity::DO_NOT_SEND;
+
+
auto knownTimestamp = _knownState.find(entity.get());
if (knownTimestamp == _knownState.end()) {
bool success = false;
AACube cube = entity->getQueryAACube(success);
if (success) {
- if (_traversal.getCurrentView().intersects(cube)) {
- // See the DiffTraversal::First case for an explanation of the "entity is too small" check
- if (_traversal.getCurrentView().isBigEnough(cube)) {
- if (!_traversal.getCompletedView().intersects(cube)) {
- float priority = _conicalView.computePriority(cube);
- _sendQueue.push(PrioritizedEntity(entity, priority));
- _entitiesInQueue.insert(entity.get());
- } else if (!_traversal.getCompletedView().isBigEnough(cube)) {
- // If this entity was skipped last time because it was too small, we still need to send it
- // this object was skipped in last completed traversal
- float priority = _conicalView.computePriority(cube);
- _sendQueue.push(PrioritizedEntity(entity, priority));
- _entitiesInQueue.insert(entity.get());
- }
- }
+ const auto& view = _traversal.getCurrentView();
+ // See the DiffTraversal::First case for an explanation of the "entity is too small" check
+ if ((next.intersection == ViewFrustum::INSIDE || view.intersects(cube)) &&
+ view.isBigEnough(cube)) {
+ // If this entity wasn't in the last view or
+ // If this entity was skipped last time because it was too small, we still need to send it
+ priority = _conicalView.computePriority(cube);
}
} else {
- _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
- _entitiesInQueue.insert(entity.get());
+ priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY;
}
} else if (entity->getLastEdited() > knownTimestamp->second
|| entity->getLastChangedOnServer() > knownTimestamp->second) {
// it is known and it changed --> put it on the queue with any priority
// TODO: sort these correctly
- _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
+ priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY;
+ }
+
+
+ if (priority != PrioritizedEntity::DO_NOT_SEND) {
+ _sendQueue.emplace(entity, priority);
_entitiesInQueue.insert(entity.get());
}
});
@@ -499,11 +475,11 @@ void EntityTreeSendThread::editingEntityPointer(const EntityItemPointer& entity)
if (success) {
// We can force a removal from _knownState if the current view is used and entity is out of view
if (_traversal.doesCurrentUseViewFrustum() && !_traversal.getCurrentView().intersects(cube)) {
- _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::FORCE_REMOVE, true));
+ _sendQueue.emplace(entity, PrioritizedEntity::FORCE_REMOVE, true);
_entitiesInQueue.insert(entity.get());
}
} else {
- _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY, true));
+ _sendQueue.emplace(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY, true);
_entitiesInQueue.insert(entity.get());
}
}
diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp
index 11f37728df..d5f2273fd5 100644
--- a/libraries/entities/src/DiffTraversal.cpp
+++ b/libraries/entities/src/DiffTraversal.cpp
@@ -13,7 +13,6 @@
#include
-
DiffTraversal::Waypoint::Waypoint(EntityTreeElementPointer& element) : _nextIndex(0) {
assert(element);
_weakElement = element;
@@ -140,12 +139,12 @@ bool DiffTraversal::View::isBigEnough(const AACube& cube, float minDiameter) con
return true;
}
- for (const auto& viewFrustum : viewFrustums) {
- if (isAngularSizeBigEnough(viewFrustum.getPosition(), cube, lodScaleFactor, minDiameter)) {
- return true;
- }
- }
- return false;
+ bool isBigEnough = std::any_of(std::begin(viewFrustums), std::end(viewFrustums),
+ [&](const ViewFrustum& viewFrustum) {
+ return isAngularSizeBigEnough(viewFrustum.getPosition(), cube, lodScaleFactor, minDiameter);
+ });
+
+ return isBigEnough;
}
bool DiffTraversal::View::intersects(const AACube& cube) const {
@@ -154,12 +153,12 @@ bool DiffTraversal::View::intersects(const AACube& cube) const {
return true;
}
- for (const auto& viewFrustum : viewFrustums) {
- if (viewFrustum.cubeIntersectsKeyhole(cube)) {
- return true;
- }
- }
- return false;
+ bool intersects = std::any_of(std::begin(viewFrustums), std::end(viewFrustums),
+ [&](const ViewFrustum& viewFrustum) {
+ return viewFrustum.cubeIntersectsKeyhole(cube);
+ });
+
+ return intersects;
}
ViewFrustum::intersection DiffTraversal::View::calculateIntersection(const AACube& cube) const {
@@ -231,7 +230,7 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const DiffTraversal::View
// If usesViewFrustum changes, treat it as a First traversal
if (_completedView.startTime == 0 || _currentView.usesViewFrustums() != _completedView.usesViewFrustums()) {
type = Type::First;
- _currentView.viewFrustums = std::move(view.viewFrustums);
+ _currentView.viewFrustums = view.viewFrustums;
_currentView.lodScaleFactor = view.lodScaleFactor;
_getNextVisibleElementCallback = [this](DiffTraversal::VisibleElement& next) {
_path.back().getNextVisibleElementFirstTime(next, _currentView);
@@ -243,7 +242,7 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const DiffTraversal::View
};
} else {
type = Type::Differential;
- _currentView.viewFrustums = std::move(view.viewFrustums);
+ _currentView.viewFrustums = view.viewFrustums;
_currentView.lodScaleFactor = view.lodScaleFactor;
_getNextVisibleElementCallback = [this](DiffTraversal::VisibleElement& next) {
_path.back().getNextVisibleElementDifferential(next, _currentView, _completedView);
From 7a710093acc4abd982535985cd48ceed311380f0 Mon Sep 17 00:00:00 2001
From: Atlante45
Date: Tue, 17 Apr 2018 16:28:50 -0700
Subject: [PATCH 15/51] Fix build error
---
libraries/entities/src/EntityTree.h | 3 ---
1 file changed, 3 deletions(-)
diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h
index 3289101967..d95dbf2990 100644
--- a/libraries/entities/src/EntityTree.h
+++ b/libraries/entities/src/EntityTree.h
@@ -27,9 +27,6 @@ using EntityTreePointer = std::shared_ptr;
#include "MovingEntitiesOperator.h"
class EntityEditFilters;
-class Model;
-using ModelPointer = std::shared_ptr;
-using ModelWeakPointer = std::weak_ptr;
class EntitySimulation;
From 69a7f2d4aa2852ac43f4f5454beea494553c2925 Mon Sep 17 00:00:00 2001
From: Clement
Date: Tue, 17 Apr 2018 17:41:35 -0700
Subject: [PATCH 16/51] Fix entity server crash
---
.../src/entities/EntityPriorityQueue.h | 47 ++++++++++++++++++-
.../src/entities/EntityTreeSendThread.cpp | 22 ++++-----
.../src/entities/EntityTreeSendThread.h | 1 -
3 files changed, 54 insertions(+), 16 deletions(-)
diff --git a/assignment-client/src/entities/EntityPriorityQueue.h b/assignment-client/src/entities/EntityPriorityQueue.h
index 4068b4dc4b..730e08591e 100644
--- a/assignment-client/src/entities/EntityPriorityQueue.h
+++ b/assignment-client/src/entities/EntityPriorityQueue.h
@@ -13,6 +13,7 @@
#define hifi_EntityPriorityQueue_h
#include
+#include
#include
#include
@@ -71,6 +72,50 @@ private:
bool _forceRemove;
};
-using EntityPriorityQueue = std::priority_queue< PrioritizedEntity, std::vector, PrioritizedEntity::Compare >;
+class EntityPriorityQueue {
+public:
+ inline bool empty() const {
+ assert(_queue.empty() == _entities.empty());
+ return _queue.empty();
+ }
+
+ inline const PrioritizedEntity& top() const {
+ assert(!_queue.empty());
+ return _queue.top();
+ }
+
+ inline bool contains(const EntityItem* entity) const {
+ return _entities.find(entity) != std::end(_entities);
+ }
+
+ inline void emplace(const EntityItemPointer& entity, float priority, bool forceRemove = false) {
+ assert(entity && !contains(entity.get()));
+ _queue.emplace(entity, priority, forceRemove);
+ _entities.insert(entity.get());
+ assert(_queue.size() == _entities.size());
+ }
+
+ inline void pop() {
+ assert(!empty());
+ _entities.erase(_queue.top().getRawEntityPointer());
+ _queue.pop();
+ assert(_queue.size() == _entities.size());
+ }
+
+ inline void swap(EntityPriorityQueue& other) {
+ std::swap(_queue, other._queue);
+ std::swap(_entities, other._entities);
+ }
+
+private:
+ using PriorityQueue = std::priority_queue,
+ PrioritizedEntity::Compare>;
+
+ PriorityQueue _queue;
+ // Keep dictionary of al the entities in the queue for fast contain checks.
+ std::unordered_set _entities;
+
+};
#endif // hifi_EntityPriorityQueue_h
diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp
index a282c4ad4c..ae7de01c3e 100644
--- a/assignment-client/src/entities/EntityTreeSendThread.cpp
+++ b/assignment-client/src/entities/EntityTreeSendThread.cpp
@@ -127,8 +127,9 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
// and also use the opportunity to cull anything no longer in view
if (viewFrustumChanged && !_sendQueue.empty()) {
EntityPriorityQueue prevSendQueue;
- _sendQueue.swap(prevSendQueue);
- _entitiesInQueue.clear();
+ std::swap(_sendQueue, prevSendQueue);
+ assert(_sendQueue.empty());
+
// Re-add elements from previous traversal if they still need to be sent
while (!prevSendQueue.empty()) {
EntityItemPointer entity = prevSendQueue.top().getEntity();
@@ -156,7 +157,6 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
if (priority != PrioritizedEntity::DO_NOT_SEND) {
_sendQueue.emplace(entity, priority, forceRemove);
- _entitiesInQueue.insert(entity.get());
}
}
}
@@ -250,7 +250,7 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
_traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
next.element->forEachEntity([&](EntityItemPointer entity) {
// Bail early if we've already checked this entity this frame
- if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
+ if (_sendQueue.contains(entity.get())) {
return;
}
float priority = PrioritizedEntity::DO_NOT_SEND;
@@ -275,7 +275,6 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
if (priority != PrioritizedEntity::DO_NOT_SEND) {
_sendQueue.emplace(entity, priority);
- _entitiesInQueue.insert(entity.get());
}
});
});
@@ -286,7 +285,7 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
if (next.element->getLastChangedContent() > startOfCompletedTraversal) {
next.element->forEachEntity([&](EntityItemPointer entity) {
// Bail early if we've already checked this entity this frame
- if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
+ if (_sendQueue.contains(entity.get())) {
return;
}
float priority = PrioritizedEntity::DO_NOT_SEND;
@@ -315,7 +314,6 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
if (priority != PrioritizedEntity::DO_NOT_SEND) {
_sendQueue.emplace(entity, priority);
- _entitiesInQueue.insert(entity.get());
}
});
}
@@ -326,7 +324,7 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
_traversal.setScanCallback([this] (DiffTraversal::VisibleElement& next) {
next.element->forEachEntity([&](EntityItemPointer entity) {
// Bail early if we've already checked this entity this frame
- if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
+ if (_sendQueue.contains(entity.get())) {
return;
}
float priority = PrioritizedEntity::DO_NOT_SEND;
@@ -358,7 +356,6 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
if (priority != PrioritizedEntity::DO_NOT_SEND) {
_sendQueue.emplace(entity, priority);
- _entitiesInQueue.insert(entity.get());
}
});
});
@@ -447,11 +444,10 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream
}
}
_sendQueue.pop();
- _entitiesInQueue.erase(entity.get());
}
nodeData->stats.encodeStopped();
if (_sendQueue.empty()) {
- assert(_entitiesInQueue.empty());
+ assert(_sendQueue.empty());
params.stopReason = EncodeBitstreamParams::FINISHED;
_extraEncodeData->entities.clear();
}
@@ -469,18 +465,16 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream
void EntityTreeSendThread::editingEntityPointer(const EntityItemPointer& entity) {
if (entity) {
- if (_entitiesInQueue.find(entity.get()) == _entitiesInQueue.end() && _knownState.find(entity.get()) != _knownState.end()) {
+ if (!_sendQueue.contains(entity.get()) && _knownState.find(entity.get()) != _knownState.end()) {
bool success = false;
AACube cube = entity->getQueryAACube(success);
if (success) {
// We can force a removal from _knownState if the current view is used and entity is out of view
if (_traversal.doesCurrentUseViewFrustum() && !_traversal.getCurrentView().intersects(cube)) {
_sendQueue.emplace(entity, PrioritizedEntity::FORCE_REMOVE, true);
- _entitiesInQueue.insert(entity.get());
}
} else {
_sendQueue.emplace(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY, true);
- _entitiesInQueue.insert(entity.get());
}
}
}
diff --git a/assignment-client/src/entities/EntityTreeSendThread.h b/assignment-client/src/entities/EntityTreeSendThread.h
index 5ea723c8b2..9eea98b7fd 100644
--- a/assignment-client/src/entities/EntityTreeSendThread.h
+++ b/assignment-client/src/entities/EntityTreeSendThread.h
@@ -50,7 +50,6 @@ private:
DiffTraversal _traversal;
EntityPriorityQueue _sendQueue;
- std::unordered_set _entitiesInQueue;
std::unordered_map _knownState;
ConicalView _conicalView; // cached optimized view for fast priority calculations
From fea49744ed3acbc673eb1b160f526b6c9a898718 Mon Sep 17 00:00:00 2001
From: Clement
Date: Tue, 17 Apr 2018 18:15:47 -0700
Subject: [PATCH 17/51] Add comment for future work
---
interface/src/Application.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index a38f4d022d..ae84491097 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -5534,6 +5534,9 @@ void Application::update(float deltaTime) {
_myCamera.loadViewFrustum(_viewFrustum);
+ // TODO: Fix this by modeling the way the secondary camera works on how the main camera works
+ // ie. Use a camera object stored in the game logic and informs the Engine on where the secondary
+ // camera should be.
auto renderConfig = _renderEngine->getConfiguration();
assert(renderConfig);
auto secondaryCamera = dynamic_cast(renderConfig->getConfig("SecondaryCamera"));
From 4c90763236dcd83d66d7476fed57dfd25e48895c Mon Sep 17 00:00:00 2001
From: Clement
Date: Wed, 18 Apr 2018 17:52:15 -0700
Subject: [PATCH 18/51] Correctly update secondary camera frustum
---
interface/src/Application.cpp | 92 +++++++++++++++++++++++++++--------
interface/src/Application.h | 2 +
2 files changed, 75 insertions(+), 19 deletions(-)
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index ae84491097..bbdae9218b 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -5179,6 +5179,78 @@ void Application::updateDialogs(float deltaTime) const {
}
}
+void Application::updateSecondaryCameraViewFrustum() {
+ // TODO: Fix this by modeling the way the secondary camera works on how the main camera works
+ // ie. Use a camera object stored in the game logic and informs the Engine on where the secondary
+ // camera should be.
+
+ // Code based on SecondaryCameraJob
+ auto renderConfig = _renderEngine->getConfiguration();
+ assert(renderConfig);
+ auto camera = dynamic_cast(renderConfig->getConfig("SecondaryCamera"));
+ assert(camera);
+
+ if (!camera->isEnabled()) {
+ _hasSecondaryViewFrustum = false;
+ return;
+ }
+
+ if (camera->mirrorProjection && !camera->attachedEntityId.isNull()) {
+ auto entityScriptingInterface = DependencyManager::get();
+ auto entityProperties = entityScriptingInterface->getEntityProperties(camera->attachedEntityId);
+ glm::vec3 mirrorPropertiesPosition = entityProperties.getPosition();
+ glm::quat mirrorPropertiesRotation = entityProperties.getRotation();
+ glm::vec3 mirrorPropertiesDimensions = entityProperties.getDimensions();
+ glm::vec3 halfMirrorPropertiesDimensions = 0.5f * mirrorPropertiesDimensions;
+
+ // setup mirror from world as inverse of world from mirror transformation using inverted x and z for mirrored image
+ // TODO: we are assuming here that UP is world y-axis
+ glm::mat4 worldFromMirrorRotation = glm::mat4_cast(mirrorPropertiesRotation) * glm::scale(vec3(-1.0f, 1.0f, -1.0f));
+ glm::mat4 worldFromMirrorTranslation = glm::translate(mirrorPropertiesPosition);
+ glm::mat4 worldFromMirror = worldFromMirrorTranslation * worldFromMirrorRotation;
+ glm::mat4 mirrorFromWorld = glm::inverse(worldFromMirror);
+
+ // get mirror camera position by reflecting main camera position's z coordinate in mirror space
+ glm::vec3 mainCameraPositionWorld = getCamera().getPosition();
+ glm::vec3 mainCameraPositionMirror = vec3(mirrorFromWorld * vec4(mainCameraPositionWorld, 1.0f));
+ glm::vec3 mirrorCameraPositionMirror = vec3(mainCameraPositionMirror.x, mainCameraPositionMirror.y,
+ -mainCameraPositionMirror.z);
+ glm::vec3 mirrorCameraPositionWorld = vec3(worldFromMirror * vec4(mirrorCameraPositionMirror, 1.0f));
+
+ // set frustum position to be mirrored camera and set orientation to mirror's adjusted rotation
+ glm::quat mirrorCameraOrientation = glm::quat_cast(worldFromMirrorRotation);
+ _secondaryViewFrustum.setPosition(mirrorCameraPositionWorld);
+ _secondaryViewFrustum.setOrientation(mirrorCameraOrientation);
+
+ // build frustum using mirror space translation of mirrored camera
+ float nearClip = mirrorCameraPositionMirror.z + mirrorPropertiesDimensions.z * 2.0f;
+ glm::vec3 upperRight = halfMirrorPropertiesDimensions - mirrorCameraPositionMirror;
+ glm::vec3 bottomLeft = -halfMirrorPropertiesDimensions - mirrorCameraPositionMirror;
+ glm::mat4 frustum = glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, camera->farClipPlaneDistance);
+ _secondaryViewFrustum.setProjection(frustum);
+ } else {
+ if (!camera->attachedEntityId.isNull()) {
+ auto entityScriptingInterface = DependencyManager::get();
+ auto entityProperties = entityScriptingInterface->getEntityProperties(camera->attachedEntityId);
+ _secondaryViewFrustum.setPosition(entityProperties.getPosition());
+ _secondaryViewFrustum.setOrientation(entityProperties.getRotation());
+ } else {
+ _secondaryViewFrustum.setPosition(camera->position);
+ _secondaryViewFrustum.setOrientation(camera->orientation);
+ }
+
+ float aspectRatio = (float)camera->textureWidth / (float)camera->textureHeight;
+ _secondaryViewFrustum.setProjection(camera->vFoV,
+ aspectRatio,
+ camera->nearClipPlaneDistance,
+ camera->farClipPlaneDistance);
+ }
+ // Without calculating the bound planes, the secondary camera will use the same culling frustum as the main camera,
+ // which is not what we want here.
+ _secondaryViewFrustum.calculate();
+ _hasSecondaryViewFrustum = true;
+}
+
static bool domainLoadingInProgress = false;
void Application::update(float deltaTime) {
@@ -5533,28 +5605,10 @@ void Application::update(float deltaTime) {
QMutexLocker viewLocker(&_viewMutex);
_myCamera.loadViewFrustum(_viewFrustum);
-
// TODO: Fix this by modeling the way the secondary camera works on how the main camera works
// ie. Use a camera object stored in the game logic and informs the Engine on where the secondary
// camera should be.
- auto renderConfig = _renderEngine->getConfiguration();
- assert(renderConfig);
- auto secondaryCamera = dynamic_cast(renderConfig->getConfig("SecondaryCamera"));
- assert(secondaryCamera);
-
- if (secondaryCamera->isEnabled()) {
- _secondaryViewFrustum.setPosition(secondaryCamera->position);
- _secondaryViewFrustum.setOrientation(secondaryCamera->orientation);
- _secondaryViewFrustum.setProjection(secondaryCamera->vFoV,
- secondaryCamera->textureWidth / secondaryCamera->textureHeight,
- secondaryCamera->nearClipPlaneDistance,
- secondaryCamera->farClipPlaneDistance);
- _secondaryViewFrustum.calculate();
- _hasSecondaryViewFrustum = true;
- } else {
- _hasSecondaryViewFrustum = false;
- }
-
+ updateSecondaryCameraViewFrustum();
}
quint64 now = usecTimestampNow();
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 043a9b52ab..f31ca6547e 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -149,6 +149,8 @@ public:
void initializeRenderEngine();
void initializeUi();
+ void updateSecondaryCameraViewFrustum();
+
void updateCamera(RenderArgs& renderArgs, float deltaTime);
void paintGL();
void resizeGL();
From 0820ef3c9582a89388090e3e929b3cd7a5010d8a Mon Sep 17 00:00:00 2001
From: Atlante45
Date: Wed, 18 Apr 2018 20:19:27 -0700
Subject: [PATCH 19/51] Account for secondary view when deciding to query
---
interface/src/Application.cpp | 3 +++
interface/src/Application.h | 3 ++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index bbdae9218b..a5b859628f 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -5622,6 +5622,8 @@ void Application::update(float deltaTime) {
const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND;
bool queryIsDue = sinceLastQuery > TOO_LONG_SINCE_LAST_QUERY;
bool viewIsDifferentEnough = !_lastQueriedViewFrustum.isVerySimilar(_viewFrustum);
+ viewIsDifferentEnough |= _hasSecondaryViewFrustum && !_lastQueriedSecondaryViewFrustum.isVerySimilar(_secondaryViewFrustum);
+
// if it's been a while since our last query or the view has significantly changed then send a query, otherwise suppress it
if (queryIsDue || viewIsDifferentEnough) {
_lastQueriedTime = now;
@@ -5630,6 +5632,7 @@ void Application::update(float deltaTime) {
}
sendAvatarViewFrustum();
_lastQueriedViewFrustum = _viewFrustum;
+ _lastQueriedSecondaryViewFrustum = _secondaryViewFrustum;
}
}
diff --git a/interface/src/Application.h b/interface/src/Application.h
index f31ca6547e..eed6ceeae5 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -557,9 +557,10 @@ private:
mutable QMutex _viewMutex { QMutex::Recursive };
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
- ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels)
+ ViewFrustum _lastQueriedViewFrustum; // last view frustum used to query octree servers
ViewFrustum _displayViewFrustum;
ViewFrustum _secondaryViewFrustum;
+ ViewFrustum _lastQueriedSecondaryViewFrustum; // last secondary view frustum used to query octree servers
bool _hasSecondaryViewFrustum;
quint64 _lastQueriedTime;
From 30d14dcd45834c7241b67b3be63430399417f386 Mon Sep 17 00:00:00 2001
From: Clement
Date: Thu, 19 Apr 2018 13:23:24 -0700
Subject: [PATCH 20/51] Push packet version
---
libraries/networking/src/udt/PacketHeaders.cpp | 2 +-
libraries/networking/src/udt/PacketHeaders.h | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp
index 98b0e1d892..b16f9c903e 100644
--- a/libraries/networking/src/udt/PacketHeaders.cpp
+++ b/libraries/networking/src/udt/PacketHeaders.cpp
@@ -34,7 +34,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::EntityPhysics:
return static_cast(EntityVersion::MaterialData);
case PacketType::EntityQuery:
- return static_cast(EntityQueryPacketVersion::RemovedJurisdictions);
+ return static_cast(EntityQueryPacketVersion::MultiFrustumQuery);
case PacketType::AvatarIdentity:
case PacketType::AvatarData:
case PacketType::BulkAvatarData:
diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h
index e6b133c158..9b48e3a132 100644
--- a/libraries/networking/src/udt/PacketHeaders.h
+++ b/libraries/networking/src/udt/PacketHeaders.h
@@ -244,7 +244,8 @@ enum class EntityQueryPacketVersion: PacketVersion {
JSONFilter = 18,
JSONFilterWithFamilyTree = 19,
ConnectionIdentifier = 20,
- RemovedJurisdictions = 21
+ RemovedJurisdictions = 21,
+ MultiFrustumQuery = 22
};
enum class AssetServerPacketVersion: PacketVersion {
From d47ddbd6e4f5a9e09425fb9b8c51e215e195672d Mon Sep 17 00:00:00 2001
From: Clement
Date: Tue, 1 May 2018 18:02:15 -0700
Subject: [PATCH 21/51] CR
---
assignment-client/src/entities/EntityPriorityQueue.h | 5 +++--
.../src/entities/EntityTreeSendThread.cpp | 11 ++++-------
libraries/entities/src/DiffTraversal.cpp | 2 +-
3 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/assignment-client/src/entities/EntityPriorityQueue.h b/assignment-client/src/entities/EntityPriorityQueue.h
index 730e08591e..9210ac549f 100644
--- a/assignment-client/src/entities/EntityPriorityQueue.h
+++ b/assignment-client/src/entities/EntityPriorityQueue.h
@@ -22,7 +22,7 @@
const float SQRT_TWO_OVER_TWO = 0.7071067811865f;
const float DEFAULT_VIEW_RADIUS = 10.0f;
-// ConicalView is an approximation of a ViewFrustum for fast calculation of sort priority.
+// ConicalViewFrustum is an approximation of a ViewFrustum for fast calculation of sort priority.
class ConicalViewFrustum {
public:
ConicalViewFrustum() {}
@@ -37,6 +37,7 @@ private:
float _radius { DEFAULT_VIEW_RADIUS };
};
+// Simple wrapper around a set of conical view frustums
class ConicalView {
public:
ConicalView() {}
@@ -113,7 +114,7 @@ private:
PrioritizedEntity::Compare>;
PriorityQueue _queue;
- // Keep dictionary of al the entities in the queue for fast contain checks.
+ // Keep dictionary of all the entities in the queue for fast contain checks.
std::unordered_set _entities;
};
diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp
index ae7de01c3e..2e57f2e00f 100644
--- a/assignment-client/src/entities/EntityTreeSendThread.cpp
+++ b/assignment-client/src/entities/EntityTreeSendThread.cpp
@@ -138,7 +138,6 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
if (entity) {
float priority = PrioritizedEntity::DO_NOT_SEND;
-
if (forceRemove) {
priority = PrioritizedEntity::FORCE_REMOVE;
} else {
@@ -154,7 +153,6 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
}
}
-
if (priority != PrioritizedEntity::DO_NOT_SEND) {
_sendQueue.emplace(entity, priority, forceRemove);
}
@@ -305,7 +303,8 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
} else {
priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY;
}
- } else if (entity->getLastEdited() > knownTimestamp->second) {
+ } else if (entity->getLastEdited() > knownTimestamp->second ||
+ entity->getLastChangedOnServer() > knownTimestamp->second) {
// it is known and it changed --> put it on the queue with any priority
// TODO: sort these correctly
priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY;
@@ -339,15 +338,13 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
// See the DiffTraversal::First case for an explanation of the "entity is too small" check
if ((next.intersection == ViewFrustum::INSIDE || view.intersects(cube)) &&
view.isBigEnough(cube)) {
- // If this entity wasn't in the last view or
- // If this entity was skipped last time because it was too small, we still need to send it
priority = _conicalView.computePriority(cube);
}
} else {
priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY;
}
- } else if (entity->getLastEdited() > knownTimestamp->second
- || entity->getLastChangedOnServer() > knownTimestamp->second) {
+ } else if (entity->getLastEdited() > knownTimestamp->second ||
+ entity->getLastChangedOnServer() > knownTimestamp->second) {
// it is known and it changed --> put it on the queue with any priority
// TODO: sort these correctly
priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY;
diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp
index d5f2273fd5..39328e11ad 100644
--- a/libraries/entities/src/DiffTraversal.cpp
+++ b/libraries/entities/src/DiffTraversal.cpp
@@ -221,7 +221,7 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const DiffTraversal::View
//
// _getNextVisibleElementCallback = identifies elements that need to be traversed,
// updates VisibleElement ref argument with pointer-to-element and view-intersection
- // (INSIDE, INTERSECtT, or OUTSIDE)
+ // (INSIDE, INTERSECT, or OUTSIDE)
//
// external code should update the _scanElementCallback after calling prepareNewTraversal
//
From 21213e81f4bda569b8cca9db2088ec3375fe1d71 Mon Sep 17 00:00:00 2001
From: Clement
Date: Wed, 18 Apr 2018 16:21:03 -0700
Subject: [PATCH 22/51] Multiview support for priority queue
---
.../src/avatars/AvatarMixerSlave.cpp | 2 +-
interface/src/Application.h | 6 ++--
interface/src/avatar/AvatarManager.cpp | 16 +++++++--
.../src/EntityTreeRenderer.cpp | 20 ++++++++---
.../src/EntityTreeRenderer.h | 3 +-
.../src/AbstractViewStateInterface.h | 4 +++
libraries/shared/src/PrioritySortUtil.h | 33 ++++++++++++-------
tests/render-perf/src/main.cpp | 10 ++++++
8 files changed, 71 insertions(+), 23 deletions(-)
diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp
index 6f19b73cc5..da9b7934ad 100644
--- a/assignment-client/src/avatars/AvatarMixerSlave.cpp
+++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp
@@ -223,7 +223,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
// prepare to sort
ViewFrustum cameraView = nodeData->getViewFrustum();
- PrioritySortUtil::PriorityQueue sortedAvatars(cameraView,
+ PrioritySortUtil::PriorityQueue sortedAvatars({cameraView},
AvatarData::_avatarSortCoefficientSize,
AvatarData::_avatarSortCoefficientCenter,
AvatarData::_avatarSortCoefficientAge);
diff --git a/interface/src/Application.h b/interface/src/Application.h
index eed6ceeae5..256f428d12 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -175,13 +175,13 @@ public:
Camera& getCamera() { return _myCamera; }
const Camera& getCamera() const { return _myCamera; }
// Represents the current view frustum of the avatar.
- void copyViewFrustum(ViewFrustum& viewOut) const;
+ void copyViewFrustum(ViewFrustum& viewOut) const override;
+ void copySecondaryViewFrustum(ViewFrustum& viewOut) const override;
+ bool hasSecondaryViewFrustum() const override { return _hasSecondaryViewFrustum; }
// Represents the view frustum of the current rendering pass,
// which might be different from the viewFrustum, i.e. shadowmap
// passes, mirror window passes, etc
void copyDisplayViewFrustum(ViewFrustum& viewOut) const;
- void copySecondaryViewFrustum(ViewFrustum& viewOut) const;
- bool hasSecondaryViewFrustum() const { return _hasSecondaryViewFrustum; }
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
QSharedPointer getEntities() const { return DependencyManager::get(); }
diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp
index b71c060465..cd20fd9350 100644
--- a/interface/src/avatar/AvatarManager.cpp
+++ b/interface/src/avatar/AvatarManager.cpp
@@ -155,9 +155,19 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
AvatarSharedPointer _avatar;
};
- ViewFrustum cameraView;
- qApp->copyDisplayViewFrustum(cameraView);
- PrioritySortUtil::PriorityQueue sortedAvatars(cameraView,
+
+ std::vector views;
+
+ ViewFrustum view;
+ qApp->copyCurrentViewFrustum(view);
+ views.push_back(view);
+
+ if (qApp->hasSecondaryViewFrustum()) {
+ qApp->copySecondaryViewFrustum(view);
+ views.push_back(view);
+ }
+
+ PrioritySortUtil::PriorityQueue sortedAvatars(views,
AvatarData::_avatarSortCoefficientSize,
AvatarData::_avatarSortCoefficientCenter,
AvatarData::_avatarSortCoefficientAge);
diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
index ba81922979..511fa33591 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
@@ -296,7 +296,8 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r
}
}
-void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, const ViewFrustum& view, render::Transaction& transaction) {
+void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, const std::vector& views,
+ render::Transaction& transaction) {
PROFILE_RANGE_EX(simulation_physics, "ChangeInScene", 0xffff00ff, (uint64_t)_changedEntities.size());
PerformanceTimer pt("change");
std::unordered_set changedEntities;
@@ -357,7 +358,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
// prioritize and sort the renderables
uint64_t sortStart = usecTimestampNow();
- PrioritySortUtil::PriorityQueue sortedRenderables(view);
+ PrioritySortUtil::PriorityQueue sortedRenderables(views);
{
PROFILE_RANGE_EX(simulation_physics, "SortRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size());
std::unordered_map::iterator itr = _renderablesToUpdate.begin();
@@ -415,9 +416,20 @@ void EntityTreeRenderer::update(bool simulate) {
if (scene) {
render::Transaction transaction;
addPendingEntities(scene, transaction);
+
+ std::vector views;
+
ViewFrustum view;
- _viewState->copyCurrentViewFrustum(view);
- updateChangedEntities(scene, view, transaction);
+ _viewState->copyViewFrustum(view);
+ views.push_back(view);
+
+ if (_viewState->hasSecondaryViewFrustum()) {
+ _viewState->copySecondaryViewFrustum(view);
+ views.push_back(view);
+ }
+
+
+ updateChangedEntities(scene, views, transaction);
scene->enqueueTransaction(transaction);
}
}
diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h
index f5cedfdd01..7a7920d5b2 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.h
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.h
@@ -148,7 +148,8 @@ protected:
private:
void addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction);
- void updateChangedEntities(const render::ScenePointer& scene, const ViewFrustum& view, render::Transaction& transaction);
+ void updateChangedEntities(const render::ScenePointer& scene, const std::vector& views,
+ render::Transaction& transaction);
EntityRendererPointer renderableForEntity(const EntityItemPointer& entity) const { return renderableForEntityId(entity->getID()); }
render::ItemID renderableIdForEntity(const EntityItemPointer& entity) const { return renderableIdForEntityId(entity->getID()); }
diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h
index 54fdc903ca..9d781b7d18 100644
--- a/libraries/render-utils/src/AbstractViewStateInterface.h
+++ b/libraries/render-utils/src/AbstractViewStateInterface.h
@@ -31,6 +31,10 @@ public:
/// copies the current view frustum for rendering the view state
virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const = 0;
+ virtual void copyViewFrustum(ViewFrustum& viewOut) const = 0;
+ virtual void copySecondaryViewFrustum(ViewFrustum& viewOut) const = 0;
+ virtual bool hasSecondaryViewFrustum() const = 0;
+
virtual QThread* getMainThread() = 0;
virtual PickRay computePickRay(float x, float y) const = 0;
diff --git a/libraries/shared/src/PrioritySortUtil.h b/libraries/shared/src/PrioritySortUtil.h
index 279fa42ea4..7c0f30ec75 100644
--- a/libraries/shared/src/PrioritySortUtil.h
+++ b/libraries/shared/src/PrioritySortUtil.h
@@ -83,15 +83,15 @@ namespace PrioritySortUtil {
template
class PriorityQueue {
public:
+ using Views = std::vector;
+
PriorityQueue() = delete;
-
- PriorityQueue(const ViewFrustum& view) : _view(view) { }
-
- PriorityQueue(const ViewFrustum& view, float angularWeight, float centerWeight, float ageWeight)
- : _view(view), _angularWeight(angularWeight), _centerWeight(centerWeight), _ageWeight(ageWeight)
+ PriorityQueue(const Views& views) : _views(views) { }
+ PriorityQueue(const Views& views, float angularWeight, float centerWeight, float ageWeight)
+ : _views(views), _angularWeight(angularWeight), _centerWeight(centerWeight), _ageWeight(ageWeight)
{ }
- void setView(const ViewFrustum& view) { _view = view; }
+ void setViews(const Views& views) { _views = views; }
void setWeights(float angularWeight, float centerWeight, float ageWeight) {
_angularWeight = angularWeight;
@@ -109,7 +109,18 @@ namespace PrioritySortUtil {
bool empty() const { return _queue.empty(); }
private:
+
float computePriority(const T& thing) const {
+ float priority = std::numeric_limits::min();
+
+ for (const auto& view : _views) {
+ priority = std::max(priority, computePriority(view, thing));
+ }
+
+ return priority;
+ }
+
+ float computePriority(const ViewFrustum& view, const T& thing) const {
// priority = weighted linear combination of multiple values:
// (a) angular size
// (b) proximity to center of view
@@ -117,11 +128,11 @@ namespace PrioritySortUtil {
// where the relative "weights" are tuned to scale the contributing values into units of "priority".
glm::vec3 position = thing.getPosition();
- glm::vec3 offset = position - _view.getPosition();
+ glm::vec3 offset = position - view.getPosition();
float distance = glm::length(offset) + 0.001f; // add 1mm to avoid divide by zero
const float MIN_RADIUS = 0.1f; // WORKAROUND for zero size objects (we still want them to sort by distance)
float radius = glm::min(thing.getRadius(), MIN_RADIUS);
- float cosineAngle = (glm::dot(offset, _view.getDirection()) / distance);
+ float cosineAngle = (glm::dot(offset, view.getDirection()) / distance);
float age = (float)(usecTimestampNow() - thing.getTimestamp());
// we modulatate "age" drift rate by the cosineAngle term to make periphrial objects sort forward
@@ -134,8 +145,8 @@ namespace PrioritySortUtil {
+ _ageWeight * cosineAngleFactor * age;
// decrement priority of things outside keyhole
- if (distance - radius > _view.getCenterRadius()) {
- if (!_view.sphereIntersectsFrustum(position, radius)) {
+ if (distance - radius > view.getCenterRadius()) {
+ if (!view.sphereIntersectsFrustum(position, radius)) {
constexpr float OUT_OF_VIEW_PENALTY = -10.0f;
priority += OUT_OF_VIEW_PENALTY;
}
@@ -143,7 +154,7 @@ namespace PrioritySortUtil {
return priority;
}
- ViewFrustum _view;
+ Views _views;
std::priority_queue _queue;
float _angularWeight { DEFAULT_ANGULAR_COEF };
float _centerWeight { DEFAULT_CENTER_COEF };
diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp
index 9249b3d957..8c17d7c5c2 100644
--- a/tests/render-perf/src/main.cpp
+++ b/tests/render-perf/src/main.cpp
@@ -441,6 +441,16 @@ protected:
viewOut = _viewFrustum;
}
+ void copyViewFrustum(ViewFrustum& viewOut) const override {
+ viewOut = _viewFrustum;
+ }
+
+ void copySecondaryViewFrustum(ViewFrustum& viewOut) const override {}
+
+ bool hasSecondaryViewFrustum() const override {
+ return false;
+ }
+
QThread* getMainThread() override {
return QThread::currentThread();
}
From 1b2b70b7691b65cfa96881cddd005a6f2d664147 Mon Sep 17 00:00:00 2001
From: Clement
Date: Mon, 23 Apr 2018 15:47:05 -0700
Subject: [PATCH 23/51] Send both frustums to Avatar Mixer
---
assignment-client/src/avatars/AvatarMixer.cpp | 8 +++-----
.../src/avatars/AvatarMixerClientData.cpp | 16 ++++++++++++----
.../src/avatars/AvatarMixerClientData.h | 4 ++--
.../src/avatars/AvatarMixerSlave.cpp | 4 ++--
interface/src/Application.cpp | 4 ++++
5 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp
index 29340f6474..6353a1664f 100644
--- a/assignment-client/src/avatars/AvatarMixer.cpp
+++ b/assignment-client/src/avatars/AvatarMixer.cpp
@@ -521,11 +521,9 @@ void AvatarMixer::handleViewFrustumPacket(QSharedPointer messag
auto start = usecTimestampNow();
getOrCreateClientData(senderNode);
- if (senderNode->getLinkedData()) {
- AvatarMixerClientData* nodeData = dynamic_cast(senderNode->getLinkedData());
- if (nodeData != nullptr) {
- nodeData->readViewFrustumPacket(message->getMessage());
- }
+ AvatarMixerClientData* nodeData = dynamic_cast(senderNode->getLinkedData());
+ if (nodeData) {
+ nodeData->readViewFrustumPacket(message->getMessage());
}
auto end = usecTimestampNow();
diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp
index 268aba62d6..8c159cf744 100644
--- a/assignment-client/src/avatars/AvatarMixerClientData.cpp
+++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp
@@ -19,8 +19,6 @@
AvatarMixerClientData::AvatarMixerClientData(const QUuid& nodeID) :
NodeData(nodeID)
{
- _currentViewFrustum.invalidate();
-
// in case somebody calls getSessionUUID on the AvatarData instance, make sure it has the right ID
_avatar->setID(nodeID);
}
@@ -129,11 +127,21 @@ void AvatarMixerClientData::removeFromRadiusIgnoringSet(SharedNodePointer self,
}
void AvatarMixerClientData::readViewFrustumPacket(const QByteArray& message) {
- _currentViewFrustum.fromByteArray(message);
+ _currentViewFrustums.clear();
+
+ auto offset = 0;
+ while (offset < message.size()) {
+ ViewFrustum frustum;
+ offset += frustum.fromByteArray(message);
+ _currentViewFrustums.push_back(frustum);
+ }
}
bool AvatarMixerClientData::otherAvatarInView(const AABox& otherAvatarBox) {
- return _currentViewFrustum.boxIntersectsKeyhole(otherAvatarBox);
+ return std::any_of(std::begin(_currentViewFrustums), std::end(_currentViewFrustums),
+ [&](const ViewFrustum& viewFrustum) {
+ return viewFrustum.boxIntersectsKeyhole(otherAvatarBox);
+ });
}
void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const {
diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h
index 6963f4df0d..4b06617175 100644
--- a/assignment-client/src/avatars/AvatarMixerClientData.h
+++ b/assignment-client/src/avatars/AvatarMixerClientData.h
@@ -110,7 +110,7 @@ public:
bool getRequestsDomainListData() { return _requestsDomainListData; }
void setRequestsDomainListData(bool requesting) { _requestsDomainListData = requesting; }
- ViewFrustum getViewFrustum() const { return _currentViewFrustum; }
+ const std::vector& getViewFrustums() const { return _currentViewFrustums; }
uint64_t getLastOtherAvatarEncodeTime(QUuid otherAvatar) const;
void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time);
@@ -150,7 +150,7 @@ private:
SimpleMovingAverage _avgOtherAvatarDataRate;
std::unordered_set _radiusIgnoredOthers;
- ViewFrustum _currentViewFrustum;
+ std::vector _currentViewFrustums;
int _recentOtherAvatarsInView { 0 };
int _recentOtherAvatarsOutOfView { 0 };
diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp
index da9b7934ad..30d94ed772 100644
--- a/assignment-client/src/avatars/AvatarMixerSlave.cpp
+++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp
@@ -222,8 +222,8 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
};
// prepare to sort
- ViewFrustum cameraView = nodeData->getViewFrustum();
- PrioritySortUtil::PriorityQueue sortedAvatars({cameraView},
+ const auto& cameraViews = nodeData->getViewFrustums();
+ PrioritySortUtil::PriorityQueue sortedAvatars(cameraViews,
AvatarData::_avatarSortCoefficientSize,
AvatarData::_avatarSortCoefficientCenter,
AvatarData::_avatarSortCoefficientAge);
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index a5b859628f..33c334b493 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -5806,6 +5806,10 @@ void Application::update(float deltaTime) {
void Application::sendAvatarViewFrustum() {
QByteArray viewFrustumByteArray = _viewFrustum.toByteArray();
+ if (hasSecondaryViewFrustum()) {
+ viewFrustumByteArray += _viewFrustum.toByteArray();
+ }
+
auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size());
avatarPacket->write(viewFrustumByteArray);
From 538f24162f3ecc2892ca361a0339eced1087113f Mon Sep 17 00:00:00 2001
From: Clement
Date: Mon, 23 Apr 2018 15:57:21 -0700
Subject: [PATCH 24/51] Define ViewFrustums type alias
---
assignment-client/src/avatars/AvatarMixerClientData.h | 4 ++--
interface/src/avatar/AvatarManager.cpp | 2 +-
libraries/entities-renderer/src/EntityTreeRenderer.cpp | 4 ++--
libraries/entities-renderer/src/EntityTreeRenderer.h | 2 +-
libraries/entities/src/DiffTraversal.h | 2 +-
libraries/shared/src/PrioritySortUtil.h | 10 ++++------
libraries/shared/src/ViewFrustum.h | 1 +
7 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h
index 4b06617175..13415d6a66 100644
--- a/assignment-client/src/avatars/AvatarMixerClientData.h
+++ b/assignment-client/src/avatars/AvatarMixerClientData.h
@@ -110,7 +110,7 @@ public:
bool getRequestsDomainListData() { return _requestsDomainListData; }
void setRequestsDomainListData(bool requesting) { _requestsDomainListData = requesting; }
- const std::vector& getViewFrustums() const { return _currentViewFrustums; }
+ const ViewFrustums& getViewFrustums() const { return _currentViewFrustums; }
uint64_t getLastOtherAvatarEncodeTime(QUuid otherAvatar) const;
void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time);
@@ -150,7 +150,7 @@ private:
SimpleMovingAverage _avgOtherAvatarDataRate;
std::unordered_set _radiusIgnoredOthers;
- std::vector _currentViewFrustums;
+ ViewFrustums _currentViewFrustums;
int _recentOtherAvatarsInView { 0 };
int _recentOtherAvatarsOutOfView { 0 };
diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp
index cd20fd9350..087e23a933 100644
--- a/interface/src/avatar/AvatarManager.cpp
+++ b/interface/src/avatar/AvatarManager.cpp
@@ -156,7 +156,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
};
- std::vector views;
+ ViewFrustums views;
ViewFrustum view;
qApp->copyCurrentViewFrustum(view);
diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
index 511fa33591..6dd13c7332 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
@@ -296,7 +296,7 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r
}
}
-void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, const std::vector& views,
+void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, const ViewFrustums& views,
render::Transaction& transaction) {
PROFILE_RANGE_EX(simulation_physics, "ChangeInScene", 0xffff00ff, (uint64_t)_changedEntities.size());
PerformanceTimer pt("change");
@@ -417,7 +417,7 @@ void EntityTreeRenderer::update(bool simulate) {
render::Transaction transaction;
addPendingEntities(scene, transaction);
- std::vector views;
+ ViewFrustums views;
ViewFrustum view;
_viewState->copyViewFrustum(view);
diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h
index 7a7920d5b2..9ed4f9d21d 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.h
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.h
@@ -148,7 +148,7 @@ protected:
private:
void addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction);
- void updateChangedEntities(const render::ScenePointer& scene, const std::vector& views,
+ void updateChangedEntities(const render::ScenePointer& scene, const ViewFrustums& views,
render::Transaction& transaction);
EntityRendererPointer renderableForEntity(const EntityItemPointer& entity) const { return renderableForEntityId(entity->getID()); }
render::ItemID renderableIdForEntity(const EntityItemPointer& entity) const { return renderableIdForEntityId(entity->getID()); }
diff --git a/libraries/entities/src/DiffTraversal.h b/libraries/entities/src/DiffTraversal.h
index 50fe74a75b..0fd014ac23 100644
--- a/libraries/entities/src/DiffTraversal.h
+++ b/libraries/entities/src/DiffTraversal.h
@@ -36,7 +36,7 @@ public:
bool isVerySimilar(const View& view) const;
ViewFrustum::intersection calculateIntersection(const AACube& cube) const;
- std::vector viewFrustums;
+ ViewFrustums viewFrustums;
uint64_t startTime { 0 };
float lodScaleFactor { 1.0f };
};
diff --git a/libraries/shared/src/PrioritySortUtil.h b/libraries/shared/src/PrioritySortUtil.h
index 7c0f30ec75..ba15222611 100644
--- a/libraries/shared/src/PrioritySortUtil.h
+++ b/libraries/shared/src/PrioritySortUtil.h
@@ -83,15 +83,13 @@ namespace PrioritySortUtil {
template
class PriorityQueue {
public:
- using Views = std::vector;
-
PriorityQueue() = delete;
- PriorityQueue(const Views& views) : _views(views) { }
- PriorityQueue(const Views& views, float angularWeight, float centerWeight, float ageWeight)
+ PriorityQueue(const ViewFrustums& views) : _views(views) { }
+ PriorityQueue(const ViewFrustums& views, float angularWeight, float centerWeight, float ageWeight)
: _views(views), _angularWeight(angularWeight), _centerWeight(centerWeight), _ageWeight(ageWeight)
{ }
- void setViews(const Views& views) { _views = views; }
+ void setViews(const ViewFrustums& views) { _views = views; }
void setWeights(float angularWeight, float centerWeight, float ageWeight) {
_angularWeight = angularWeight;
@@ -154,7 +152,7 @@ namespace PrioritySortUtil {
return priority;
}
- Views _views;
+ ViewFrustums _views;
std::priority_queue _queue;
float _angularWeight { DEFAULT_ANGULAR_COEF };
float _centerWeight { DEFAULT_CENTER_COEF };
diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h
index ba8957bba3..128a717df8 100644
--- a/libraries/shared/src/ViewFrustum.h
+++ b/libraries/shared/src/ViewFrustum.h
@@ -189,5 +189,6 @@ private:
};
using ViewFrustumPointer = std::shared_ptr;
+using ViewFrustums = std::vector;
#endif // hifi_ViewFrustum_h
From ddde0228ba3b1fd6b8a3006101594ff6ead9e2a8 Mon Sep 17 00:00:00 2001
From: Clement
Date: Mon, 23 Apr 2018 16:10:44 -0700
Subject: [PATCH 25/51] Fix AC not sending Avatar Mixer a frustum
---
assignment-client/src/Agent.cpp | 15 +++++++++++++++
assignment-client/src/Agent.h | 1 +
interface/src/Application.cpp | 4 ++--
3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp
index 1df901dd98..26bfb586a6 100644
--- a/assignment-client/src/Agent.cpp
+++ b/assignment-client/src/Agent.cpp
@@ -594,9 +594,24 @@ void Agent::sendAvatarIdentityPacket() {
auto scriptedAvatar = DependencyManager::get();
scriptedAvatar->markIdentityDataChanged();
scriptedAvatar->sendIdentityPacket();
+ sendAvatarViewFrustum();
}
}
+void Agent::sendAvatarViewFrustum() {
+ auto scriptedAvatar = DependencyManager::get();
+ ViewFrustum view;
+ view.setPosition(scriptedAvatar->getWorldPosition());
+ view.setOrientation(scriptedAvatar->getHeadOrientation());
+ auto viewFrustumByteArray = view.toByteArray();
+
+ auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size());
+ avatarPacket->write(viewFrustumByteArray);
+
+ DependencyManager::get()->broadcastToNodes(std::move(avatarPacket),
+ { NodeType::AvatarMixer });
+}
+
void Agent::processAgentAvatar() {
if (!_scriptEngine->isFinished() && _isAvatar) {
auto scriptedAvatar = DependencyManager::get();
diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h
index 1229f06276..e4ce0f95eb 100644
--- a/assignment-client/src/Agent.h
+++ b/assignment-client/src/Agent.h
@@ -97,6 +97,7 @@ private:
void setAvatarSound(SharedSoundPointer avatarSound) { _avatarSound = avatarSound; }
void sendAvatarIdentityPacket();
+ void sendAvatarViewFrustum();
QString _scriptContents;
QTimer* _scriptRequestTimeout { nullptr };
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 33c334b493..cdb535fad1 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -5806,8 +5806,8 @@ void Application::update(float deltaTime) {
void Application::sendAvatarViewFrustum() {
QByteArray viewFrustumByteArray = _viewFrustum.toByteArray();
- if (hasSecondaryViewFrustum()) {
- viewFrustumByteArray += _viewFrustum.toByteArray();
+ if (_hasSecondaryViewFrustum) {
+ viewFrustumByteArray += _secondaryViewFrustum.toByteArray();
}
auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size());
From a283d28686fcdb9aa138dad0d66e4d4ab5ccb2b4 Mon Sep 17 00:00:00 2001
From: Clement
Date: Tue, 24 Apr 2018 19:09:16 -0700
Subject: [PATCH 26/51] Send number of frustums in packet
---
assignment-client/src/Agent.cpp | 7 ++++++-
.../src/avatars/AvatarMixerClientData.cpp | 13 +++++++++----
.../src/avatars/AvatarMixerClientData.h | 2 +-
interface/src/Application.cpp | 6 +++++-
4 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp
index 26bfb586a6..8816ed9629 100644
--- a/assignment-client/src/Agent.cpp
+++ b/assignment-client/src/Agent.cpp
@@ -600,12 +600,17 @@ void Agent::sendAvatarIdentityPacket() {
void Agent::sendAvatarViewFrustum() {
auto scriptedAvatar = DependencyManager::get();
+
ViewFrustum view;
view.setPosition(scriptedAvatar->getWorldPosition());
view.setOrientation(scriptedAvatar->getHeadOrientation());
+ view.calculate();
+
+ uint8_t numFrustums = 1;
auto viewFrustumByteArray = view.toByteArray();
- auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size());
+ auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size() + sizeof(numFrustums));
+ avatarPacket->writePrimitive(numFrustums);
avatarPacket->write(viewFrustumByteArray);
DependencyManager::get()->broadcastToNodes(std::move(avatarPacket),
diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp
index 8c159cf744..a8e5a7c541 100644
--- a/assignment-client/src/avatars/AvatarMixerClientData.cpp
+++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp
@@ -126,13 +126,18 @@ void AvatarMixerClientData::removeFromRadiusIgnoringSet(SharedNodePointer self,
}
}
-void AvatarMixerClientData::readViewFrustumPacket(const QByteArray& message) {
+void AvatarMixerClientData::readViewFrustumPacket(QByteArray message) {
_currentViewFrustums.clear();
+
+ uint8_t numFrustums = 0;
+ memcpy(&numFrustums, message.constData(), sizeof(numFrustums));
+ message.remove(0, sizeof(numFrustums));
- auto offset = 0;
- while (offset < message.size()) {
+ for (uint8_t i = 0; i < numFrustums; ++i) {
ViewFrustum frustum;
- offset += frustum.fromByteArray(message);
+ auto bytesRead = frustum.fromByteArray(message);
+ message.remove(0, bytesRead);
+
_currentViewFrustums.push_back(frustum);
}
}
diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h
index 13415d6a66..f17404b79f 100644
--- a/assignment-client/src/avatars/AvatarMixerClientData.h
+++ b/assignment-client/src/avatars/AvatarMixerClientData.h
@@ -98,7 +98,7 @@ public:
void removeFromRadiusIgnoringSet(SharedNodePointer self, const QUuid& other);
void ignoreOther(SharedNodePointer self, SharedNodePointer other);
- void readViewFrustumPacket(const QByteArray& message);
+ void readViewFrustumPacket(QByteArray message);
bool otherAvatarInView(const AABox& otherAvatarBox);
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index cdb535fad1..c88b5981b4 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -5805,12 +5805,16 @@ void Application::update(float deltaTime) {
}
void Application::sendAvatarViewFrustum() {
+ uint8_t numFrustums = 1;
QByteArray viewFrustumByteArray = _viewFrustum.toByteArray();
+
if (_hasSecondaryViewFrustum) {
+ ++numFrustums;
viewFrustumByteArray += _secondaryViewFrustum.toByteArray();
}
- auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size());
+ auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size() + sizeof(numFrustums));
+ avatarPacket->writePrimitive(numFrustums);
avatarPacket->write(viewFrustumByteArray);
DependencyManager::get()->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer);
From 2ad948c46219e75bbfab174aea2aeb4674adadb7 Mon Sep 17 00:00:00 2001
From: Clement
Date: Tue, 24 Apr 2018 19:12:42 -0700
Subject: [PATCH 27/51] Bump ViewFrustum packet version
---
libraries/networking/src/udt/PacketHeaders.cpp | 2 ++
libraries/networking/src/udt/PacketHeaders.h | 4 ++++
2 files changed, 6 insertions(+)
diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp
index b16f9c903e..17b0d90cfe 100644
--- a/libraries/networking/src/udt/PacketHeaders.cpp
+++ b/libraries/networking/src/udt/PacketHeaders.cpp
@@ -90,6 +90,8 @@ PacketVersion versionForPacketType(PacketType packetType) {
return 18; // replace min_avatar_scale and max_avatar_scale with min_avatar_height and max_avatar_height
case PacketType::Ping:
return static_cast(PingVersion::IncludeConnectionID);
+ case PacketType::ViewFrustum:
+ return static_cast(ViewFrustumVersion::SendMultipleFrustums);
default:
return 20;
}
diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h
index 9b48e3a132..c72bbb0129 100644
--- a/libraries/networking/src/udt/PacketHeaders.h
+++ b/libraries/networking/src/udt/PacketHeaders.h
@@ -328,4 +328,8 @@ enum class PingVersion : PacketVersion {
IncludeConnectionID = 18
};
+enum class ViewFrustumVersion : PacketVersion {
+ SendMultipleFrustums = 21
+};
+
#endif // hifi_PacketHeaders_h
From 83a438eb22c02ea6a86301433588c119d023a1f3 Mon Sep 17 00:00:00 2001
From: Clement
Date: Tue, 1 May 2018 18:10:55 -0700
Subject: [PATCH 28/51] Set avatar view packets on their own timer
---
assignment-client/src/Agent.cpp | 10 ++++++++--
assignment-client/src/Agent.h | 1 +
libraries/avatars/src/AvatarData.h | 1 +
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp
index 8816ed9629..f560ea72bd 100644
--- a/assignment-client/src/Agent.cpp
+++ b/assignment-client/src/Agent.cpp
@@ -548,16 +548,18 @@ void Agent::setIsAvatar(bool isAvatar) {
if (_isAvatar && !_avatarIdentityTimer) {
// set up the avatar timers
_avatarIdentityTimer = new QTimer(this);
+ _avatarViewTimer = new QTimer(this);
// connect our slot
connect(_avatarIdentityTimer, &QTimer::timeout, this, &Agent::sendAvatarIdentityPacket);
+ connect(_avatarViewTimer, &QTimer::timeout, this, &Agent::sendAvatarViewFrustum);
// start the timers
_avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); // FIXME - we shouldn't really need to constantly send identity packets
+ _avatarViewTimer->start(AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS);
// tell the avatarAudioTimer to start ticking
QMetaObject::invokeMethod(&_avatarAudioTimer, "start");
-
}
if (!_isAvatar) {
@@ -567,6 +569,10 @@ void Agent::setIsAvatar(bool isAvatar) {
delete _avatarIdentityTimer;
_avatarIdentityTimer = nullptr;
+ _avatarViewTimer->stop();
+ delete _avatarViewTimer;
+ _avatarViewTimer = nullptr;
+
// The avatar mixer never times out a connection (e.g., based on identity or data packets)
// but rather keeps avatars in its list as long as "connected". As a result, clients timeout
// when we stop sending identity, but then get woken up again by the mixer itself, which sends
@@ -585,6 +591,7 @@ void Agent::setIsAvatar(bool isAvatar) {
nodeList->sendPacket(std::move(packet), *node);
});
}
+
QMetaObject::invokeMethod(&_avatarAudioTimer, "stop");
}
}
@@ -594,7 +601,6 @@ void Agent::sendAvatarIdentityPacket() {
auto scriptedAvatar = DependencyManager::get();
scriptedAvatar->markIdentityDataChanged();
scriptedAvatar->sendIdentityPacket();
- sendAvatarViewFrustum();
}
}
diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h
index e4ce0f95eb..d144f0bc01 100644
--- a/assignment-client/src/Agent.h
+++ b/assignment-client/src/Agent.h
@@ -107,6 +107,7 @@ private:
int _numAvatarSoundSentBytes = 0;
bool _isAvatar = false;
QTimer* _avatarIdentityTimer = nullptr;
+ QTimer* _avatarViewTimer = nullptr;
QHash _outgoingScriptAudioSequenceNumbers;
AudioGate _audioGate;
diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h
index 888c3bfb24..3db94f6691 100644
--- a/libraries/avatars/src/AvatarData.h
+++ b/libraries/avatars/src/AvatarData.h
@@ -278,6 +278,7 @@ namespace AvatarDataPacket {
const float MAX_AUDIO_LOUDNESS = 1000.0f; // close enough for mouth animation
const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000;
+const int AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS = 100;
// See also static AvatarData::defaultFullAvatarModelUrl().
const QString DEFAULT_FULL_AVATAR_MODEL_NAME = QString("Default");
From 5a064d3499681c6b1376007e550fb7cea8526010 Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Wed, 2 May 2018 14:13:15 +1200
Subject: [PATCH 29/51] Remove selection handles and list highlight when entity
deletes
---
scripts/system/edit.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/scripts/system/edit.js b/scripts/system/edit.js
index c99c8d401a..9b6b70b954 100644
--- a/scripts/system/edit.js
+++ b/scripts/system/edit.js
@@ -471,6 +471,10 @@ var toolBar = (function () {
}
}
+ function checkDeletedEntityAndUpdate(entityID) {
+ selectionManager.removeEntity(entityID);
+ }
+
function initialize() {
Script.scriptEnding.connect(cleanup);
Window.domainChanged.connect(function () {
@@ -493,8 +497,10 @@ var toolBar = (function () {
Entities.canRezTmpChanged.connect(checkEditPermissionsAndUpdate);
Entities.canRezCertifiedChanged.connect(checkEditPermissionsAndUpdate);
Entities.canRezTmpCertifiedChanged.connect(checkEditPermissionsAndUpdate);
-
var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified());
+
+ Entities.deletingEntity.connect(checkDeletedEntityAndUpdate);
+
var createButtonIconRsrc = (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON);
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
activeButton = tablet.addButton({
From f27e363b6879d6a3e064ee45e91fafcb770ad465 Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Wed, 2 May 2018 15:23:13 +1200
Subject: [PATCH 30/51] Remove entity from list when it deletes; handle
multiple deletions
---
scripts/system/edit.js | 17 ++++++++++++++++-
scripts/system/libraries/entitySelectionTool.js | 11 +++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/scripts/system/edit.js b/scripts/system/edit.js
index 9b6b70b954..6bb815a597 100644
--- a/scripts/system/edit.js
+++ b/scripts/system/edit.js
@@ -471,8 +471,23 @@ var toolBar = (function () {
}
}
+ var entitiesToDelete = [];
+ var deletedEntityTimer = null;
+ var DELETE_ENTITY_TIMER_TIMEOUT = 100;
+
function checkDeletedEntityAndUpdate(entityID) {
- selectionManager.removeEntity(entityID);
+ // Allow for multiple entity deletes before updating the entity list.
+ entitiesToDelete.push(entityID);
+ if (deletedEntityTimer !== null) {
+ Script.clearTimeout(deletedEntityTimer);
+ }
+ deletedEntityTimer = Script.setTimeout(function () {
+ selectionManager.removeEntities(entitiesToDelete);
+ entityListTool.clearEntityList();
+ entityListTool.sendUpdate();
+ entitiesToDelete = [];
+ deletedEntityTimer = null;
+ }, DELETE_ENTITY_TIMER_TIMEOUT);
}
function initialize() {
diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js
index 2322210522..4996579799 100644
--- a/scripts/system/libraries/entitySelectionTool.js
+++ b/scripts/system/libraries/entitySelectionTool.js
@@ -149,6 +149,17 @@ SelectionManager = (function() {
that._update(true);
};
+ that.removeEntities = function (entityIDs) {
+ for (var i = 0, length = entityIDs.length; i < length; i++) {
+ var idx = that.selections.indexOf(entityIDs[i]);
+ if (idx >= 0) {
+ that.selections.splice(idx, 1);
+ Selection.removeFromSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityIDs[i]);
+ }
+ }
+ that._update(true);
+ };
+
that.clearSelections = function() {
that.selections = [];
that._update(true);
From 48632be3c2760725d6376f03e227045a1d7220b4 Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Wed, 2 May 2018 16:12:48 +1200
Subject: [PATCH 31/51] Fix up cache APIs' JSDoc
---
libraries/animation/src/AnimationCache.h | 30 +++----
libraries/audio/src/SoundCache.h | 20 ++---
.../src/model-networking/ModelCache.h | 18 ++---
.../src/model-networking/TextureCache.h | 81 +++++++++----------
libraries/networking/src/ResourceCache.h | 18 ++---
5 files changed, 70 insertions(+), 97 deletions(-)
diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h
index 03b37aef2f..103b620254 100644
--- a/libraries/animation/src/AnimationCache.h
+++ b/libraries/animation/src/AnimationCache.h
@@ -43,45 +43,39 @@ public:
* @property {number} sizeCached - Size in bytes of all cached resources. Read-only.
*/
- // Functions are copied over from ResourceCache (see ResourceCache.h for reason).
+ // Functions are copied over from ResourceCache (see ResourceCache.h for reason).
- /**jsdoc
+ /**jsdoc
* Get the list of all resource URLs.
* @function AnimationCache.getResourceList
- * @return {string[]}
+ * @returns {string[]}
*/
- /**jsdoc
+ /**jsdoc
* @function AnimationCache.dirty
* @returns {Signal}
*/
- /**jsdoc
+ /**jsdoc
* @function AnimationCache.updateTotalSize
* @param {number} deltaSize
*/
- /**jsdoc
+ /**jsdoc
+ * Prefetches a resource.
* @function AnimationCache.prefetch
- * @param {string} url
- * @param {object} extra
- * @returns {object}
+ * @param {string} url - URL of the resource to prefetch.
+ * @param {object} [extra=null]
+ * @returns {Resource}
*/
- /**jsdoc
+ /**jsdoc
* Asynchronously loads a resource from the specified URL and returns it.
* @function AnimationCache.getResource
* @param {string} url - URL of the resource to load.
* @param {string} [fallback=""] - Fallback URL if load of the desired URL fails.
* @param {} [extra=null]
- * @return {Resource}
- */
-
- /**jsdoc
- * Prefetches a resource.
- * @function AnimationCache.prefetch
- * @param {string} url - URL of the resource to prefetch.
- * @return {Resource}
+ * @returns {Resource}
*/
diff --git a/libraries/audio/src/SoundCache.h b/libraries/audio/src/SoundCache.h
index d8c52635e0..039e815ff3 100644
--- a/libraries/audio/src/SoundCache.h
+++ b/libraries/audio/src/SoundCache.h
@@ -36,12 +36,12 @@ public:
*/
- // Functions are copied over from ResourceCache (see ResourceCache.h for reason).
+ // Functions are copied over from ResourceCache (see ResourceCache.h for reason).
/**jsdoc
* Get the list of all resource URLs.
* @function SoundCache.getResourceList
- * @return {string[]}
+ * @returns {string[]}
*/
/**jsdoc
@@ -55,10 +55,11 @@ public:
*/
/**jsdoc
+ * Prefetches a resource.
* @function SoundCache.prefetch
- * @param {string} url
- * @param {object} extra
- * @returns {object}
+ * @param {string} url - URL of the resource to prefetch.
+ * @param {object} [extra=null]
+ * @returns {Resource}
*/
/**jsdoc
@@ -67,14 +68,7 @@ public:
* @param {string} url - URL of the resource to load.
* @param {string} [fallback=""] - Fallback URL if load of the desired URL fails.
* @param {} [extra=null]
- * @return {Resource}
- */
-
- /**jsdoc
- * Prefetches a resource.
- * @function SoundCache.prefetch
- * @param {string} url - URL of the resource to prefetch.
- * @return {Resource}
+ * @returns {Resource}
*/
diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h
index 9532f39ce0..438c5e0d65 100644
--- a/libraries/model-networking/src/model-networking/ModelCache.h
+++ b/libraries/model-networking/src/model-networking/ModelCache.h
@@ -156,7 +156,7 @@ public:
/**jsdoc
* Get the list of all resource URLs.
* @function ModelCache.getResourceList
- * @return {string[]}
+ * @returns {string[]}
*/
/**jsdoc
@@ -170,10 +170,11 @@ public:
*/
/**jsdoc
+ * Prefetches a resource.
* @function ModelCache.prefetch
- * @param {string} url
- * @param {object} extra
- * @returns {object}
+ * @param {string} url - URL of the resource to prefetch.
+ * @param {object} [extra=null]
+ * @returns {Resource}
*/
/**jsdoc
@@ -182,14 +183,7 @@ public:
* @param {string} url - URL of the resource to load.
* @param {string} [fallback=""] - Fallback URL if load of the desired URL fails.
* @param {} [extra=null]
- * @return {Resource}
- */
-
- /**jsdoc
- * Prefetches a resource.
- * @function ModelCache.prefetch
- * @param {string} url - URL of the resource to prefetch.
- * @return {Resource}
+ * @returns {Resource}
*/
diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h
index 3f46dc3074..0c0dbeefa4 100644
--- a/libraries/model-networking/src/model-networking/TextureCache.h
+++ b/libraries/model-networking/src/model-networking/TextureCache.h
@@ -148,56 +148,50 @@ public:
// Properties are copied over from ResourceCache (see ResourceCache.h for reason).
/**jsdoc
- * API to manage texture cache resources.
- * @namespace TextureCache
- *
- * @property {number} numTotal - Total number of total resources. Read-only.
- * @property {number} numCached - Total number of cached resource. Read-only.
- * @property {number} sizeTotal - Size in bytes of all resources. Read-only.
- * @property {number} sizeCached - Size in bytes of all cached resources. Read-only.
- */
+ * API to manage texture cache resources.
+ * @namespace TextureCache
+ *
+ * @property {number} numTotal - Total number of total resources. Read-only.
+ * @property {number} numCached - Total number of cached resource. Read-only.
+ * @property {number} sizeTotal - Size in bytes of all resources. Read-only.
+ * @property {number} sizeCached - Size in bytes of all cached resources. Read-only.
+ */
// Functions are copied over from ResourceCache (see ResourceCache.h for reason).
- /**jsdoc
- * Get the list of all resource URLs.
- * @function TextureCache.getResourceList
- * @return {string[]}
- */
+ /**jsdoc
+ * Get the list of all resource URLs.
+ * @function TextureCache.getResourceList
+ * @returns {string[]}
+ */
- /**jsdoc
- * @function TextureCache.dirty
- * @returns {Signal}
- */
+ /**jsdoc
+ * @function TextureCache.dirty
+ * @returns {Signal}
+ */
- /**jsdoc
- * @function TextureCache.updateTotalSize
- * @param {number} deltaSize
- */
+ /**jsdoc
+ * @function TextureCache.updateTotalSize
+ * @param {number} deltaSize
+ */
- /**jsdoc
- * @function TextureCache.prefetch
- * @param {string} url
- * @param {object} extra
- * @returns {object}
- */
+ /**jsdoc
+ * Prefetches a resource.
+ * @function TextureCache.prefetch
+ * @param {string} url - URL of the resource to prefetch.
+ * @param {object} [extra=null]
+ * @returns {Resource}
+ */
- /**jsdoc
- * Asynchronously loads a resource from the specified URL and returns it.
- * @function TextureCache.getResource
- * @param {string} url - URL of the resource to load.
- * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails.
- * @param {} [extra=null]
- * @return {Resource}
- */
-
- /**jsdoc
- * Prefetches a resource.
- * @function TextureCache.prefetch
- * @param {string} url - URL of the resource to prefetch.
- * @return {Resource}
- */
+ /**jsdoc
+ * Asynchronously loads a resource from the specified URL and returns it.
+ * @function TextureCache.getResource
+ * @param {string} url - URL of the resource to load.
+ * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails.
+ * @param {} [extra=null]
+ * @returns {Resource}
+ */
/// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture
@@ -246,10 +240,11 @@ signals:
protected:
/**jsdoc
- * @function TextureCache.prefect
+ * @function TextureCache.prefetch
* @param {string} url
* @param {number} type
* @param {number} [maxNumPixels=67108864]
+ * @returns {Resource}
*/
// Overload ResourceCache::prefetch to allow specifying texture type for loads
Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS);
diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h
index 609483bc56..8a77beefd4 100644
--- a/libraries/networking/src/ResourceCache.h
+++ b/libraries/networking/src/ResourceCache.h
@@ -209,7 +209,7 @@ public:
/**jsdoc
* Get the list of all resource URLs.
* @function ResourceCache.getResourceList
- * @return {string[]}
+ * @returns {string[]}
*/
Q_INVOKABLE QVariantList getResourceList();
@@ -251,10 +251,11 @@ protected slots:
void updateTotalSize(const qint64& deltaSize);
/**jsdoc
+ * Prefetches a resource.
* @function ResourceCache.prefetch
- * @param {string} url
- * @param {object} extra
- * @returns {object}
+ * @param {string} url - URL of the resource to prefetch.
+ * @param {object} [extra=null]
+ * @returns {Resource}
*/
// Prefetches a resource to be held by the QScriptEngine.
// Left as a protected member so subclasses can overload prefetch
@@ -267,7 +268,7 @@ protected slots:
* @param {string} url - URL of the resource to load.
* @param {string} [fallback=""] - Fallback URL if load of the desired URL fails.
* @param {} [extra=null]
- * @return {Resource}
+ * @returns {Resource}
*/
/// Loads a resource from the specified URL and returns it.
/// If the caller is on a different thread than the ResourceCache,
@@ -285,12 +286,7 @@ protected:
// Pointers created through this method should be owned by the caller,
// which should be a QScriptEngine with ScriptableResource registered, so that
// the QScriptEngine will delete the pointer when it is garbage collected.
- /**jsdoc
- * Prefetches a resource.
- * @function ResourceCache.prefetch
- * @param {string} url - URL of the resource to prefetch.
- * @return {Resource}
- */
+ // JSDoc is provided on more general function signature.
Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url) { return prefetch(url, nullptr); }
/// Creates a new resource.
From 3febdcb141d540075c09739efae715d7543a1e14 Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Wed, 2 May 2018 16:15:35 +1200
Subject: [PATCH 32/51] Miscellaneous JSDoc tidying
---
interface/src/scripting/SelectionScriptingInterface.h | 6 +++---
.../src/graphics-scripting/GraphicsScriptingInterface.h | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h
index 71ff41248a..86ececcbca 100644
--- a/interface/src/scripting/SelectionScriptingInterface.h
+++ b/interface/src/scripting/SelectionScriptingInterface.h
@@ -131,7 +131,7 @@ public:
/**jsdoc
* Get the names of all the selection lists.
* @function Selection.getListNames
- * @return {list[]} An array of names of all the selection lists.
+ * @returns {list[]} An array of names of all the selection lists.
*/
Q_INVOKABLE QStringList getListNames() const;
@@ -181,7 +181,7 @@ public:
* Get the list of avatars, entities, and overlays stored in a selection list.
* @function Selection.getList
* @param {string} listName - The name of the selection list.
- * @return {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function
+ * @returns {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function
* returns an empty object with no properties.
*/
Q_INVOKABLE QVariantMap getSelectedItemsList(const QString& listName) const;
@@ -189,7 +189,7 @@ public:
/**jsdoc
* Get the names of the highlighted selection lists.
* @function Selection.getHighlightedListNames
- * @return {string[]} An array of names of the selection list currently highlight enabled.
+ * @returns {string[]} An array of names of the selection list currently highlight enabled.
*/
Q_INVOKABLE QStringList getHighlightedListNames() const;
diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h
index 526352804b..e0bb39c855 100644
--- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h
+++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h
@@ -39,7 +39,7 @@ public slots:
*
* @function Graphics.getModel
* @param {UUID} entityID - The objectID of the model whose meshes are to be retrieved.
- * @return {Graphics.Model} the resulting Model object
+ * @returns {Graphics.Model} the resulting Model object
*/
scriptable::ScriptableModelPointer getModel(QUuid uuid);
@@ -54,7 +54,7 @@ public slots:
*
* @function Graphics.newMesh
* @param {Graphics.IFSData} ifsMeshData Index-Faced Set (IFS) arrays used to create the new mesh.
- * @return {Graphics.Mesh} the resulting Mesh / Mesh Part object
+ * @returns {Graphics.Mesh} the resulting Mesh / Mesh Part object
*/
/**jsdoc
* @typedef {object} Graphics.IFSData
From 05c534991eb182b9e2786548cd32dda8f73f771b Mon Sep 17 00:00:00 2001
From: Ken Cooke
Date: Wed, 2 May 2018 09:39:42 -0700
Subject: [PATCH 33/51] Fix ASAN warnings
---
libraries/audio/src/AudioDynamics.h | 31 ++++++++++++++---------------
1 file changed, 15 insertions(+), 16 deletions(-)
diff --git a/libraries/audio/src/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h
index a43833610a..03506fa8a1 100644
--- a/libraries/audio/src/AudioDynamics.h
+++ b/libraries/audio/src/AudioDynamics.h
@@ -10,9 +10,9 @@
// Inline functions to implement audio dynamics processing
//
-#include
#include
#include
+#include
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
@@ -147,13 +147,13 @@ static const int IEEE754_EXPN_BIAS = 127;
static inline int32_t peaklog2(float* input) {
// float as integer bits
- int32_t u = *(int32_t*)input;
+ uint32_t u = *(uint32_t*)input;
// absolute value
- int32_t peak = u & IEEE754_FABS_MASK;
+ uint32_t peak = u & IEEE754_FABS_MASK;
// split into e and x - 1.0
- int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
+ int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff;
// saturate
@@ -183,16 +183,16 @@ static inline int32_t peaklog2(float* input) {
static inline int32_t peaklog2(float* input0, float* input1) {
// float as integer bits
- int32_t u0 = *(int32_t*)input0;
- int32_t u1 = *(int32_t*)input1;
+ uint32_t u0 = *(uint32_t*)input0;
+ uint32_t u1 = *(uint32_t*)input1;
// max absolute value
u0 &= IEEE754_FABS_MASK;
u1 &= IEEE754_FABS_MASK;
- int32_t peak = MAX(u0, u1);
+ uint32_t peak = MAX(u0, u1);
// split into e and x - 1.0
- int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
+ int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff;
// saturate
@@ -222,20 +222,20 @@ static inline int32_t peaklog2(float* input0, float* input1) {
static inline int32_t peaklog2(float* input0, float* input1, float* input2, float* input3) {
// float as integer bits
- int32_t u0 = *(int32_t*)input0;
- int32_t u1 = *(int32_t*)input1;
- int32_t u2 = *(int32_t*)input2;
- int32_t u3 = *(int32_t*)input3;
+ uint32_t u0 = *(uint32_t*)input0;
+ uint32_t u1 = *(uint32_t*)input1;
+ uint32_t u2 = *(uint32_t*)input2;
+ uint32_t u3 = *(uint32_t*)input3;
// max absolute value
u0 &= IEEE754_FABS_MASK;
u1 &= IEEE754_FABS_MASK;
u2 &= IEEE754_FABS_MASK;
u3 &= IEEE754_FABS_MASK;
- int32_t peak = MAX(MAX(u0, u1), MAX(u2, u3));
+ uint32_t peak = MAX(MAX(u0, u1), MAX(u2, u3));
// split into e and x - 1.0
- int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
+ int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff;
// saturate
@@ -303,8 +303,7 @@ static inline int32_t fixlog2(int32_t x) {
// split into e and x - 1.0
uint32_t u = (uint32_t)x;
int e = CLZ(u);
- u <<= e; // normalize to [0x80000000, 0xffffffff]
- x = u & 0x7fffffff; // x - 1.0
+ x = (u << e) & 0x7fffffff;
int k = x >> (31 - LOG2_TABBITS);
From b29984ab2c8f7efec889c001db5efe58bfeed161 Mon Sep 17 00:00:00 2001
From: Ryan Huffman
Date: Tue, 1 May 2018 16:52:47 -0700
Subject: [PATCH 34/51] Remove max log age for rolling interface log
---
libraries/shared/src/shared/FileLogger.cpp | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/libraries/shared/src/shared/FileLogger.cpp b/libraries/shared/src/shared/FileLogger.cpp
index 1e17ee9e7c..6a10629ee5 100644
--- a/libraries/shared/src/shared/FileLogger.cpp
+++ b/libraries/shared/src/shared/FileLogger.cpp
@@ -36,7 +36,6 @@ protected:
private:
const FileLogger& _logger;
QMutex _fileMutex;
- std::chrono::system_clock::time_point _lastRollTime;
};
static const QString FILENAME_FORMAT = "hifi-log_%1%2.txt";
@@ -52,7 +51,6 @@ static QUuid SESSION_ID;
static const qint64 MAX_LOG_SIZE = 512 * 1024;
// Max log files found in the log directory is 100.
static const qint64 MAX_LOG_DIR_SIZE = 512 * 1024 * 100;
-static const std::chrono::minutes MAX_LOG_AGE { 60 };
static FilePersistThread* _persistThreadInstance;
@@ -83,12 +81,10 @@ FilePersistThread::FilePersistThread(const FileLogger& logger) : _logger(logger)
if (file.exists()) {
rollFileIfNecessary(file, false);
}
- _lastRollTime = std::chrono::system_clock::now();
}
void FilePersistThread::rollFileIfNecessary(QFile& file, bool notifyListenersIfRolled) {
- auto now = std::chrono::system_clock::now();
- if ((file.size() > MAX_LOG_SIZE) || (now - _lastRollTime) > MAX_LOG_AGE) {
+ if (file.size() > MAX_LOG_SIZE) {
QString newFileName = getLogRollerFilename();
if (file.copy(newFileName)) {
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
@@ -97,8 +93,6 @@ void FilePersistThread::rollFileIfNecessary(QFile& file, bool notifyListenersIfR
if (notifyListenersIfRolled) {
emit rollingLogFile(newFileName);
}
-
- _lastRollTime = std::chrono::system_clock::now();
}
QDir logDir(FileUtils::standardPath(LOGS_DIRECTORY));
From 80f87f7a6264d6e06f1340771fe0345f5e180ea5 Mon Sep 17 00:00:00 2001
From: Bradley Austin Davis
Date: Tue, 1 May 2018 15:29:22 -0700
Subject: [PATCH 35/51] Make resource swapchains immutable, fix for 14638
---
.../src/gpu/gl/GLBackendOutput.cpp | 4 ++--
.../src/gpu/gl/GLBackendPipeline.cpp | 7 +++----
libraries/gpu/src/gpu/ResourceSwapChain.h | 19 +++++++----------
.../render-utils/src/AntialiasingEffect.cpp | 21 +++++++++----------
4 files changed, 23 insertions(+), 28 deletions(-)
diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp
index 2285b0e486..d1ab34da90 100644
--- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp
+++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp
@@ -46,10 +46,10 @@ void GLBackend::do_setFramebuffer(const Batch& batch, size_t paramOffset) {
}
void GLBackend::do_setFramebufferSwapChain(const Batch& batch, size_t paramOffset) {
- auto swapChain = batch._swapChains.get(batch._params[paramOffset]._uint);
+ auto swapChain = std::static_pointer_cast(batch._swapChains.get(batch._params[paramOffset]._uint));
if (swapChain) {
auto index = batch._params[paramOffset + 1]._uint;
- FramebufferPointer framebuffer = static_cast(swapChain.get())->get(index);
+ const auto& framebuffer = swapChain->get(index);
setFramebuffer(framebuffer);
}
}
diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp
index 58fcc51605..91f1d8bb8c 100644
--- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp
+++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp
@@ -268,7 +268,7 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si
return;
}
- SwapChainPointer swapChain = batch._swapChains.get(batch._params[paramOffset + 0]._uint);
+ auto swapChain = std::static_pointer_cast(batch._swapChains.get(batch._params[paramOffset + 0]._uint));
if (!swapChain) {
releaseResourceTexture(slot);
@@ -276,9 +276,8 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si
}
auto index = batch._params[paramOffset + 2]._uint;
auto renderBufferSlot = batch._params[paramOffset + 3]._uint;
- FramebufferPointer resourceFramebuffer = static_cast(swapChain.get())->get(index);
- TexturePointer resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot);
-
+ auto resourceFramebuffer = swapChain->get(index);
+ auto resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot);
setResourceTexture(slot, resourceTexture);
}
diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h
index 7b46b35521..84e8ec7c74 100644
--- a/libraries/gpu/src/gpu/ResourceSwapChain.h
+++ b/libraries/gpu/src/gpu/ResourceSwapChain.h
@@ -15,18 +15,18 @@ namespace gpu {
class SwapChain {
public:
- SwapChain(unsigned int size = 2U) : _size{ size } {}
+ SwapChain(size_t size = 2U) : _size{ size } {}
virtual ~SwapChain() {}
void advance() {
_frontIndex = (_frontIndex + 1) % _size;
}
- unsigned int getSize() const { return _size; }
+ size_t getSize() const { return _size; }
protected:
- unsigned int _size;
- unsigned int _frontIndex{ 0U };
+ const size_t _size;
+ size_t _frontIndex{ 0U };
};
typedef std::shared_ptr SwapChainPointer;
@@ -41,16 +41,13 @@ namespace gpu {
using Type = R;
using TypePointer = std::shared_ptr;
+ using TypeConstPointer = std::shared_ptr;
- ResourceSwapChain(unsigned int size = 2U) : SwapChain{ size } {}
-
- void reset() {
- for (auto& ptr : _resources) {
- ptr.reset();
+ ResourceSwapChain(const std::vector& v) : SwapChain{ std::min(v.size(), MAX_SIZE) } {
+ for (size_t i = 0; i < _size; ++i) {
+ _resources[i] = v[i];
}
}
-
- TypePointer& edit(unsigned int index) { return _resources[(index + _frontIndex) % _size]; }
const TypePointer& get(unsigned int index) const { return _resources[(index + _frontIndex) % _size]; }
private:
diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp
index dd4bda2e37..c9aa1b8f71 100644
--- a/libraries/render-utils/src/AntialiasingEffect.cpp
+++ b/libraries/render-utils/src/AntialiasingEffect.cpp
@@ -189,7 +189,6 @@ const int AntialiasingPass_NextMapSlot = 4;
Antialiasing::Antialiasing(bool isSharpenEnabled) :
_isSharpenEnabled{ isSharpenEnabled } {
- _antialiasingBuffers = std::make_shared(2U);
}
Antialiasing::~Antialiasing() {
@@ -325,25 +324,25 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const
int width = sourceBuffer->getWidth();
int height = sourceBuffer->getHeight();
- if (_antialiasingBuffers->get(0)) {
- if (_antialiasingBuffers->get(0)->getSize() != uvec2(width, height)) {// || (sourceBuffer && (_antialiasingBuffer->getRenderBuffer(1) != sourceBuffer->getRenderBuffer(0)))) {
- _antialiasingBuffers->edit(0).reset();
- _antialiasingBuffers->edit(1).reset();
- _antialiasingTextures[0].reset();
- _antialiasingTextures[1].reset();
- }
+ if (_antialiasingBuffers && _antialiasingBuffers->get(0) && _antialiasingBuffers->get(0)->getSize() != uvec2(width, height)) {
+ _antialiasingBuffers.reset();
+ _antialiasingTextures[0].reset();
+ _antialiasingTextures[1].reset();
}
- if (!_antialiasingBuffers->get(0)) {
+
+ if (!_antialiasingBuffers) {
+ std::vector antiAliasingBuffers;
// Link the antialiasing FBO to texture
auto format = sourceBuffer->getRenderBuffer(0)->getTexelFormat();
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP);
for (int i = 0; i < 2; i++) {
- auto& antiAliasingBuffer = _antialiasingBuffers->edit(i);
- antiAliasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("antialiasing"));
+ antiAliasingBuffers.emplace_back(gpu::Framebuffer::create("antialiasing"));
+ const auto& antiAliasingBuffer = antiAliasingBuffers.back();
_antialiasingTextures[i] = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, defaultSampler);
antiAliasingBuffer->setRenderBuffer(0, _antialiasingTextures[i]);
}
+ _antialiasingBuffers = std::make_shared(antiAliasingBuffers);
}
gpu::doInBatch("Antialiasing::run", args->_context, [&](gpu::Batch& batch) {
From 64d442b281713262ff43868c3366e514a452bbfa Mon Sep 17 00:00:00 2001
From: Bradley Austin Davis
Date: Tue, 1 May 2018 16:54:26 -0700
Subject: [PATCH 36/51] Change type used for swap chain count
---
libraries/gpu/src/gpu/ResourceSwapChain.h | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h
index 84e8ec7c74..28c5ff2ed3 100644
--- a/libraries/gpu/src/gpu/ResourceSwapChain.h
+++ b/libraries/gpu/src/gpu/ResourceSwapChain.h
@@ -15,18 +15,18 @@ namespace gpu {
class SwapChain {
public:
- SwapChain(size_t size = 2U) : _size{ size } {}
+ SwapChain(uint8_t size = 2U) : _size{ size } {}
virtual ~SwapChain() {}
void advance() {
_frontIndex = (_frontIndex + 1) % _size;
}
- size_t getSize() const { return _size; }
+ uint8_t getSize() const { return _size; }
protected:
- const size_t _size;
- size_t _frontIndex{ 0U };
+ const uint8_t _size;
+ uint8_t _frontIndex{ 0U };
};
typedef std::shared_ptr SwapChainPointer;
@@ -43,7 +43,7 @@ namespace gpu {
using TypePointer = std::shared_ptr;
using TypeConstPointer = std::shared_ptr;
- ResourceSwapChain(const std::vector& v) : SwapChain{ std::min(v.size(), MAX_SIZE) } {
+ ResourceSwapChain(const std::vector& v) : SwapChain{ std::min((uint8_t)v.size(), MAX_SIZE) } {
for (size_t i = 0; i < _size; ++i) {
_resources[i] = v[i];
}
From 4a96dc2fdc4b4c722d8f342d1c33876273b08fc5 Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Thu, 3 May 2018 08:48:17 +1200
Subject: [PATCH 37/51] Refactor
---
scripts/system/libraries/entitySelectionTool.js | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js
index 4996579799..36cc98a80b 100644
--- a/scripts/system/libraries/entitySelectionTool.js
+++ b/scripts/system/libraries/entitySelectionTool.js
@@ -140,22 +140,22 @@ SelectionManager = (function() {
that._update(true);
};
- that.removeEntity = function(entityID) {
+ function removeEntityByID(entityID) {
var idx = that.selections.indexOf(entityID);
if (idx >= 0) {
that.selections.splice(idx, 1);
Selection.removeFromSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityID);
}
+ }
+
+ that.removeEntity = function (entityID) {
+ removeEntityByID(entityID);
that._update(true);
};
that.removeEntities = function (entityIDs) {
for (var i = 0, length = entityIDs.length; i < length; i++) {
- var idx = that.selections.indexOf(entityIDs[i]);
- if (idx >= 0) {
- that.selections.splice(idx, 1);
- Selection.removeFromSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityIDs[i]);
- }
+ removeEntityByID(entityIDs[i]);
}
that._update(true);
};
From 5312c81a6fe7be0ca5b5c90bbab24d91e2d14963 Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Thu, 3 May 2018 08:49:18 +1200
Subject: [PATCH 38/51] Match style of surrounding code
---
scripts/system/libraries/entitySelectionTool.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js
index 36cc98a80b..e84600a64a 100644
--- a/scripts/system/libraries/entitySelectionTool.js
+++ b/scripts/system/libraries/entitySelectionTool.js
@@ -153,7 +153,7 @@ SelectionManager = (function() {
that._update(true);
};
- that.removeEntities = function (entityIDs) {
+ that.removeEntities = function(entityIDs) {
for (var i = 0, length = entityIDs.length; i < length; i++) {
removeEntityByID(entityIDs[i]);
}
From e549f7b0859a69a6e48a915a9cf2537e9cf34991 Mon Sep 17 00:00:00 2001
From: Ken Cooke
Date: Wed, 2 May 2018 14:48:08 -0700
Subject: [PATCH 39/51] Fix VS2017 performance loss
---
libraries/audio/src/AudioDynamics.h | 32 ++++++++++++++++++-----------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/libraries/audio/src/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h
index 03506fa8a1..542f6f1a05 100644
--- a/libraries/audio/src/AudioDynamics.h
+++ b/libraries/audio/src/AudioDynamics.h
@@ -21,7 +21,15 @@
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
-#ifdef _MSC_VER
+#if defined(_MSC_VER)
+#define FORCEINLINE __forceinline
+#elif defined(__GNUC__)
+#define FORCEINLINE inline __attribute__((always_inline))
+#else
+#define FORCEINLINE inline
+#endif
+
+#if defined(_MSC_VER)
#include
#define MUL64(a,b) __emul((a), (b))
#else
@@ -42,14 +50,14 @@
#include
// convert float to int using round-to-nearest
-static inline int32_t floatToInt(float x) {
+FORCEINLINE static int32_t floatToInt(float x) {
return _mm_cvt_ss2si(_mm_load_ss(&x));
}
#else
// convert float to int using round-to-nearest
-static inline int32_t floatToInt(float x) {
+FORCEINLINE static int32_t floatToInt(float x) {
x += (x < 0.0f ? -0.5f : 0.5f); // round
return (int32_t)x;
}
@@ -60,12 +68,12 @@ static const double FIXQ31 = 2147483648.0; // convert float to Q31
static const double DB_TO_LOG2 = 0.16609640474436813; // convert dB to log2
// convert dB to amplitude
-static inline double dBToGain(double dB) {
+static double dBToGain(double dB) {
return pow(10.0, dB / 20.0);
}
// convert milliseconds to first-order time constant
-static inline int32_t msToTc(double ms, double sampleRate) {
+static int32_t msToTc(double ms, double sampleRate) {
double tc = exp(-1000.0 / (ms * sampleRate));
return (int32_t)(FIXQ31 * tc); // Q31
}
@@ -144,7 +152,7 @@ static const int IEEE754_EXPN_BIAS = 127;
// x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff
// x > 2^LOG2_HEADROOM undefined
//
-static inline int32_t peaklog2(float* input) {
+FORCEINLINE static int32_t peaklog2(float* input) {
// float as integer bits
uint32_t u = *(uint32_t*)input;
@@ -180,7 +188,7 @@ static inline int32_t peaklog2(float* input) {
// x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff
// x > 2^LOG2_HEADROOM undefined
//
-static inline int32_t peaklog2(float* input0, float* input1) {
+FORCEINLINE static int32_t peaklog2(float* input0, float* input1) {
// float as integer bits
uint32_t u0 = *(uint32_t*)input0;
@@ -219,7 +227,7 @@ static inline int32_t peaklog2(float* input0, float* input1) {
// x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff
// x > 2^LOG2_HEADROOM undefined
//
-static inline int32_t peaklog2(float* input0, float* input1, float* input2, float* input3) {
+FORCEINLINE static int32_t peaklog2(float* input0, float* input1, float* input2, float* input3) {
// float as integer bits
uint32_t u0 = *(uint32_t*)input0;
@@ -261,7 +269,7 @@ static inline int32_t peaklog2(float* input0, float* input1, float* input2, floa
// Count Leading Zeros
// Emulates the CLZ (ARM) and LZCNT (x86) instruction
//
-static inline int CLZ(uint32_t u) {
+FORCEINLINE static int CLZ(uint32_t u) {
if (u == 0) {
return 32;
@@ -294,7 +302,7 @@ static inline int CLZ(uint32_t u) {
// Compute -log2(x) for x=[0,1] in Q31, result in Q26
// x <= 0 returns 0x7fffffff
//
-static inline int32_t fixlog2(int32_t x) {
+FORCEINLINE static int32_t fixlog2(int32_t x) {
if (x <= 0) {
return 0x7fffffff;
@@ -323,7 +331,7 @@ static inline int32_t fixlog2(int32_t x) {
// Compute exp2(-x) for x=[0,32] in Q26, result in Q31
// x <= 0 returns 0x7fffffff
//
-static inline int32_t fixexp2(int32_t x) {
+FORCEINLINE static int32_t fixexp2(int32_t x) {
if (x <= 0) {
return 0x7fffffff;
@@ -349,7 +357,7 @@ static inline int32_t fixexp2(int32_t x) {
}
// fast TPDF dither in [-1.0f, 1.0f]
-static inline float dither() {
+FORCEINLINE static float dither() {
static uint32_t rz = 0;
rz = rz * 69069 + 1;
int32_t r0 = rz & 0xffff;
From 5f394fb25442c51cf2bbbf8e39be2c26ddd0d588 Mon Sep 17 00:00:00 2001
From: Ken Cooke
Date: Wed, 2 May 2018 15:31:40 -0700
Subject: [PATCH 40/51] Remove workaround for VS2013 bug
---
libraries/audio/src/AudioDynamics.h | 2 +-
libraries/audio/src/AudioReverb.cpp | 2 +-
libraries/audio/src/AudioSRC.cpp | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libraries/audio/src/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h
index 542f6f1a05..dac59dbce1 100644
--- a/libraries/audio/src/AudioDynamics.h
+++ b/libraries/audio/src/AudioDynamics.h
@@ -362,7 +362,7 @@ FORCEINLINE static float dither() {
rz = rz * 69069 + 1;
int32_t r0 = rz & 0xffff;
int32_t r1 = rz >> 16;
- return (int32_t)(r0 - r1) * (1/65536.0f);
+ return (r0 - r1) * (1/65536.0f);
}
//
diff --git a/libraries/audio/src/AudioReverb.cpp b/libraries/audio/src/AudioReverb.cpp
index c561231376..0901e76251 100644
--- a/libraries/audio/src/AudioReverb.cpp
+++ b/libraries/audio/src/AudioReverb.cpp
@@ -1954,7 +1954,7 @@ static inline float dither() {
rz = rz * 69069 + 1;
int32_t r0 = rz & 0xffff;
int32_t r1 = rz >> 16;
- return (int32_t)(r0 - r1) * (1/65536.0f);
+ return (r0 - r1) * (1/65536.0f);
}
// convert float to int16_t with dither, interleave stereo
diff --git a/libraries/audio/src/AudioSRC.cpp b/libraries/audio/src/AudioSRC.cpp
index 80cb756d04..fbdf890246 100644
--- a/libraries/audio/src/AudioSRC.cpp
+++ b/libraries/audio/src/AudioSRC.cpp
@@ -1200,7 +1200,7 @@ static inline float dither() {
rz = rz * 69069 + 1;
int32_t r0 = rz & 0xffff;
int32_t r1 = rz >> 16;
- return (int32_t)(r0 - r1) * (1/65536.0f);
+ return (r0 - r1) * (1/65536.0f);
}
// convert float to int16_t with dither, interleave stereo
From 3071b410bff9d1370077ecad1acb2cc6e38c58a6 Mon Sep 17 00:00:00 2001
From: Ken Cooke
Date: Wed, 2 May 2018 15:42:53 -0700
Subject: [PATCH 41/51] Remove obsolete 32-bit optimizations
---
libraries/audio/src/AudioReverb.cpp | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/libraries/audio/src/AudioReverb.cpp b/libraries/audio/src/AudioReverb.cpp
index 0901e76251..d457ce7a96 100644
--- a/libraries/audio/src/AudioReverb.cpp
+++ b/libraries/audio/src/AudioReverb.cpp
@@ -13,18 +13,11 @@
#include "AudioReverb.h"
#ifdef _MSC_VER
-
#include
-inline static int MULHI(int a, int b) {
- long long c = __emul(a, b);
- return ((int*)&c)[1];
-}
-
+#define MULHI(a,b) ((int32_t)(__emul(a, b) >> 32))
#else
-
-#define MULHI(a,b) (int)(((long long)(a) * (b)) >> 32)
-
-#endif // _MSC_VER
+#define MULHI(a,b) ((int32_t)(((int64_t)(a) * (int64_t)(b)) >> 32))
+#endif
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
From 56ba59681a95450a151b6e9bad59a35e731c3380 Mon Sep 17 00:00:00 2001
From: Zach Fox
Date: Wed, 2 May 2018 16:12:55 -0700
Subject: [PATCH 42/51] Fix MS14741, allowing uninstall of apps whose scripts
are no longer running
---
interface/src/commerce/QmlCommerce.cpp | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp
index 568556cb22..722f29ba2f 100644
--- a/interface/src/commerce/QmlCommerce.cpp
+++ b/interface/src/commerce/QmlCommerce.cpp
@@ -301,7 +301,7 @@ bool QmlCommerce::uninstallApp(const QString& itemHref) {
// Read from the file to know what .js script to stop
QFile appFile(_appsPath + "/" + appHref.fileName());
if (!appFile.open(QIODevice::ReadOnly)) {
- qCDebug(commerce) << "Couldn't open local .app.json file for deletion.";
+ qCDebug(commerce) << "Couldn't open local .app.json file for deletion. Cannot continue with app uninstallation. App filename is:" << appHref.fileName();
return false;
}
QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(appFile.readAll());
@@ -309,15 +309,13 @@ bool QmlCommerce::uninstallApp(const QString& itemHref) {
QString scriptUrl = appFileJsonObject["scriptURL"].toString();
if (!DependencyManager::get()->stopScript(scriptUrl.trimmed(), false)) {
- qCDebug(commerce) << "Couldn't stop script.";
- return false;
+ qCWarning(commerce) << "Couldn't stop script during app uninstall. Continuing anyway. ScriptURL is:" << scriptUrl.trimmed();
}
// Delete the .app.json from the filesystem
// remove() closes the file first.
if (!appFile.remove()) {
- qCDebug(commerce) << "Couldn't delete local .app.json file.";
- return false;
+ qCWarning(commerce) << "Couldn't delete local .app.json file during app uninstall. Continuing anyway. App filename is:" << appHref.fileName();
}
emit appUninstalled(itemHref);
From e1c5eb9bda063367ab0af270d14505ab925af9ab Mon Sep 17 00:00:00 2001
From: Clement
Date: Wed, 2 May 2018 17:17:19 -0700
Subject: [PATCH 43/51] Fix wizard wording
---
domain-server/resources/web/wizard/index.shtml | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/domain-server/resources/web/wizard/index.shtml b/domain-server/resources/web/wizard/index.shtml
index 5a3286296d..3bc7503b44 100644
--- a/domain-server/resources/web/wizard/index.shtml
+++ b/domain-server/resources/web/wizard/index.shtml
@@ -26,7 +26,7 @@
Place names are similar to web addresses. Users who want to visit your domain can
enter its Place Name in High Fidelity's Interface. You can choose a Place Name for your domain.
- People can also use your domain's IP address (shown below) to visit your High Fidelity domain.
+ Your domain may also be reachable by IP address.
@@ -35,10 +35,10 @@
From 3e77d946ea49e82fd1b22c3fbe0713aef57ac67b Mon Sep 17 00:00:00 2001
From: Ken Cooke
Date: Wed, 2 May 2018 17:48:04 -0700
Subject: [PATCH 44/51] Silence warnings of unused functions
---
libraries/audio/src/AudioDynamics.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libraries/audio/src/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h
index dac59dbce1..8dbc7a75cc 100644
--- a/libraries/audio/src/AudioDynamics.h
+++ b/libraries/audio/src/AudioDynamics.h
@@ -68,12 +68,12 @@ static const double FIXQ31 = 2147483648.0; // convert float to Q31
static const double DB_TO_LOG2 = 0.16609640474436813; // convert dB to log2
// convert dB to amplitude
-static double dBToGain(double dB) {
+FORCEINLINE static double dBToGain(double dB) {
return pow(10.0, dB / 20.0);
}
// convert milliseconds to first-order time constant
-static int32_t msToTc(double ms, double sampleRate) {
+FORCEINLINE static int32_t msToTc(double ms, double sampleRate) {
double tc = exp(-1000.0 / (ms * sampleRate));
return (int32_t)(FIXQ31 * tc); // Q31
}
From 2a7e8c6f89944962370edbbd310c4660f5738b3b Mon Sep 17 00:00:00 2001
From: Ken Cooke
Date: Thu, 3 May 2018 07:15:18 -0700
Subject: [PATCH 45/51] Default audio meter overlay to "on"
---
interface/src/ui/AvatarInputs.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/interface/src/ui/AvatarInputs.cpp b/interface/src/ui/AvatarInputs.cpp
index 3053cb8855..0aa352de23 100644
--- a/interface/src/ui/AvatarInputs.cpp
+++ b/interface/src/ui/AvatarInputs.cpp
@@ -18,7 +18,7 @@
static AvatarInputs* INSTANCE{ nullptr };
-Setting::Handle showAudioToolsSetting { QStringList { "AvatarInputs", "showAudioTools" }, false };
+Setting::Handle showAudioToolsSetting { QStringList { "AvatarInputs", "showAudioTools" }, true };
AvatarInputs* AvatarInputs::getInstance() {
if (!INSTANCE) {
From cefb8457eacb47af31b32f44088bd98e9b2c0edc Mon Sep 17 00:00:00 2001
From: Clement
Date: Thu, 3 May 2018 11:17:31 -0700
Subject: [PATCH 46/51] Fix uninitialized boolean
---
libraries/networking/src/NodeList.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h
index 9595c5da84..c5cf5e9524 100644
--- a/libraries/networking/src/NodeList.h
+++ b/libraries/networking/src/NodeList.h
@@ -167,7 +167,7 @@ private:
HifiSockAddr _assignmentServerSocket;
bool _isShuttingDown { false };
QTimer _keepAlivePingTimer;
- bool _requestsDomainListData;
+ bool _requestsDomainListData { false };
mutable QReadWriteLock _ignoredSetLock;
tbb::concurrent_unordered_set _ignoredNodeIDs;
From 767e6b15f34e9827d41f2e351933dba566eb0c2f Mon Sep 17 00:00:00 2001
From: samcake
Date: Thu, 3 May 2018 11:42:06 -0700
Subject: [PATCH 47/51] Fixing the local lighting on translucents bug
---
.../src/RenderableParticleEffectEntityItem.cpp | 4 ++--
.../entities-renderer/src/RenderablePolyLineEntityItem.cpp | 4 ++--
libraries/gpu-gl-common/src/gpu/gl/GLBackend.h | 2 +-
libraries/gpu/src/gpu/Batch.cpp | 2 +-
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp
index b3a4a1a1ab..ee77646920 100644
--- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp
@@ -23,8 +23,8 @@ using namespace render::entities;
static uint8_t CUSTOM_PIPELINE_NUMBER = 0;
static gpu::Stream::FormatPointer _vertexFormat;
static std::weak_ptr _texturedPipeline;
-// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions
-static int32_t PARTICLE_UNIFORM_SLOT { 11 };
+// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions
+static int32_t PARTICLE_UNIFORM_SLOT { 12 };
static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) {
auto texturedPipeline = _texturedPipeline.lock();
diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
index 394ab08dfb..d571eac35c 100644
--- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
@@ -34,8 +34,8 @@ using namespace render::entities;
static uint8_t CUSTOM_PIPELINE_NUMBER { 0 };
static const int32_t PAINTSTROKE_TEXTURE_SLOT { 0 };
-// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions
-static const int32_t PAINTSTROKE_UNIFORM_SLOT { 11 };
+// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions
+static const int32_t PAINTSTROKE_UNIFORM_SLOT { 12 };
static gpu::Stream::FormatPointer polylineFormat;
static gpu::PipelinePointer polylinePipeline;
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h
index 5bbb44f9e1..314bbee387 100644
--- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h
+++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h
@@ -91,7 +91,7 @@ public:
// this is the maximum per shader stage on the low end apple
// TODO make it platform dependant at init time
- static const int MAX_NUM_UNIFORM_BUFFERS = 12;
+ static const int MAX_NUM_UNIFORM_BUFFERS = 14;
size_t getMaxNumUniformBuffers() const { return MAX_NUM_UNIFORM_BUFFERS; }
// this is the maximum per shader stage on the low end apple
diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp
index 84a7c275f0..90115806b4 100644
--- a/libraries/gpu/src/gpu/Batch.cpp
+++ b/libraries/gpu/src/gpu/Batch.cpp
@@ -34,7 +34,7 @@ ProfileRangeBatch::~ProfileRangeBatch() {
using namespace gpu;
// FIXME make these backend / pipeline dependent.
-static const int MAX_NUM_UNIFORM_BUFFERS = 12;
+static const int MAX_NUM_UNIFORM_BUFFERS = 14;
static const int MAX_NUM_RESOURCE_BUFFERS = 16;
static const int MAX_NUM_RESOURCE_TEXTURES = 16;
From fc9bd7f905d2f0c6dd92ac539e2dbbb4afb75f17 Mon Sep 17 00:00:00 2001
From: "Anthony J. Thibault"
Date: Thu, 3 May 2018 13:51:50 -0700
Subject: [PATCH 48/51] Fix for crash deep in QML after useFullAvatarURL
Here we avoid calling FSTReader::downloadMapping() from within MyAvatar::useFullAvatarURL().
This prevents the error case where a QEventLoop is entered during QML execution.
---
interface/src/avatar/MyAvatar.cpp | 18 +++++++++++-------
.../src/model-networking/ModelCache.cpp | 19 +++++++++++--------
.../src/model-networking/ModelCache.h | 2 ++
3 files changed, 24 insertions(+), 15 deletions(-)
diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp
index e116b3830e..15b220c63b 100755
--- a/interface/src/avatar/MyAvatar.cpp
+++ b/interface/src/avatar/MyAvatar.cpp
@@ -1486,6 +1486,15 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
std::shared_ptr skeletonConnection = std::make_shared();
*skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded, [this, skeletonModelChangeCount, skeletonConnection]() {
if (skeletonModelChangeCount == _skeletonModelChangeCount) {
+
+ if (_fullAvatarModelName.isEmpty()) {
+ // Store the FST file name into preferences
+ const auto& mapping = _skeletonModel->getGeometry()->getMapping();
+ if (mapping.value("name").isValid()) {
+ _fullAvatarModelName = mapping.value("name").toString();
+ }
+ }
+
initHeadBones();
_skeletonModel->setCauterizeBoneSet(_headBoneSet);
_fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl();
@@ -1548,12 +1557,7 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN
if (_fullAvatarURLFromPreferences != fullAvatarURL) {
_fullAvatarURLFromPreferences = fullAvatarURL;
- if (modelName.isEmpty()) {
- QVariantHash fullAvatarFST = FSTReader::downloadMapping(_fullAvatarURLFromPreferences.toString());
- _fullAvatarModelName = fullAvatarFST["name"].toString();
- } else {
- _fullAvatarModelName = modelName;
- }
+ _fullAvatarModelName = modelName;
}
const QString& urlString = fullAvatarURL.toString();
@@ -1561,8 +1565,8 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN
setSkeletonModelURL(fullAvatarURL);
UserActivityLogger::getInstance().changedModel("skeleton", urlString);
}
+
markIdentityDataChanged();
-
}
void MyAvatar::setAttachmentData(const QVector& attachmentData) {
diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp
index 416920d43f..45f2462f57 100644
--- a/libraries/model-networking/src/model-networking/ModelCache.cpp
+++ b/libraries/model-networking/src/model-networking/ModelCache.cpp
@@ -63,9 +63,10 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) {
PROFILE_ASYNC_BEGIN(resource_parse_geometry, "GeometryMappingResource::downloadFinished", _url.toString(),
{ { "url", _url.toString() } });
- auto mapping = FSTReader::readMapping(data);
+ // store parsed contents of FST file
+ _mapping = FSTReader::readMapping(data);
- QString filename = mapping.value("filename").toString();
+ QString filename = _mapping.value("filename").toString();
if (filename.isNull()) {
qCDebug(modelnetworking) << "Mapping file" << _url << "has no \"filename\" field";
@@ -73,7 +74,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) {
} else {
QUrl url = _url.resolved(filename);
- QString texdir = mapping.value(TEXDIR_FIELD).toString();
+ QString texdir = _mapping.value(TEXDIR_FIELD).toString();
if (!texdir.isNull()) {
if (!texdir.endsWith('/')) {
texdir += '/';
@@ -83,15 +84,16 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) {
_textureBaseUrl = url.resolved(QUrl("."));
}
- auto scripts = FSTReader::getScripts(_url, mapping);
+ auto scripts = FSTReader::getScripts(_url, _mapping);
if (scripts.size() > 0) {
- mapping.remove(SCRIPT_FIELD);
+ _mapping.remove(SCRIPT_FIELD);
for (auto &scriptPath : scripts) {
- mapping.insertMulti(SCRIPT_FIELD, scriptPath);
+ _mapping.insertMulti(SCRIPT_FIELD, scriptPath);
}
}
- auto animGraphVariant = mapping.value("animGraphUrl");
+ auto animGraphVariant = _mapping.value("animGraphUrl");
+
if (animGraphVariant.isValid()) {
QUrl fstUrl(animGraphVariant.toString());
if (fstUrl.isValid()) {
@@ -104,7 +106,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) {
}
auto modelCache = DependencyManager::get();
- GeometryExtra extra{ mapping, _textureBaseUrl, false };
+ GeometryExtra extra{ _mapping, _textureBaseUrl, false };
// Get the raw GeometryResource
_geometryResource = modelCache->getResource(url, QUrl(), &extra).staticCast();
@@ -379,6 +381,7 @@ Geometry::Geometry(const Geometry& geometry) {
}
_animGraphOverrideUrl = geometry._animGraphOverrideUrl;
+ _mapping = geometry._mapping;
}
void Geometry::setTextures(const QVariantMap& textureMap) {
diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h
index cda825e5fb..7cb11587c9 100644
--- a/libraries/model-networking/src/model-networking/ModelCache.h
+++ b/libraries/model-networking/src/model-networking/ModelCache.h
@@ -55,6 +55,7 @@ public:
virtual bool areTexturesLoaded() const;
const QUrl& getAnimGraphOverrideUrl() const { return _animGraphOverrideUrl; }
+ const QVariantHash& getMapping() const { return _mapping; }
protected:
friend class GeometryMappingResource;
@@ -68,6 +69,7 @@ protected:
NetworkMaterials _materials;
QUrl _animGraphOverrideUrl;
+ QVariantHash _mapping; // parsed contents of FST file.
private:
mutable bool _areTexturesLoaded { false };
From 7fe16f82fbdaed268b03ce8caa935b196019c929 Mon Sep 17 00:00:00 2001
From: Clement
Date: Thu, 3 May 2018 17:08:17 -0700
Subject: [PATCH 49/51] Move variables to Agent.cpp
---
assignment-client/src/Agent.cpp | 3 +++
libraries/avatars/src/AvatarData.h | 3 ---
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp
index f560ea72bd..0b373e511b 100644
--- a/assignment-client/src/Agent.cpp
+++ b/assignment-client/src/Agent.cpp
@@ -554,6 +554,9 @@ void Agent::setIsAvatar(bool isAvatar) {
connect(_avatarIdentityTimer, &QTimer::timeout, this, &Agent::sendAvatarIdentityPacket);
connect(_avatarViewTimer, &QTimer::timeout, this, &Agent::sendAvatarViewFrustum);
+ static const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000;
+ static const int AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS = 1000;
+
// start the timers
_avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); // FIXME - we shouldn't really need to constantly send identity packets
_avatarViewTimer->start(AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS);
diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h
index 3db94f6691..bbcdd3693d 100644
--- a/libraries/avatars/src/AvatarData.h
+++ b/libraries/avatars/src/AvatarData.h
@@ -277,9 +277,6 @@ namespace AvatarDataPacket {
const float MAX_AUDIO_LOUDNESS = 1000.0f; // close enough for mouth animation
-const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000;
-const int AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS = 100;
-
// See also static AvatarData::defaultFullAvatarModelUrl().
const QString DEFAULT_FULL_AVATAR_MODEL_NAME = QString("Default");
From 73ce02ce75098cae634664151b11c6f28b8508d6 Mon Sep 17 00:00:00 2001
From: Ken Cooke
Date: Fri, 4 May 2018 07:56:44 -0700
Subject: [PATCH 50/51] Fix asan warnings in byte-unpacking functions
---
libraries/shared/src/GLMHelpers.cpp | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp
index 72710a6a7d..e963345ecd 100644
--- a/libraries/shared/src/GLMHelpers.cpp
+++ b/libraries/shared/src/GLMHelpers.cpp
@@ -76,13 +76,15 @@ glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float proportion) {
// Allows sending of fixed-point numbers: radix 1 makes 15.1 number, radix 8 makes 8.8 number, etc
int packFloatScalarToSignedTwoByteFixed(unsigned char* buffer, float scalar, int radix) {
- int16_t outVal = (int16_t)(scalar * (float)(1 << radix));
- memcpy(buffer, &outVal, sizeof(uint16_t));
- return sizeof(uint16_t);
+ int16_t twoByteFixed = (int16_t)(scalar * (float)(1 << radix));
+ memcpy(buffer, &twoByteFixed, sizeof(int16_t));
+ return sizeof(int16_t);
}
int unpackFloatScalarFromSignedTwoByteFixed(const int16_t* byteFixedPointer, float* destinationPointer, int radix) {
- *destinationPointer = *byteFixedPointer / (float)(1 << radix);
+ int16_t twoByteFixed;
+ memcpy(&twoByteFixed, byteFixedPointer, sizeof(int16_t));
+ *destinationPointer = twoByteFixed / (float)(1 << radix);
return sizeof(int16_t);
}
@@ -102,18 +104,19 @@ int unpackFloatVec3FromSignedTwoByteFixed(const unsigned char* sourceBuffer, glm
return sourceBuffer - startPosition;
}
-
int packFloatAngleToTwoByte(unsigned char* buffer, float degrees) {
const float ANGLE_CONVERSION_RATIO = (std::numeric_limits::max() / 360.0f);
- uint16_t angleHolder = floorf((degrees + 180.0f) * ANGLE_CONVERSION_RATIO);
- memcpy(buffer, &angleHolder, sizeof(uint16_t));
+ uint16_t twoByteAngle = floorf((degrees + 180.0f) * ANGLE_CONVERSION_RATIO);
+ memcpy(buffer, &twoByteAngle, sizeof(uint16_t));
return sizeof(uint16_t);
}
int unpackFloatAngleFromTwoByte(const uint16_t* byteAnglePointer, float* destinationPointer) {
- *destinationPointer = (*byteAnglePointer / (float) std::numeric_limits::max()) * 360.0f - 180.0f;
+ uint16_t twoByteAngle;
+ memcpy(&twoByteAngle, byteAnglePointer, sizeof(uint16_t));
+ *destinationPointer = (twoByteAngle / (float) std::numeric_limits::max()) * 360.0f - 180.0f;
return sizeof(uint16_t);
}
From e48d39ec38c3012b019e928bf05718dc23d9ba1d Mon Sep 17 00:00:00 2001
From: Zach Fox
Date: Fri, 4 May 2018 10:10:48 -0700
Subject: [PATCH 51/51] MS14758: Fix avatar reset when gifting worn avatar
---
interface/resources/qml/hifi/commerce/purchases/Purchases.qml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
index 6b48f8d51d..d79b8d09fa 100644
--- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
+++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
@@ -729,7 +729,7 @@ Rectangle {
}
lightboxPopup.button2text = "CONFIRM";
lightboxPopup.button2method = function() {
- MyAvatar.skeletonModelURL = '';
+ MyAvatar.useFullAvatarURL('');
root.activeView = "giftAsset";
lightboxPopup.visible = false;
};