The default scripts implement hand controller actions that use {@link Entities.callEntityMethod} to call entity script
+ * methods, if present in the entity being interacted with.
+ *
+ *
+ *
+ *
Method Name
Description
Example
+ *
+ *
+ *
+ *
startFarTrigger continueFarTrigger stopFarTrigger
+ *
These methods are called when a user is more than 0.3m away from the entity, the entity is triggerable, and the
+ * user starts, continues, or stops squeezing the trigger.
+ *
+ *
A light switch that can be toggled on and off from a distance.
These methods are called when a user is less than 0.3m away from the entity, the entity is triggerable, and the
+ * user starts, continues, or stops squeezing the trigger.
+ *
A doorbell that can be rung when a user is near.
+ *
+ *
+ *
startDistanceGrab continueDistanceGrab
+ *
These methods are called when a user is more than 0.3m away from the entity, the entity is either cloneable, or
+ * grabbable and not locked, and the user starts or continues to squeeze the trigger.
+ *
A comet that emits icy particle trails when a user is dragging it through the sky.
+ *
+ *
+ *
startNearGrab continueNearGrab
+ *
These methods are called when a user is less than 0.3m away from the entity, the entity is either cloneable, or
+ * grabbable and not locked, and the user starts or continues to squeeze the trigger.
+ *
A ball that glows when it's being held close.
+ *
+ *
+ *
releaseGrab
+ *
This method is called when a user releases the trigger when having been either distance or near grabbing an
+ * entity.
+ *
Turn off the ball glow or comet trail with the user finishes grabbing it.
+ *
+ *
+ *
startEquip continueEquip releaseEquip
+ *
These methods are called when a user starts, continues, or stops equipping an entity.
+ *
A glass that stays in the user's hand after the trigger is clicked.
+ *
+ *
+ *
+ *
All the entity methods are called with the following two arguments:
+ *
+ *
The entity ID.
+ *
A string, "hand,userID" — where "hand" is "left" or "right", and "userID"
+ * is the user's {@link MyAvatar|MyAvatar.sessionUUID}.
+ *
+ *
* @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..8b5c12e3dc 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 () {
@@ -131,7 +134,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 +184,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 +192,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/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/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp
index 87bf09a252..789a2a2bdf 100644
--- a/interface/src/ui/AddressBarDialog.cpp
+++ b/interface/src/ui/AddressBarDialog.cpp
@@ -58,9 +58,8 @@ void AddressBarDialog::loadHome() {
qDebug() << "Called LoadHome";
auto locationBookmarks = DependencyManager::get();
QString homeLocation = locationBookmarks->addressForBookmark(LocationBookmarks::HOME_BOOKMARK);
- const QString DEFAULT_HOME_LOCATION = "localhost";
if (homeLocation == "") {
- homeLocation = DEFAULT_HOME_LOCATION;
+ homeLocation = DEFAULT_HIFI_ADDRESS;
}
DependencyManager::get()->handleLookupString(homeLocation);
}
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) {
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..d8f8a13cde 100644
--- a/libraries/animation/src/AnimationCache.h
+++ b/libraries/animation/src/AnimationCache.h
@@ -37,51 +37,49 @@ 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.
* @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-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/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h
index a43833610a..8dbc7a75cc 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))
@@ -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) {
+FORCEINLINE 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) {
+FORCEINLINE static int32_t msToTc(double ms, double sampleRate) {
double tc = exp(-1000.0 / (ms * sampleRate));
return (int32_t)(FIXQ31 * tc); // Q31
}
@@ -144,16 +152,16 @@ 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
- 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
@@ -180,19 +188,19 @@ 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
- 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
@@ -219,23 +227,23 @@ 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
- 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
@@ -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;
@@ -303,8 +311,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);
@@ -324,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;
@@ -350,12 +357,12 @@ 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;
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..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))
@@ -1954,7 +1947,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
diff --git a/libraries/audio/src/InboundAudioStream.cpp b/libraries/audio/src/InboundAudioStream.cpp
index 172ec9411a..d60c5ba4ab 100644
--- a/libraries/audio/src/InboundAudioStream.cpp
+++ b/libraries/audio/src/InboundAudioStream.cpp
@@ -150,6 +150,7 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
// fall through to OnTime case
}
+ // FALLTHRU
case SequenceNumberStats::OnTime: {
// Packet is on time; parse its data to the ringbuffer
if (message.getType() == PacketType::SilentAudioFrame
diff --git a/libraries/audio/src/SoundCache.h b/libraries/audio/src/SoundCache.h
index d8c52635e0..347f324353 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.
@@ -36,12 +41,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 +60,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 +73,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/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h
index 888c3bfb24..bbcdd3693d 100644
--- a/libraries/avatars/src/AvatarData.h
+++ b/libraries/avatars/src/AvatarData.h
@@ -277,8 +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;
-
// See also static AvatarData::defaultFullAvatarModelUrl().
const QString DEFAULT_FULL_AVATAR_MODEL_NAME = QString("Default");
diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h
index 86a43c0c13..5bc7357dd7 100644
--- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h
+++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h
@@ -39,7 +39,9 @@ class UserInputMapper;
* methods.
*
Use {@link Controller.parseMapping} or {@link Controller.loadMapping} to load a {@link Controller.MappingJSON}.
*
- *
Enable the mapping using {@link MappingObject#enable|enable} or {@link Controller.enableMapping} for it to take effect.
+ *
+ *
Enable the mapping using {@link MappingObject#enable|enable} or {@link Controller.enableMapping} for it to take
+ * effect.
*
*
Mappings and their routes are applied according to the following rules:
*
@@ -49,9 +51,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.
A route in a {@link MappingObject} used by the {@link Controller} API.
*
*
Create a route using {@link MappingObject} methods and apply this object's methods to process it, terminating with
- * {@link RouteObject#to} to apply it to a Standard control, action, or script function.
+ * {@link RouteObject#to} to apply it to a Standard control, action, or script function. Note: Loops are not
+ * permitted.
*
*
Some methods apply to routes with number data, some apply routes with {@link Pose} data, and some apply to both route
* 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/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp
index f33af1b580..59cd637ca0 100644
--- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp
+++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp
@@ -147,20 +147,21 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() {
batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize()));
batch.draw(gpu::TRIANGLE_STRIP, 4);
});
-
- // render stick head
- auto jumpTransform = DependencyManager::get()->getPoint2DTransform(virtualPadManager.getJumpButtonPosition(),
- _virtualPadJumpBtnPixelSize, _virtualPadJumpBtnPixelSize);
- render([&](gpu::Batch& batch) {
- batch.enableStereo(false);
- batch.setProjectionTransform(mat4());
- batch.setPipeline(_cursorPipeline);
- batch.setResourceTexture(0, _virtualPadJumpBtnTexture);
- batch.resetViewTransform();
- batch.setModelTransform(jumpTransform);
- batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize()));
- batch.draw(gpu::TRIANGLE_STRIP, 4);
- });
+ if (!virtualPadManager.getLeftVirtualPad()->isBeingTouched()) {
+ // render stick head
+ auto jumpTransform = DependencyManager::get()->getPoint2DTransform(virtualPadManager.getJumpButtonPosition(),
+ _virtualPadJumpBtnPixelSize, _virtualPadJumpBtnPixelSize);
+ render([&](gpu::Batch& batch) {
+ batch.enableStereo(false);
+ batch.setProjectionTransform(mat4());
+ batch.setPipeline(_cursorPipeline);
+ batch.setResourceTexture(0, _virtualPadJumpBtnTexture);
+ batch.resetViewTransform();
+ batch.setModelTransform(jumpTransform);
+ batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize()));
+ batch.draw(gpu::TRIANGLE_STRIP, 4);
+ });
+ }
}
#endif
Parent::compositeExtra();
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-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
index ba81922979..6dd13c7332 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 ViewFrustums& 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);
+
+ ViewFrustums 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..9ed4f9d21d 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 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-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/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
index f333e805ce..693e3d0cf4 100644
--- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
@@ -308,12 +308,7 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
item->setProperty(URL_PROPERTY, _lastSourceUrl);
});
} else if (_contentType == ContentType::QmlContent) {
- _webSurface->load(_lastSourceUrl, [this](QQmlContext* context, QObject* item) {
- if (item && item->objectName() == "tabletRoot") {
- auto tabletScriptingInterface = DependencyManager::get();
- tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
- }
- });
+ _webSurface->load(_lastSourceUrl);
}
_fadeStartTime = usecTimestampNow();
_webSurface->resume();
@@ -323,32 +318,21 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
void WebEntityRenderer::destroyWebSurface() {
QSharedPointer webSurface;
+ ContentType contentType{ ContentType::NoContent };
withWriteLock([&] {
webSurface.swap(_webSurface);
+ std::swap(contentType, _contentType);
});
if (webSurface) {
--_currentWebCount;
QQuickItem* rootItem = webSurface->getRootItem();
- // Explicitly set the web URL to an empty string, in an effort to get a
- // faster shutdown of any chromium processes interacting with audio
- if (rootItem && _contentType == ContentType::HtmlContent) {
- rootItem->setProperty(URL_PROPERTY, "");
- }
-
- if (rootItem && rootItem->objectName() == "tabletRoot") {
- auto tabletScriptingInterface = DependencyManager::get();
- tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", nullptr);
- }
// Fix for crash in QtWebEngineCore when rapidly switching domains
// Call stop on the QWebEngineView before destroying OffscreenQMLSurface.
- if (rootItem) {
- QObject* obj = rootItem->findChild("webEngineView");
- if (obj) {
- // stop loading
- QMetaObject::invokeMethod(obj, "stop");
- }
+ if (rootItem && contentType == ContentType::HtmlContent) {
+ // stop loading
+ QMetaObject::invokeMethod(rootItem, "stop");
}
webSurface->pause();
diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp
index 764c420197..39328e11ad 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;
@@ -37,15 +36,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 +74,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 +115,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 +133,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;
+ }
+
+ 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 {
+ if (viewFrustums.empty()) {
+ // Everything intersects when not using view frustums
+ return true;
+ }
+
+ 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 {
+ 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:
//
@@ -159,29 +225,25 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFr
//
// 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 = 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 = 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..0fd014ac23 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;
+
+ ViewFrustums 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/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h
index 5e76d18515..8adb5138f2 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/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp
index b56f367e0a..3149527216 100644
--- a/libraries/entities/src/EntityTree.cpp
+++ b/libraries/entities/src/EntityTree.cpp
@@ -1402,6 +1402,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
case PacketType::EntityAdd:
isAdd = true; // fall through to next case
+ // FALLTHRU
case PacketType::EntityPhysics:
case PacketType::EntityEdit: {
quint64 startDecode = 0, endDecode = 0;
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;
diff --git a/libraries/fbx/src/FBX.h b/libraries/fbx/src/FBX.h
index a609d85fc8..ce3fc52c3a 100644
--- a/libraries/fbx/src/FBX.h
+++ b/libraries/fbx/src/FBX.h
@@ -298,6 +298,7 @@ public:
bool hasSkeletonJoints;
QVector meshes;
+ QVector scripts;
QHash materials;
diff --git a/libraries/fbx/src/FBXReader_Mesh.cpp b/libraries/fbx/src/FBXReader_Mesh.cpp
index e8365e38b7..801edddb06 100644
--- a/libraries/fbx/src/FBXReader_Mesh.cpp
+++ b/libraries/fbx/src/FBXReader_Mesh.cpp
@@ -249,7 +249,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
indexToDirect = true;
}
}
- if (indexToDirect && data.normalIndices.isEmpty()) {
+ if (indexToDirect && data.colorIndices.isEmpty()) {
// hack to work around wacky Makehuman exports
data.colorsByVertex = true;
}
diff --git a/libraries/fbx/src/FBXWriter.cpp b/libraries/fbx/src/FBXWriter.cpp
index 511f253193..e6adff0df9 100644
--- a/libraries/fbx/src/FBXWriter.cpp
+++ b/libraries/fbx/src/FBXWriter.cpp
@@ -142,7 +142,6 @@ void FBXWriter::encodeFBXProperty(QDataStream& out, const QVariant& prop) {
out << prop.toInt();
break;
- encodeNode(out, FBXNode());
case QMetaType::Float:
out.device()->write("F", 1);
out << prop.toFloat();
diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp
index cc4a919445..d63a5b3cc4 100644
--- a/libraries/fbx/src/FSTReader.cpp
+++ b/libraries/fbx/src/FSTReader.cpp
@@ -84,7 +84,7 @@ void FSTReader::writeVariant(QBuffer& buffer, QVariantHash::const_iterator& it)
QByteArray FSTReader::writeMapping(const QVariantHash& mapping) {
static const QStringList PREFERED_ORDER = QStringList() << NAME_FIELD << TYPE_FIELD << SCALE_FIELD << FILENAME_FIELD
- << TEXDIR_FIELD << JOINT_FIELD << FREE_JOINT_FIELD
+ << TEXDIR_FIELD << SCRIPT_FIELD << JOINT_FIELD << FREE_JOINT_FIELD
<< BLENDSHAPE_FIELD << JOINT_INDEX_FIELD;
QBuffer buffer;
buffer.open(QIODevice::WriteOnly);
@@ -92,7 +92,7 @@ QByteArray FSTReader::writeMapping(const QVariantHash& mapping) {
for (auto key : PREFERED_ORDER) {
auto it = mapping.find(key);
if (it != mapping.constEnd()) {
- if (key == FREE_JOINT_FIELD) { // writeVariant does not handle strings added using insertMulti.
+ if (key == FREE_JOINT_FIELD || key == SCRIPT_FIELD) { // writeVariant does not handle strings added using insertMulti.
for (auto multi : mapping.values(key)) {
buffer.write(key.toUtf8());
buffer.write(" = ");
@@ -187,6 +187,26 @@ FSTReader::ModelType FSTReader::predictModelType(const QVariantHash& mapping) {
return ENTITY_MODEL;
}
+QVector FSTReader::getScripts(const QUrl& url, const QVariantHash& mapping) {
+
+ auto fstMapping = mapping.isEmpty() ? downloadMapping(url.toString()) : mapping;
+ QVector scriptPaths;
+ if (!fstMapping.value(SCRIPT_FIELD).isNull()) {
+ auto scripts = fstMapping.values(SCRIPT_FIELD).toVector();
+ for (auto &script : scripts) {
+ QString scriptPath = script.toString();
+ if (QUrl(scriptPath).isRelative()) {
+ if (scriptPath.at(0) == '/') {
+ scriptPath = scriptPath.right(scriptPath.length() - 1);
+ }
+ scriptPath = url.resolved(QUrl(scriptPath)).toString();
+ }
+ scriptPaths.push_back(scriptPath);
+ }
+ }
+ return scriptPaths;
+}
+
QVariantHash FSTReader::downloadMapping(const QString& url) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest = QNetworkRequest(url);
diff --git a/libraries/fbx/src/FSTReader.h b/libraries/fbx/src/FSTReader.h
index 981bae4feb..4a8574f0cf 100644
--- a/libraries/fbx/src/FSTReader.h
+++ b/libraries/fbx/src/FSTReader.h
@@ -28,6 +28,7 @@ static const QString TRANSLATION_Z_FIELD = "tz";
static const QString JOINT_FIELD = "joint";
static const QString FREE_JOINT_FIELD = "freeJoint";
static const QString BLENDSHAPE_FIELD = "bs";
+static const QString SCRIPT_FIELD = "script";
class FSTReader {
public:
@@ -49,6 +50,8 @@ public:
/// Predicts the type of model by examining the mapping
static ModelType predictModelType(const QVariantHash& mapping);
+ static QVector getScripts(const QUrl& fstUrl, const QVariantHash& mapping = QVariantHash());
+
static QString getNameFromType(ModelType modelType);
static FSTReader::ModelType getTypeFromName(const QString& name);
static QVariantHash downloadMapping(const QString& url);
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-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/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;
diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h
index 7b46b35521..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(unsigned int size = 2U) : _size{ size } {}
+ SwapChain(uint8_t size = 2U) : _size{ size } {}
virtual ~SwapChain() {}
void advance() {
_frontIndex = (_frontIndex + 1) % _size;
}
- unsigned int getSize() const { return _size; }
+ uint8_t getSize() const { return _size; }
protected:
- unsigned int _size;
- unsigned int _frontIndex{ 0U };
+ const uint8_t _size;
+ uint8_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((uint8_t)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/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h
index 526352804b..b88c6345cf 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 {
@@ -39,7 +42,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 +57,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
diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp
index 957104bd30..7ee2135325 100644
--- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp
+++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp
@@ -43,6 +43,18 @@ void TouchscreenVirtualPadDevice::init() {
_fixedPosition = true; // This should be config
_viewTouchUpdateCount = 0;
+ resize();
+
+ auto& virtualPadManager = VirtualPad::Manager::instance();
+
+ if (_fixedPosition) {
+ virtualPadManager.getLeftVirtualPad()->setShown(virtualPadManager.isEnabled() && !virtualPadManager.isHidden()); // Show whenever it's enabled
+ }
+
+ KeyboardMouseDevice::enableTouch(false); // Touch for view controls is managed by this plugin
+}
+
+void TouchscreenVirtualPadDevice::resize() {
QScreen* eventScreen = qApp->primaryScreen();
if (_screenDPIProvided != eventScreen->physicalDotsPerInch()) {
_screenWidthCenter = eventScreen->size().width() / 2;
@@ -59,12 +71,6 @@ void TouchscreenVirtualPadDevice::init() {
auto& virtualPadManager = VirtualPad::Manager::instance();
setupControlsPositions(virtualPadManager, true);
-
- if (_fixedPosition) {
- virtualPadManager.getLeftVirtualPad()->setShown(virtualPadManager.isEnabled() && !virtualPadManager.isHidden()); // Show whenever it's enabled
- }
-
- KeyboardMouseDevice::enableTouch(false); // Touch for view controls is managed by this plugin
}
void TouchscreenVirtualPadDevice::setupControlsPositions(VirtualPad::Manager& virtualPadManager, bool force) {
@@ -80,9 +86,10 @@ void TouchscreenVirtualPadDevice::setupControlsPositions(VirtualPad::Manager& vi
virtualPadManager.getLeftVirtualPad()->setFirstTouch(_moveRefTouchPoint);
// Jump button
- float leftMargin = _screenDPI * VirtualPad::Manager::JUMP_BTN_LEFT_MARGIN_PIXELS / VirtualPad::Manager::DPI;
+ float jumpBtnPixelSize = _screenDPI * VirtualPad::Manager::JUMP_BTN_FULL_PIXELS / VirtualPad::Manager::DPI;
+ float rightMargin = _screenDPI * VirtualPad::Manager::JUMP_BTN_RIGHT_MARGIN_PIXELS / VirtualPad::Manager::DPI;
float bottomMargin = _screenDPI * VirtualPad::Manager::JUMP_BTN_BOTTOM_MARGIN_PIXELS/ VirtualPad::Manager::DPI;
- _jumpButtonPosition = glm::vec2( _jumpButtonRadius + leftMargin, eventScreen->size().height() - bottomMargin - _jumpButtonRadius - _extraBottomMargin);
+ _jumpButtonPosition = glm::vec2( eventScreen->size().width() - rightMargin - jumpBtnPixelSize, eventScreen->size().height() - bottomMargin - _jumpButtonRadius - _extraBottomMargin);
virtualPadManager.setJumpButtonPosition(_jumpButtonPosition);
}
diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h
index 212b7633ec..e7e540b503 100644
--- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h
+++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h
@@ -26,6 +26,7 @@ public:
// Plugin functions
virtual void init() override;
+ virtual void resize();
virtual bool isSupported() const override;
virtual const QString getName() const override { return NAME; }
diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp
index f17cdbb7e8..45f2462f57 100644
--- a/libraries/model-networking/src/model-networking/ModelCache.cpp
+++ b/libraries/model-networking/src/model-networking/ModelCache.cpp
@@ -63,16 +63,18 @@ 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";
finishedLoading(false);
} 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 += '/';
@@ -82,7 +84,16 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) {
_textureBaseUrl = url.resolved(QUrl("."));
}
- auto animGraphVariant = mapping.value("animGraphUrl");
+ auto scripts = FSTReader::getScripts(_url, _mapping);
+ if (scripts.size() > 0) {
+ _mapping.remove(SCRIPT_FIELD);
+ for (auto &scriptPath : scripts) {
+ _mapping.insertMulti(SCRIPT_FIELD, scriptPath);
+ }
+ }
+
+ auto animGraphVariant = _mapping.value("animGraphUrl");
+
if (animGraphVariant.isValid()) {
QUrl fstUrl(animGraphVariant.toString());
if (fstUrl.isValid()) {
@@ -95,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();
@@ -209,6 +220,14 @@ void GeometryReader::run() {
throw QString("unsupported format");
}
+ // Add scripts to fbxgeometry
+ if (!_mapping.value(SCRIPT_FIELD).isNull()) {
+ QVariantList scripts = _mapping.values(SCRIPT_FIELD);
+ for (auto &script : scripts) {
+ fbxGeometry->scripts.push_back(script.toString());
+ }
+ }
+
// Ensure the resource has not been deleted
auto resource = _resource.toStrongRef();
if (!resource) {
@@ -362,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 9532f39ce0..7e911bc9bf 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 };
@@ -144,6 +146,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.
@@ -156,7 +161,7 @@ public:
/**jsdoc
* Get the list of all resource URLs.
* @function ModelCache.getResourceList
- * @return {string[]}
+ * @returns {string[]}
*/
/**jsdoc
@@ -170,10 +175,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 +188,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..4ea8a98976 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.
@@ -160,44 +163,38 @@ public:
// 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 +243,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/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp
index f6264a19c4..049129b2ba 100644
--- a/libraries/networking/src/AccountManager.cpp
+++ b/libraries/networking/src/AccountManager.cpp
@@ -106,7 +106,11 @@ void AccountManager::logout() {
}
QString accountFileDir() {
+#if defined(Q_OS_ANDROID)
+ return QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/../files";
+#else
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
+#endif
}
QString accountFilePath() {
diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp
index 055d94c3b3..edb2992128 100644
--- a/libraries/networking/src/AddressManager.cpp
+++ b/libraries/networking/src/AddressManager.cpp
@@ -114,8 +114,6 @@ QUrl AddressManager::currentFacingPublicAddress() const {
void AddressManager::loadSettings(const QString& lookupString) {
#if defined(USE_GLES) && defined(Q_OS_WIN)
handleUrl(QUrl("hifi://127.0.0.0"), LookupTrigger::StartupFromSettings);
-#elif defined(Q_OS_ANDROID)
- handleUrl(QUrl("hifi://pikachu/167.11,0.745735,181.529/0,0.887027,0,-0.461717"), LookupTrigger::StartupFromSettings);
#else
if (lookupString.isEmpty()) {
handleUrl(currentAddressHandle.get(), LookupTrigger::StartupFromSettings);
diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h
index 94eff46bda..8e2553779b 100644
--- a/libraries/networking/src/AddressManager.h
+++ b/libraries/networking/src/AddressManager.h
@@ -33,11 +33,14 @@ 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.
- * @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 +71,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;
diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp
index 31500be682..0660f02fd6 100644
--- a/libraries/networking/src/LimitedNodeList.cpp
+++ b/libraries/networking/src/LimitedNodeList.cpp
@@ -302,6 +302,7 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
}
} else {
NLPacket::LocalID sourceLocalID = Node::NULL_LOCAL_ID;
+
// check if we were passed a sourceNode hint or if we need to look it up
if (!sourceNode) {
// figure out which node this is from
@@ -314,6 +315,7 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
QUuid sourceID = sourceNode ? sourceNode->getUUID() : QUuid();
if (!sourceNode &&
+ !isDomainServer() &&
sourceLocalID == getDomainLocalID() &&
packet.getSenderSockAddr() == getDomainSockAddr() &&
PacketTypeEnum::getDomainSourcedPackets().contains(headerType)) {
@@ -608,6 +610,7 @@ bool LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID, ConnectionID newCo
{
QWriteLocker writeLocker(&_nodeMutex);
+ _localIDMap.unsafe_erase(matchingNode->getLocalID());
_nodeHash.unsafe_erase(it);
}
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/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;
diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp
index 7ba7cca96d..d3583687e8 100644
--- a/libraries/networking/src/ResourceCache.cpp
+++ b/libraries/networking/src/ResourceCache.cpp
@@ -750,6 +750,7 @@ bool Resource::handleFailedRequest(ResourceRequest::Result result) {
qCDebug(networking) << "Timed out loading" << _url << "received" << _bytesReceived << "total" << _bytesTotal;
// Fall through to other cases
}
+ // FALLTHRU
case ResourceRequest::Result::ServerUnavailable: {
_attempts++;
_attemptsRemaining--;
@@ -768,6 +769,7 @@ bool Resource::handleFailedRequest(ResourceRequest::Result result) {
}
// fall through to final failure
}
+ // FALLTHRU
default: {
_attemptsRemaining = 0;
qCDebug(networking) << "Error loading " << _url << "attempt:" << _attempts << "attemptsRemaining:" << _attemptsRemaining;
diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h
index 609483bc56..e2df582aa3 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.
*/
@@ -209,7 +215,7 @@ public:
/**jsdoc
* Get the list of all resource URLs.
* @function ResourceCache.getResourceList
- * @return {string[]}
+ * @returns {string[]}
*/
Q_INVOKABLE QVariantList getResourceList();
@@ -251,10 +257,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 +274,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 +292,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.
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
diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp
index 98b0e1d892..17b0d90cfe 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:
@@ -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 e6b133c158..c72bbb0129 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 {
@@ -327,4 +328,8 @@ enum class PingVersion : PacketVersion {
IncludeConnectionID = 18
};
+enum class ViewFrustumVersion : PacketVersion {
+ SendMultipleFrustums = 21
+};
+
#endif // hifi_PacketHeaders_h
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/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp
index c2bacd4949..68f21eea87 100644
--- a/libraries/physics/src/EntityMotionState.cpp
+++ b/libraries/physics/src/EntityMotionState.cpp
@@ -447,7 +447,12 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) {
// this case is prevented by setting _ownershipState to UNOWNABLE in EntityMotionState::ctor
assert(!(_entity->getClientOnly() && _entity->getOwningAvatarID() != Physics::getSessionUUID()));
- if (_entity->dynamicDataNeedsTransmit() || _entity->queryAACubeNeedsUpdate()) {
+ // shouldSendUpdate() sould NOT be triggering updates to maintain the queryAACube of dynamic entities.
+ // The server is supposed to predict the transform of such moving things. The client performs a "double prediction"
+ // where it predicts what the the server is doing, and only sends updates whent the entity's true transform
+ // differs significantly. That is what the remoteSimulationOutOfSync() logic is all about.
+ if (_entity->dynamicDataNeedsTransmit() ||
+ (!_entity->getDynamic() && _entity->queryAACubeNeedsUpdate())) {
return true;
}
diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp
index ab7c2ec252..3ea3616b15 100644
--- a/libraries/physics/src/PhysicalEntitySimulation.cpp
+++ b/libraries/physics/src/PhysicalEntitySimulation.cpp
@@ -153,6 +153,8 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
// remove the objects (aka MotionStates) from physics
_physicsEngine->removeSetOfObjects(_physicalObjects);
+ clearOwnershipData();
+
// delete the MotionStates
for (auto stateItr : _physicalObjects) {
EntityMotionState* motionState = static_cast(&(*stateItr));
@@ -165,7 +167,6 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
_physicalObjects.clear();
// clear all other lists specific to this derived class
- clearOwnershipData();
_entitiesToRemoveFromPhysics.clear();
_entitiesToAddToPhysics.clear();
_incomingChanges.clear();
diff --git a/libraries/physics/src/PhysicsDebugDraw.cpp b/libraries/physics/src/PhysicsDebugDraw.cpp
new file mode 100644
index 0000000000..b2911219d5
--- /dev/null
+++ b/libraries/physics/src/PhysicsDebugDraw.cpp
@@ -0,0 +1,54 @@
+//
+// PhysicsDebugDraw.cpp
+// libraries/physics/src
+//
+// Created by Anthony Thibault 2018-4-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 "PhysicsDebugDraw.h"
+#include "BulletUtil.h"
+#include "PhysicsLogging.h"
+
+#include
+#include
+
+void PhysicsDebugDraw::drawLine(const btVector3& from, const btVector3& to, const btVector3& color) {
+ DebugDraw::getInstance().drawRay(bulletToGLM(from), bulletToGLM(to), glm::vec4(color.getX(), color.getY(), color.getZ(), 1.0f));
+}
+
+void PhysicsDebugDraw::drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance,
+ int lifeTime, const btVector3& color) {
+
+ glm::vec3 normal, tangent, biNormal;
+ generateBasisVectors(bulletToGLM(normalOnB), Vectors::UNIT_X, normal, tangent, biNormal);
+ btVector3 u = glmToBullet(normal);
+ btVector3 v = glmToBullet(tangent);
+ btVector3 w = glmToBullet(biNormal);
+
+ // x marks the spot, green is along the normal.
+ const float CONTACT_POINT_RADIUS = 0.1f;
+ const btVector3 GREEN(0.0f, 1.0f, 0.0f);
+ const btVector3 WHITE(1.0f, 1.0f, 1.0f);
+ drawLine(PointOnB - u * CONTACT_POINT_RADIUS, PointOnB + u * CONTACT_POINT_RADIUS, GREEN);
+ drawLine(PointOnB - v * CONTACT_POINT_RADIUS, PointOnB + v * CONTACT_POINT_RADIUS, WHITE);
+ drawLine(PointOnB - w * CONTACT_POINT_RADIUS, PointOnB + w * CONTACT_POINT_RADIUS, WHITE);
+}
+
+void PhysicsDebugDraw::reportErrorWarning(const char* warningString) {
+ qCWarning(physics) << "BULLET:" << warningString;
+}
+
+void PhysicsDebugDraw::draw3dText(const btVector3& location, const char* textString) {
+}
+
+void PhysicsDebugDraw::setDebugMode(int debugMode) {
+ _debugDrawMode = debugMode;
+}
+
+int PhysicsDebugDraw::getDebugMode() const {
+ return _debugDrawMode;
+}
diff --git a/libraries/physics/src/PhysicsDebugDraw.h b/libraries/physics/src/PhysicsDebugDraw.h
new file mode 100644
index 0000000000..f653136474
--- /dev/null
+++ b/libraries/physics/src/PhysicsDebugDraw.h
@@ -0,0 +1,34 @@
+//
+// PhysicsDebugDraw.h
+// libraries/physics/src
+//
+// Created by Anthony Thibault 2018-4-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
+//
+// http://bulletphysics.org/Bullet/BulletFull/classbtIDebugDraw.html
+
+#ifndef hifi_PhysicsDebugDraw_h
+#define hifi_PhysicsDebugDraw_h
+
+#include
+#include
+
+class PhysicsDebugDraw : public btIDebugDraw {
+public:
+ using btIDebugDraw::drawLine;
+ virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) override;
+ virtual void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance,
+ int lifeTime, const btVector3& color) override;
+ virtual void reportErrorWarning(const char* warningString) override;
+ virtual void draw3dText(const btVector3& location, const char* textString) override;
+ virtual void setDebugMode(int debugMode) override;
+ virtual int getDebugMode() const override;
+
+protected:
+ uint32_t _debugDrawMode;
+};
+
+#endif // hifi_PhysicsDebugDraw_h
diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp
index 7c2ad55405..50d516c256 100644
--- a/libraries/physics/src/PhysicsEngine.cpp
+++ b/libraries/physics/src/PhysicsEngine.cpp
@@ -22,6 +22,7 @@
#include "ObjectMotionState.h"
#include "PhysicsEngine.h"
#include "PhysicsHelpers.h"
+#include "PhysicsDebugDraw.h"
#include "ThreadSafeDynamicsWorld.h"
#include "PhysicsLogging.h"
@@ -49,6 +50,10 @@ void PhysicsEngine::init() {
_broadphaseFilter = new btDbvtBroadphase();
_constraintSolver = new btSequentialImpulseConstraintSolver;
_dynamicsWorld = new ThreadSafeDynamicsWorld(_collisionDispatcher, _broadphaseFilter, _constraintSolver, _collisionConfig);
+ _physicsDebugDraw.reset(new PhysicsDebugDraw());
+
+ // hook up debug draw renderer
+ _dynamicsWorld->setDebugDrawer(_physicsDebugDraw.get());
_ghostPairCallback = new btGhostPairCallback();
_dynamicsWorld->getPairCache()->setInternalGhostPairCallback(_ghostPairCallback);
@@ -333,6 +338,10 @@ void PhysicsEngine::stepSimulation() {
_hasOutgoingChanges = true;
}
+
+ if (_physicsDebugDraw->getDebugMode()) {
+ _dynamicsWorld->debugDrawWorld();
+ }
}
class CProfileOperator {
@@ -785,3 +794,49 @@ void PhysicsEngine::forEachDynamic(std::function act
}
}
}
+
+void PhysicsEngine::setShowBulletWireframe(bool value) {
+ int mode = _physicsDebugDraw->getDebugMode();
+ if (value) {
+ _physicsDebugDraw->setDebugMode(mode | btIDebugDraw::DBG_DrawWireframe);
+ } else {
+ _physicsDebugDraw->setDebugMode(mode & ~btIDebugDraw::DBG_DrawWireframe);
+ }
+}
+
+void PhysicsEngine::setShowBulletAABBs(bool value) {
+ int mode = _physicsDebugDraw->getDebugMode();
+ if (value) {
+ _physicsDebugDraw->setDebugMode(mode | btIDebugDraw::DBG_DrawAabb);
+ } else {
+ _physicsDebugDraw->setDebugMode(mode & ~btIDebugDraw::DBG_DrawAabb);
+ }
+}
+
+void PhysicsEngine::setShowBulletContactPoints(bool value) {
+ int mode = _physicsDebugDraw->getDebugMode();
+ if (value) {
+ _physicsDebugDraw->setDebugMode(mode | btIDebugDraw::DBG_DrawContactPoints);
+ } else {
+ _physicsDebugDraw->setDebugMode(mode & ~btIDebugDraw::DBG_DrawContactPoints);
+ }
+}
+
+void PhysicsEngine::setShowBulletConstraints(bool value) {
+ int mode = _physicsDebugDraw->getDebugMode();
+ if (value) {
+ _physicsDebugDraw->setDebugMode(mode | btIDebugDraw::DBG_DrawConstraints);
+ } else {
+ _physicsDebugDraw->setDebugMode(mode & ~btIDebugDraw::DBG_DrawConstraints);
+ }
+}
+
+void PhysicsEngine::setShowBulletConstraintLimits(bool value) {
+ int mode = _physicsDebugDraw->getDebugMode();
+ if (value) {
+ _physicsDebugDraw->setDebugMode(mode | btIDebugDraw::DBG_DrawConstraintLimits);
+ } else {
+ _physicsDebugDraw->setDebugMode(mode & ~btIDebugDraw::DBG_DrawConstraintLimits);
+ }
+}
+
diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h
index 92d2e6885a..0dfe3a7a7c 100644
--- a/libraries/physics/src/PhysicsEngine.h
+++ b/libraries/physics/src/PhysicsEngine.h
@@ -30,6 +30,7 @@
const float HALF_SIMULATION_EXTENT = 512.0f; // meters
class CharacterController;
+class PhysicsDebugDraw;
// simple class for keeping track of contacts
class ContactKey {
@@ -96,6 +97,12 @@ public:
void removeDynamic(const QUuid dynamicID);
void forEachDynamic(std::function actor);
+ void setShowBulletWireframe(bool value);
+ void setShowBulletAABBs(bool value);
+ void setShowBulletContactPoints(bool value);
+ void setShowBulletConstraints(bool value);
+ void setShowBulletConstraintLimits(bool value);
+
private:
QList removeDynamicsForBody(btRigidBody* body);
void addObjectToDynamicsWorld(ObjectMotionState* motionState);
@@ -114,6 +121,7 @@ private:
btSequentialImpulseConstraintSolver* _constraintSolver = NULL;
ThreadSafeDynamicsWorld* _dynamicsWorld = NULL;
btGhostPairCallback* _ghostPairCallback = NULL;
+ std::unique_ptr _physicsDebugDraw;
ContactMap _contactMap;
CollisionEvents _collisionEvents;
diff --git a/libraries/qml/src/qml/impl/SharedObject.cpp b/libraries/qml/src/qml/impl/SharedObject.cpp
index 9253c41b39..2fde057ca8 100644
--- a/libraries/qml/src/qml/impl/SharedObject.cpp
+++ b/libraries/qml/src/qml/impl/SharedObject.cpp
@@ -90,19 +90,23 @@ SharedObject::~SharedObject() {
_renderControl = nullptr;
}
+ if (_rootItem) {
+ delete _rootItem;
+ _rootItem = nullptr;
+ }
+
if (_quickWindow) {
_quickWindow->destroy();
delete _quickWindow;
_quickWindow = nullptr;
}
- // _rootItem is parented to the quickWindow, so needs no explicit destruction
- //if (_rootItem) {
- // delete _rootItem;
- // _rootItem = nullptr;
- //}
-
- releaseEngine(_qmlContext->engine());
+ if (_qmlContext) {
+ auto engine = _qmlContext->engine();
+ delete _qmlContext;
+ _qmlContext = nullptr;
+ releaseEngine(engine);
+ }
}
void SharedObject::create(OffscreenSurface* surface) {
@@ -210,9 +214,9 @@ QQmlEngine* SharedObject::acquireEngine(OffscreenSurface* surface) {
if (!globalEngine) {
Q_ASSERT(0 == globalEngineRefCount);
globalEngine = new QQmlEngine();
- surface->initializeQmlEngine(result);
- ++globalEngineRefCount;
+ surface->initializeEngine(result);
}
+ ++globalEngineRefCount;
result = globalEngine;
#else
result = new QQmlEngine();
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/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp
index 7086b65f4c..eca500f36c 100644
--- a/libraries/render-utils/src/AnimDebugDraw.cpp
+++ b/libraries/render-utils/src/AnimDebugDraw.cpp
@@ -52,9 +52,9 @@ public:
batch.setInputFormat(_vertexFormat);
batch.setInputBuffer(0, _vertexBuffer, 0, sizeof(Vertex));
- batch.setIndexBuffer(gpu::UINT16, _indexBuffer, 0);
+ batch.setIndexBuffer(gpu::UINT32, _indexBuffer, 0);
- auto numIndices = _indexBuffer->getSize() / sizeof(uint16_t);
+ auto numIndices = _indexBuffer->getSize() / sizeof(uint32_t);
batch.drawIndexed(gpu::LINES, (int)numIndices);
}
@@ -135,9 +135,9 @@ AnimDebugDraw::AnimDebugDraw() :
AnimDebugDrawData::Vertex { glm::vec3(1.0, 1.0f, 1.0f), toRGBA(0, 0, 255, 255) },
AnimDebugDrawData::Vertex { glm::vec3(1.0, 1.0f, 2.0f), toRGBA(0, 0, 255, 255) },
});
- static std::vector indices({ 0, 1, 2, 3, 4, 5 });
+ static std::vector indices({ 0, 1, 2, 3, 4, 5 });
_animDebugDrawData->_vertexBuffer->setSubData(0, vertices);
- _animDebugDrawData->_indexBuffer->setSubData(0, indices);
+ _animDebugDrawData->_indexBuffer->setSubData(0, indices);
}
AnimDebugDraw::~AnimDebugDraw() {
@@ -425,9 +425,9 @@ void AnimDebugDraw::update() {
data._isVisible = (numVerts > 0);
- data._indexBuffer->resize(sizeof(uint16_t) * numVerts);
+ data._indexBuffer->resize(sizeof(uint32_t) * numVerts);
for (int i = 0; i < numVerts; i++) {
- data._indexBuffer->setSubData(i, (uint16_t)i);;
+ data._indexBuffer->setSubData(i, (uint32_t)i);;
}
});
scene->enqueueTransaction(transaction);
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) {
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.cpp b/libraries/script-engine/src/ScriptEngine.cpp
index c79ffffec7..4915a2dc8b 100644
--- a/libraries/script-engine/src/ScriptEngine.cpp
+++ b/libraries/script-engine/src/ScriptEngine.cpp
@@ -180,6 +180,21 @@ ScriptEngine::ScriptEngine(Context context, const QString& scriptContents, const
// don't delete `ScriptEngines` until all `ScriptEngine`s are gone
_scriptEngines(DependencyManager::get())
{
+ switch (_context) {
+ case Context::CLIENT_SCRIPT:
+ _type = Type::CLIENT;
+ break;
+ case Context::ENTITY_CLIENT_SCRIPT:
+ _type = Type::ENTITY_CLIENT;
+ break;
+ case Context::ENTITY_SERVER_SCRIPT:
+ _type = Type::ENTITY_SERVER;
+ break;
+ case Context::AGENT_SCRIPT:
+ _type = Type::AGENT;
+ break;
+ }
+
connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) {
if (hasUncaughtException()) {
// the engine's uncaughtException() seems to produce much better stack traces here
@@ -2161,6 +2176,32 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString&
}, forceRedownload);
}
+/**jsdoc
+ * Triggered when the script starts for a user.
+ *
Note: Can only be connected to via this.preload = function (...) { ... } in the entity script.
+ *
Available in:
Client Entity Scripts
Server Entity Scripts
+ * @function Entities.preload
+ * @param {Uuid} entityID - The ID of the entity that the script is running in.
+ * @returns {Signal}
+ * @example
Get the ID of the entity that a client entity script is running in.
+ * var entityScript = (function () {
+ * this.entityID = Uuid.NULL;
+ *
+ * this.preload = function (entityID) {
+ * this.entityID = entityID;
+ * print("Entity ID: " + this.entityID);
+ * };
+ * );
+ *
+ * var entityID = Entities.addEntity({
+ * type: "Box",
+ * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -5 })),
+ * dimensions: { x: 0.5, y: 0.5, z: 0.5 },
+ * color: { red: 255, green: 0, blue: 0 },
+ * script: "(" + entityScript + ")", // Could host the script on a Web server instead.
+ * lifetime: 300 // Delete after 5 minutes.
+ * });
+ */
// since all of these operations can be asynch we will always do the actual work in the response handler
// for the download
void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success , const QString& status) {
@@ -2345,6 +2386,13 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
processDeferredEntityLoads(entityScript, entityID);
}
+/**jsdoc
+ * Triggered when the script terminates for a user.
+ *
Note: Can only be connected to via this.unoad = function () { ... } in the entity script.