diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 2faa9809bb..bc6e5c8386 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -5,7 +5,7 @@ If you are upgrading from previous versions, do a clean uninstall of those versi Note: The prerequisites will require about 10 GB of space on your drive. You will also need a system with at least 8GB of main memory. -### Step 1. Visual Studio & Python +### Step 1. Visual Studio & Python 3.x If you don’t have Community or Professional edition of Visual Studio, download [Visual Studio Community 2019](https://visualstudio.microsoft.com/vs/). If you have Visual Studio 2017, you are not required to download Visual Studio 2019. @@ -21,7 +21,7 @@ When selecting components, check "Desktop development with C++". On the right on * MSVC v141 - VS 2017 C++ x64/x86 build tools * MSVC v140 - VS 2015 C++ build tools (v14.00) -If you do not already have a Python development environment installed, also check "Python Development" in this screen. +If you do not already have a Python 3.x development environment installed, also check "Python Development" in this screen. If you already have Visual Studio installed and need to add Python, open the "Add or remove programs" control panel and find the "Microsoft Visual Studio Installer". Select it and click "Modify". In the installer, select "Modify" again, then check "Python Development" and allow the installer to apply the changes. @@ -31,9 +31,10 @@ If you do not wish to use the Python installation bundled with Visual Studio, yo ### Step 2. Installing CMake -Download and install the latest version of CMake 3.14. +Download and install the latest version of CMake 3.15. + * Note that earlier versions of CMake will work, but there is a specific bug related to the interaction of Visual Studio 2019 and CMake versions prior to 3.15 that will cause Visual Studio to rebuild far more than it needs to on every build -Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.14 Version page](https://cmake.org/files/v3.14/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted. +Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.15 Version page](https://cmake.org/files/v3.15/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted. ### Step 3. Create VCPKG environment variable In the next step, you will use CMake to build High Fidelity. By default, the CMake process builds dependency files in Windows' `%TEMP%` directory, which is periodically cleared by the operating system. To prevent you from having to re-build the dependencies in the event that Windows clears that directory, we recommend that you create a `HIFI_VCPKG_BASE` environment variable linked to a directory somewhere on your machine. That directory will contain all dependency files until you manually remove them. @@ -42,9 +43,18 @@ To create this variable: * Naviagte to 'Edit the System Environment Variables' Through the start menu. * Click on 'Environment Variables' * Select 'New' -* Set "Variable name" to HIFI_VCPKG_BASE +* Set "Variable name" to `HIFI_VCPKG_BASE` * Set "Variable value" to any directory that you have control over. +Additionally, if you have Visual Studio 2019 installed and _only_ Visual Studio 2019 (i.e. you do not have Visual Studio 2017 installed) you must add an additional environment variable `HIFI_VCPKG_BOOTSTRAP` that will fix a bug in our `vcpkg` pre-build step. + +To create this variable: +* Naviagte to 'Edit the System Environment Variables' Through the start menu. +* Click on 'Environment Variables' +* Select 'New' +* Set "Variable name" to `HIFI_VCPKG_BOOTSTRAP` +* Set "Variable value" to `1` + ### Step 4. Running CMake to Generate Build Files Run Command Prompt from Start and run the following commands: diff --git a/assignment-client/src/avatars/AvatarMixerSlavePool.h b/assignment-client/src/avatars/AvatarMixerSlavePool.h index c8f4c252b1..915c6d8dc4 100644 --- a/assignment-client/src/avatars/AvatarMixerSlavePool.h +++ b/assignment-client/src/avatars/AvatarMixerSlavePool.h @@ -75,7 +75,7 @@ public: void each(std::function functor); #ifdef DEBUG_EVENT_QUEUE - void AvatarMixerSlavePool::queueStats(QJsonObject& stats); + void queueStats(QJsonObject& stats); #endif void setNumThreads(int numThreads); diff --git a/hifi_vcpkg.py b/hifi_vcpkg.py index 764a6270bd..821d9ae0b7 100644 --- a/hifi_vcpkg.py +++ b/hifi_vcpkg.py @@ -71,16 +71,19 @@ endif() if 'Windows' == system: self.exe = os.path.join(self.path, 'vcpkg.exe') + self.bootstrapCmd = 'bootstrap-vcpkg.bat' self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-win32.tar.gz?versionId=YZYkDejDRk7L_hrK_WVFthWvisAhbDzZ' self.vcpkgHash = '3e0ff829a74956491d57666109b3e6b5ce4ed0735c24093884317102387b2cb1b2cd1ff38af9ed9173501f6e32ffa05cc6fe6d470b77a71ca1ffc3e0aa46ab9e' self.hostTriplet = 'x64-windows' elif 'Darwin' == system: self.exe = os.path.join(self.path, 'vcpkg') + self.bootstrapCmd = 'bootstrap-vcpkg.sh' self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-osx.tar.gz?versionId=_fhqSxjfrtDJBvEsQ8L_ODcdUjlpX9cc' self.vcpkgHash = '519d666d02ef22b87c793f016ca412e70f92e1d55953c8f9bd4ee40f6d9f78c1df01a6ee293907718f3bbf24075cc35492fb216326dfc50712a95858e9cbcb4d' self.hostTriplet = 'x64-osx' else: self.exe = os.path.join(self.path, 'vcpkg') + self.bootstrapCmd = 'bootstrap-vcpkg.sh' self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-linux.tar.gz?versionId=97Nazh24etEVKWz33XwgLY0bvxEfZgMU' self.vcpkgHash = '6a1ce47ef6621e699a4627e8821ad32528c82fce62a6939d35b205da2d299aaa405b5f392df4a9e5343dd6a296516e341105fbb2dd8b48864781d129d7fba10d' self.hostTriplet = 'x64-linux' @@ -141,8 +144,14 @@ endif() downloadVcpkg = True if downloadVcpkg: - print("Fetching vcpkg from {} to {}".format(self.vcpkgUrl, self.path)) - hifi_utils.downloadAndExtract(self.vcpkgUrl, self.path, self.vcpkgHash) + if "HIFI_VCPKG_BOOTSTRAP" in os.environ: + print("Cloning vcpkg from github to {}".format(self.path)) + hifi_utils.executeSubprocess(['git', 'clone', 'git@github.com:microsoft/vcpkg.git', self.path]) + print("Bootstrapping vcpkg") + hifi_utils.executeSubprocess([self.bootstrapCmd], folder=self.path) + else: + print("Fetching vcpkg from {} to {}".format(self.vcpkgUrl, self.path)) + hifi_utils.downloadAndExtract(self.vcpkgUrl, self.path, self.vcpkgHash) print("Replacing port files") portsPath = os.path.join(self.path, 'ports') diff --git a/interface/resources/avatar/animations/emote_clap02_all.fbx b/interface/resources/avatar/animations/emote_clap02_all.fbx index 5584a38ac0..caf673f28a 100644 Binary files a/interface/resources/avatar/animations/emote_clap02_all.fbx and b/interface/resources/avatar/animations/emote_clap02_all.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_agree_headnod.fbx b/interface/resources/avatar/animations/sitting_emote_agree_headnod.fbx new file mode 100644 index 0000000000..655608fe55 Binary files /dev/null and b/interface/resources/avatar/animations/sitting_emote_agree_headnod.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_agree_headnodyes.fbx b/interface/resources/avatar/animations/sitting_emote_agree_headnodyes.fbx new file mode 100644 index 0000000000..cfe90c45f0 Binary files /dev/null and b/interface/resources/avatar/animations/sitting_emote_agree_headnodyes.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_agree_longheadnod.fbx b/interface/resources/avatar/animations/sitting_emote_agree_longheadnod.fbx new file mode 100644 index 0000000000..ead3a29fe6 Binary files /dev/null and b/interface/resources/avatar/animations/sitting_emote_agree_longheadnod.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_clap_all.fbx b/interface/resources/avatar/animations/sitting_emote_clap_all.fbx new file mode 100644 index 0000000000..947ef4541a Binary files /dev/null and b/interface/resources/avatar/animations/sitting_emote_clap_all.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_disagree_drophead.fbx b/interface/resources/avatar/animations/sitting_emote_disagree_drophead.fbx new file mode 100644 index 0000000000..239b242aab Binary files /dev/null and b/interface/resources/avatar/animations/sitting_emote_disagree_drophead.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_disagree_headshake.fbx b/interface/resources/avatar/animations/sitting_emote_disagree_headshake.fbx new file mode 100644 index 0000000000..7c6f90ee89 Binary files /dev/null and b/interface/resources/avatar/animations/sitting_emote_disagree_headshake.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_point_all.fbx b/interface/resources/avatar/animations/sitting_emote_point_all.fbx new file mode 100644 index 0000000000..f850c8e9b3 Binary files /dev/null and b/interface/resources/avatar/animations/sitting_emote_point_all.fbx differ diff --git a/interface/resources/avatar/animations/sitting_emote_raisehand_all.fbx b/interface/resources/avatar/animations/sitting_emote_raisehand_all.fbx new file mode 100644 index 0000000000..7f1b2efea2 Binary files /dev/null and b/interface/resources/avatar/animations/sitting_emote_raisehand_all.fbx differ diff --git a/interface/resources/avatar/animations/sitting_talk04.fbx b/interface/resources/avatar/animations/sitting_talk04.fbx new file mode 100644 index 0000000000..ee920672fa Binary files /dev/null and b/interface/resources/avatar/animations/sitting_talk04.fbx differ diff --git a/interface/resources/avatar/avatar-animation.json b/interface/resources/avatar/avatar-animation.json index 0c8d331164..b23e1c74d9 100644 --- a/interface/resources/avatar/avatar-animation.json +++ b/interface/resources/avatar/avatar-animation.json @@ -615,6 +615,19 @@ }, "id": "seatedTalk03", "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 442, + "loopFlag": true, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_talk04.fbx" + }, + "id": "seatedTalk04", + "type": "clip" } ], "data": { @@ -639,6 +652,15 @@ "resume": true, "transitions": [ ] + }, + { + "id": "seatedTalk04", + "interpDuration": 6, + "interpTarget": 6, + "priority": 1, + "resume": true, + "transitions": [ + ] } ] }, @@ -713,68 +735,433 @@ }, { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 44, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_agree_headnod.fbx" + }, + "id": "seatedReactionPositiveHeadNod", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 78, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_agree_headnodyes.fbx" + }, + "id": "seatedReactionPositiveHeadNodYes", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 65, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_agree_longheadnod.fbx" + }, + "id": "seatedReactionPositiveLongHeadNod", + "type": "clip" + } ], "data": { + "currentState": "seatedReactionPositiveHeadNod", "endFrame": 30, "loopFlag": false, + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, "startFrame": 0, + "states": [ + { + "id": "seatedReactionPositiveHeadNod", + "interpDuration": 6, + "interpTarget": 6, + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "id": "seatedReactionPositiveHeadNodYes", + "interpDuration": 6, + "interpTarget": 6, + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "id": "seatedReactionPositiveLongHeadNod", + "interpDuration": 6, + "interpTarget": 6, + "priority": 1, + "resume": false, + "transitions": [ + ] + } + ], "timeScale": 1, + "triggerRandomSwitch": "", "url": "qrc:///avatar/animations/sitting_idle.fbx" }, "id": "seatedReactionPositive", - "type": "clip" + "type": "randomSwitchStateMachine" }, { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 64, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_disagree_headshake.fbx" + }, + "id": "seatedReactionNegativeDisagreeHeadshake", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 158, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_disagree_drophead.fbx" + }, + "id": "seatedReactionNegativeDisagreeDropHead", + "type": "clip" + } ], "data": { + "currentState": "seatedReactionNegativeDisagreeHeadshake", "endFrame": 30, "loopFlag": false, + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, "startFrame": 0, + "states": [ + { + "id": "seatedReactionNegativeDisagreeHeadshake", + "interpDuration": 6, + "interpTarget": 6, + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "id": "seatedReactionNegativeDisagreeDropHead", + "interpDuration": 6, + "interpTarget": 6, + "priority": 1, + "resume": false, + "transitions": [ + ] + } + ], "timeScale": 1, + "triggerRandomSwitch": "", "url": "qrc:///avatar/animations/sitting_idle.fbx" }, "id": "seatedReactionNegative", - "type": "clip" + "type": "randomSwitchStateMachine" }, { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 32, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_raisehand_all.fbx" + }, + "id": "seatedReactionRaiseHandIntro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 345, + "loopFlag": true, + "startFrame": 32, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_raisehand_all.fbx" + }, + "id": "seatedReactionRaiseHandLoop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 400, + "loopFlag": false, + "startFrame": 345, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_raisehand_all.fbx" + }, + "id": "seatedReactionRaiseHandOutro", + "type": "clip" + } ], "data": { - "endFrame": 0, - "loopFlag": true, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle.fbx" + "currentState": "seatedReactionRaiseHandIntro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "seatedReactionRaiseHandIntro", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionRaiseHandLoop", + "var": "seatedReactionRaiseHandIntroOnDone" + } + ] + }, + { + "id": "seatedReactionRaiseHandLoop", + "interpDuration": 5, + "interpTarget": 5, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionRaiseHandOutro", + "var": "reactionRaiseHandDisabled" + } + ] + }, + { + "id": "seatedReactionRaiseHandOutro", + "interpDuration": 1, + "interpTarget": 1, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionRaiseHandLoop", + "var": "reactionRaiseHandEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" }, "id": "seatedReactionRaiseHand", - "type": "clip" + "type": "randomSwitchStateMachine" }, { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 12, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_clap_all.fbx" + }, + "id": "seatedReactionApplaudIntro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 76, + "loopFlag": true, + "startFrame": 12, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_clap_all.fbx" + }, + "id": "seatedReactionApplaudLoop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 99, + "loopFlag": false, + "startFrame": 76, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_clap_all.fbx" + }, + "id": "seatedReactionApplaudOutro", + "type": "clip" + } ], "data": { - "endFrame": 0, - "loopFlag": true, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle.fbx" + "currentState": "seatedReactionApplaudIntro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "seatedReactionApplaudIntro", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionApplaudLoop", + "var": "seatedReactionApplaudIntroOnDone" + } + ] + }, + { + "id": "seatedReactionApplaudLoop", + "interpDuration": 5, + "interpTarget": 5, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionApplaudOutro", + "var": "reactionApplaudDisabled" + } + ] + }, + { + "id": "seatedReactionApplaudOutro", + "interpDuration": 1, + "interpTarget": 1, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionApplaudLoop", + "var": "reactionApplaudEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" }, "id": "seatedReactionApplaud", - "type": "clip" + "type": "randomSwitchStateMachine" }, { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 22, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_all.fbx" + }, + "id": "seatedReactionPointIntro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 43, + "loopFlag": true, + "startFrame": 22, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_all.fbx" + }, + "id": "seatedReactionPointLoop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 71, + "loopFlag": false, + "startFrame": 43, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_all.fbx" + }, + "id": "seatedReactionPointOutro", + "type": "clip" + } ], "data": { - "endFrame": 0, - "loopFlag": true, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle.fbx" + "currentState": "seatedReactionPointIntro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "seatedReactionPointIntro", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionPointLoop", + "var": "seatedReactionPointIntroOnDone" + } + ] + }, + { + "id": "seatedReactionPointLoop", + "interpDuration": 5, + "interpTarget": 5, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionPointOutro", + "var": "reactionPointDisabled" + } + ] + }, + { + "id": "seatedReactionPointOutro", + "interpDuration": 1, + "interpTarget": 1, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionPointLoop", + "var": "reactionPointEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" }, "id": "seatedReactionPoint", - "type": "clip" + "type": "randomSwitchStateMachine" } ], "data": { @@ -783,9 +1170,9 @@ { "easingType": "easeInOutQuad", "id": "seatedTalkOverlay", - "interpDuration": 18, - "interpTarget": 18, - "interpType": "snapshotPrev", + "interpDuration": 15, + "interpTarget": 15, + "interpType": "evaluateBoth", "transitions": [ { "state": "seatedReactionPositive", @@ -817,7 +1204,15 @@ "transitions": [ { "state": "seatedTalkOverlay", - "var": "seatedReactionPositiveOnDone" + "var": "seatedReactionPositiveHeadNodOnDone" + }, + { + "state": "seatedTalkOverlay", + "var": "seatedReactionPositiveHeadNodYesOnDone" + }, + { + "state": "seatedTalkOverlay", + "var": "seatedReactionPositiveLongHeadNodOnDone" }, { "state": "seatedReactionNegative", @@ -849,7 +1244,11 @@ }, { "state": "seatedTalkOverlay", - "var": "seatedReactionNegativeOnDone" + "var": "seatedReactionNegativeDisagreeHeadshakeOnDone" + }, + { + "state": "seatedTalkOverlay", + "var": "seatedReactionNegativeDisagreeDropHeadOnDone" }, { "state": "seatedReactionRaiseHand", @@ -1859,11 +2258,8 @@ ], "data": { "currentState": "negativeAnnoyedHeadshake", - "endFrame": 110, - "loopFlag": false, "randomSwitchTimeMax": 10, "randomSwitchTimeMin": 1, - "startFrame": 0, "states": [ { "id": "negativeAnnoyedHeadshake", @@ -1901,42 +2297,285 @@ "children": [ { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 18, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_raisehand01_all.fbx" + }, + "id": "raiseHand01Intro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 378, + "loopFlag": true, + "startFrame": 18, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_raisehand01_all.fbx" + }, + "id": "raiseHand01Loop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 435, + "loopFlag": false, + "startFrame": 378, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_raisehand01_all.fbx" + }, + "id": "raiseHand01Outro", + "type": "clip" + } ], "data": { - "endFrame": 378, - "loopFlag": true, - "startFrame": 18, - "timeScale": 1, - "url": "qrc:///avatar/animations/emote_raisehand01_all.fbx" + "currentState": "raiseHand01Intro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "raiseHand01Intro", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "raiseHand01Loop", + "var": "raiseHand01IntroOnDone" + } + ] + }, + { + "id": "raiseHand01Loop", + "interpDuration": 5, + "interpTarget": 5, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "raiseHand01Outro", + "var": "reactionRaiseHandDisabled" + } + ] + }, + { + "id": "raiseHand01Outro", + "interpDuration": 1, + "interpTarget": 1, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "raiseHand01Loop", + "var": "reactionRaiseHandEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" }, "id": "raiseHand01", - "type": "clip" + "type": "randomSwitchStateMachine" }, { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 19, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_raisehand03_all.fbx" + }, + "id": "raiseHand03Intro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 237, + "loopFlag": true, + "startFrame": 19, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_raisehand03_all.fbx" + }, + "id": "raiseHand03Loop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 300, + "loopFlag": false, + "startFrame": 237, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_raisehand03_all.fbx" + }, + "id": "raiseHand03Outro", + "type": "clip" + } ], "data": { - "endFrame": 237, - "loopFlag": true, - "startFrame": 19, - "timeScale": 1, - "url": "qrc:///avatar/animations/emote_raisehand03_all.fbx" + "currentState": "raiseHand03Intro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "raiseHand03Intro", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "raiseHand03Loop", + "var": "raiseHand03IntroOnDone" + } + ] + }, + { + "id": "raiseHand03Loop", + "interpDuration": 5, + "interpTarget": 5, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "raiseHand03Outro", + "var": "reactionRaiseHandDisabled" + } + ] + }, + { + "id": "raiseHand03Outro", + "interpDuration": 1, + "interpTarget": 1, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "raiseHand03Loop", + "var": "reactionRaiseHandEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" }, "id": "raiseHand03", - "type": "clip" + "type": "randomSwitchStateMachine" }, { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 32, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_raisehand04_all.fbx" + }, + "id": "raiseHand04Intro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 345, + "loopFlag": true, + "startFrame": 32, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_raisehand04_all.fbx" + }, + "id": "raiseHand04Loop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 400, + "loopFlag": false, + "startFrame": 345, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_raisehand04_all.fbx" + }, + "id": "raiseHand04Outro", + "type": "clip" + } ], "data": { - "endFrame": 345, - "loopFlag": true, - "startFrame": 32, - "timeScale": 1, - "url": "qrc:///avatar/animations/emote_raisehand04_all.fbx" + "currentState": "raiseHand04Intro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "raiseHand04Intro", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "raiseHand04Loop", + "var": "raiseHand04IntroOnDone" + } + ] + }, + { + "id": "raiseHand04Loop", + "interpDuration": 5, + "interpTarget": 5, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "raiseHand04Outro", + "var": "reactionRaiseHandDisabled" + } + ] + }, + { + "id": "raiseHand04Outro", + "interpDuration": 1, + "interpTarget": 1, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "raiseHand04Loop", + "var": "reactionRaiseHandEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" }, "id": "raiseHand04", - "type": "clip" + "type": "randomSwitchStateMachine" } ], "data": { @@ -1980,42 +2619,288 @@ "children": [ { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 18, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_clap01_all.fbx" + }, + "id": "applaudClap01Intro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 97, + "loopFlag": true, + "startFrame": 18, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_clap01_all.fbx" + }, + "id": "applaudClap01Loop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 146, + "loopFlag": false, + "startFrame": 97, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_clap01_all.fbx" + }, + "id": "applaudClap01Outro", + "type": "clip" + } ], "data": { - "endFrame": 97, - "loopFlag": true, - "startFrame": 18, - "timeScale": 1, - "url": "qrc:///avatar/animations/emote_clap01_all.fbx" + "currentState": "applaudClap01Intro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "applaudClap01Intro", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "applaudClap01Loop", + "var": "applaudClap01IntroOnDone" + } + ] + }, + { + "id": "applaudClap01Loop", + "interpDuration": 5, + "interpTarget": 5, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "applaudClap01Outro", + "var": "reactionApplaudDisabled" + } + ] + }, + { + "id": "applaudClap01Outro", + "interpDuration": 5, + "interpTarget": 5, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "applaudClap01Loop", + "var": "reactionApplaudEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" }, "id": "applaudClap01", - "type": "clip" + "type": "randomSwitchStateMachine" }, { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 14, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_clap02_all.fbx" + }, + "id": "applaudClap02Intro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 78, + "loopFlag": true, + "startFrame": 14, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_clap02_all.fbx" + }, + "id": "applaudClap02Loop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 115, + "loopFlag": false, + "startFrame": 78, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_clap02_all.fbx" + }, + "id": "applaudClap02Outro", + "type": "clip" + } ], "data": { - "endFrame": 237, - "loopFlag": true, - "startFrame": 19, - "timeScale": 1, - "url": "qrc:///avatar/animations/emote_clap02_all.fbx" + "currentState": "applaudClap02Intro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "applaudClap02Intro", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "applaudClap02Loop", + "var": "applaudClap02IntroOnDone" + } + ] + }, + { + "id": "applaudClap02Loop", + "interpDuration": 5, + "interpTarget": 5, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "applaudClap02Outro", + "var": "reactionApplaudDisabled" + } + ] + }, + { + "id": "applaudClap02Outro", + "interpDuration": 5, + "interpTarget": 5, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "applaudClap02Loop", + "var": "reactionApplaudEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" }, "id": "applaudClap02", - "type": "clip" + "type": "randomSwitchStateMachine" }, { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 14, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_clap03_all.fbx" + }, + "id": "applaudClap03Intro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 100, + "loopFlag": true, + "startFrame": 14, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_clap03_all.fbx" + }, + "id": "applaudClap03Loop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 149, + "loopFlag": false, + "startFrame": 100, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_clap03_all.fbx" + }, + "id": "applaudClap03Outro", + "type": "clip" + } ], "data": { - "endFrame": 100, - "loopFlag": true, - "startFrame": 14, - "timeScale": 1, - "url": "qrc:///avatar/animations/emote_clap03_all.fbx" + "currentState": "applaudClap03Intro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "applaudClap03Intro", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "applaudClap03Loop", + "var": "applaudClap03IntroOnDone" + } + ] + }, + { + "id": "applaudClap03Loop", + "interpDuration": 5, + "interpTarget": 5, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "applaudClap03Outro", + "var": "reactionApplaudDisabled" + } + ] + }, + { + "id": "applaudClap03Outro", + "interpDuration": 5, + "interpTarget": 5, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "applaudClap03Loop", + "var": "reactionApplaudEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" }, "id": "applaudClap03", - "type": "clip" + "type": "randomSwitchStateMachine" } ], "data": { @@ -2057,16 +2942,97 @@ }, { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 22, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_point01_all.fbx" + }, + "id": "reactionPointIntro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 40, + "loopFlag": true, + "startFrame": 22, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_point01_all.fbx" + }, + "id": "reactionPointLoop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 78, + "loopFlag": false, + "startFrame": 40, + "timeScale": 1, + "url": "qrc:///avatar/animations/emote_point01_all.fbx" + }, + "id": "reactionPointOutro", + "type": "clip" + } ], "data": { - "endFrame": 44, - "loopFlag": true, - "startFrame": 22, - "timeScale": 1, - "url": "qrc:///avatar/animations/emote_point01_all.fbx" + "currentState": "reactionPointIntro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "reactionPointIntro", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "reactionPointLoop", + "var": "reactionPointIntroOnDone" + } + ] + }, + { + "id": "reactionPointLoop", + "interpDuration": 5, + "interpTarget": 5, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "reactionPointOutro", + "var": "reactionPointDisabled" + } + ] + }, + { + "id": "reactionPointOutro", + "interpDuration": 1, + "interpTarget": 1, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "reactionPointLoop", + "var": "reactionPointEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" }, "id": "reactionPoint", - "type": "clip" + "type": "randomSwitchStateMachine" } ], "data": { @@ -2075,9 +3041,9 @@ { "easingType": "easeInOutQuad", "id": "idleTalkOverlay", - "interpDuration": 18, - "interpTarget": 18, - "interpType": "snapshotPrev", + "interpDuration": 24, + "interpTarget": 24, + "interpType": "evaluateBoth", "transitions": [ { "state": "reactionPositive", diff --git a/interface/resources/qml/hifi/dialogs/TabletLODTools.qml b/interface/resources/qml/hifi/dialogs/TabletLODTools.qml index bb3d668850..ed0545e6ad 100644 --- a/interface/resources/qml/hifi/dialogs/TabletLODTools.qml +++ b/interface/resources/qml/hifi/dialogs/TabletLODTools.qml @@ -27,11 +27,15 @@ Rectangle { HifiConstants { id: hifi } - readonly property real treeScale: 32768; // ~20 miles.. This is the number of meters of the 0.0 to 1.0 voxel universe - readonly property real halfTreeScale: treeScale / 2; - - // This controls the LOD. Larger number will make smaller voxels visible at greater distance. - readonly property real defaultOctreeSizeScale: treeScale * 400.0 + // This controls the LOD. Larger number will make smaller objects visible at greater distance. + readonly property real defaultMaxVisibilityDistance: 400.0 + readonly property real unitElementMaxExtent: Math.sqrt(3.0) * 0.5 + + function visibilityDistanceToLODAngleDeg(visibilityDistance) { + var lodHalfAngle = Math.atan(unitElementMaxExtent / visibilityDistance); + var lodAngle = lodHalfAngle * 2.0; + return lodAngle * 180.0 / Math.PI; + } Column { anchors.margins: 10 @@ -71,7 +75,7 @@ Rectangle { id: adjustCheckbox boxSize: 20 anchors.verticalCenter: parent.verticalCenter - onCheckedChanged: LODManager.setAutomaticLODAdjust(!checked); + onCheckedChanged: LODManager.setAutomaticLODAdjust(!adjustCheckbox.checked); } } @@ -89,10 +93,10 @@ Rectangle { anchors.right: parent.right minimumValue: 5 maximumValue: 2000 - value: LODManager.getOctreeSizeScale() / treeScale + value: defaultMaxVisibilityDistance tickmarksEnabled: false onValueChanged: { - LODManager.setOctreeSizeScale(value * treeScale); + LODManager.lodAngleDeg = visibilityDistanceToLODAngleDeg(slider.value); whatYouCanSeeLabel.text = LODManager.getLODFeedbackText() } } @@ -106,7 +110,7 @@ Rectangle { colorScheme: root.colorScheme height: 30 onClicked: { - slider.value = defaultOctreeSizeScale/treeScale + slider.value = defaultMaxVisibilityDistance adjustCheckbox.checked = false LODManager.setAutomaticLODAdjust(adjustCheckbox.checked); } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8789fcde1c..062a8fa9c1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -292,7 +292,7 @@ static const uint32_t MAX_CONCURRENT_RESOURCE_DOWNLOADS = 4; // For processing on QThreadPool, we target a number of threads after reserving some // based on how many are being consumed by the application and the display plugin. However, // we will never drop below the 'min' value -static const int MIN_PROCESSING_THREAD_POOL_SIZE = 1; +static const int MIN_PROCESSING_THREAD_POOL_SIZE = 2; static const QString SNAPSHOT_EXTENSION = ".jpg"; static const QString JPG_EXTENSION = ".jpg"; @@ -4418,8 +4418,6 @@ void Application::keyPressEvent(QKeyEvent* event) { } else if (isMeta) { auto dialogsManager = DependencyManager::get(); dialogsManager->toggleAddressBar(); - } else if (isShifted) { - Menu::getInstance()->triggerOption(MenuOption::LodTools); } break; @@ -6817,8 +6815,8 @@ void Application::updateRenderArgs(float deltaTime) { _viewFrustum.setProjection(adjustedProjection); _viewFrustum.calculate(); } - appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getOctreeSizeScale(), - lodManager->getBoundaryLevelAdjust(), lodManager->getLODAngleHalfTan(), RenderArgs::DEFAULT_RENDER_MODE, + appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getVisibilityDistance(), + lodManager->getBoundaryLevelAdjust(), lodManager->getLODHalfAngleTan(), RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::DEFERRED, RenderArgs::RENDER_DEBUG_NONE); appRenderArgs._renderArgs._scene = getMain3DScene(); diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 0cf795e35b..3e47d88f3c 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -12,7 +12,6 @@ #include "LODManager.h" #include -#include #include #include @@ -93,8 +92,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { return; } - // Previous values for output - float oldOctreeSizeScale = getOctreeSizeScale(); + // Previous value for output float oldLODAngle = getLODAngleDeg(); // Target fps is slightly overshooted by 5hz @@ -165,7 +163,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { // And now add the output of the controller to the LODAngle where we will guarantee it is in the proper range setLODAngleDeg(oldLODAngle + output); - if (oldOctreeSizeScale != _octreeSizeScale) { + if (oldLODAngle != getLODAngleDeg()) { auto lodToolsDialog = DependencyManager::get()->getLodToolsDialog(); if (lodToolsDialog) { lodToolsDialog->reloadSliders(); @@ -173,21 +171,32 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { } } -float LODManager::getLODAngleHalfTan() const { - return getPerspectiveAccuracyAngleTan(_octreeSizeScale, _boundaryLevelAdjust); +float LODManager::getLODHalfAngleTan() const { + return tan(_lodHalfAngle); } float LODManager::getLODAngle() const { - return 2.0f * atanf(getLODAngleHalfTan()); + return 2.0f * _lodHalfAngle; } float LODManager::getLODAngleDeg() const { return glm::degrees(getLODAngle()); } +float LODManager::getVisibilityDistance() const { + float systemDistance = getVisibilityDistanceFromHalfAngle(_lodHalfAngle); + // Maintain behavior with deprecated _boundaryLevelAdjust property + return systemDistance * powf(2.0f, _boundaryLevelAdjust); +} + +void LODManager::setVisibilityDistance(float distance) { + // Maintain behavior with deprecated _boundaryLevelAdjust property + float userDistance = distance / powf(2.0f, _boundaryLevelAdjust); + _lodHalfAngle = getHalfAngleFromVisibilityDistance(userDistance); +} + void LODManager::setLODAngleDeg(float lodAngle) { - auto newSolidAngle = std::max(0.5f, std::min(lodAngle, 90.f)); - auto halTan = glm::tan(glm::radians(newSolidAngle * 0.5f)); - auto octreeSizeScale = TREE_SCALE * OCTREE_TO_MESH_RATIO / halTan; - setOctreeSizeScale(octreeSizeScale); + auto newLODAngleDeg = std::max(0.001f, std::min(lodAngle, 90.f)); + auto newLODHalfAngle = glm::radians(newLODAngleDeg * 0.5f); + _lodHalfAngle = newLODHalfAngle; } void LODManager::setSmoothScale(float t) { @@ -267,7 +276,11 @@ bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) { }; void LODManager::setOctreeSizeScale(float sizeScale) { - _octreeSizeScale = sizeScale; + setVisibilityDistance(sizeScale / TREE_SCALE); +} + +float LODManager::getOctreeSizeScale() const { + return getVisibilityDistance() * TREE_SCALE; } void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) { @@ -293,12 +306,14 @@ QString LODManager::getLODFeedbackText() { } break; } // distance feedback - float octreeSizeScale = getOctreeSizeScale(); - float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE; + float visibilityDistance = getVisibilityDistance(); + float relativeToDefault = visibilityDistance / DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT; int relativeToTwentyTwenty = 20 / relativeToDefault; QString result; - if (relativeToDefault > 1.01f) { + if (relativeToTwentyTwenty < 1) { + result = QString("%2 times further than average vision%3").arg(relativeToDefault, 0, 'f', 3).arg(granularityFeedback); + } else if (relativeToDefault > 1.01f) { result = QString("20:%1 or %2 times further than average vision%3").arg(relativeToTwentyTwenty).arg(relativeToDefault, 0, 'f', 2).arg(granularityFeedback); } else if (relativeToDefault > 0.99f) { result = QString("20:20 or the default distance for average vision%1").arg(granularityFeedback); diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 649e0e8e34..3dafa8c800 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -138,24 +139,28 @@ public: /**jsdoc * @function LODManager.setOctreeSizeScale * @param {number} sizeScale + * @deprecated This function is deprecated and will be removed. Use the {@link LODManager.lodAngleDeg} property instead. */ Q_INVOKABLE void setOctreeSizeScale(float sizeScale); /**jsdoc * @function LODManager.getOctreeSizeScale * @returns {number} + * @deprecated This function is deprecated and will be removed. Use the {@link LODManager.lodAngleDeg} property instead. */ - Q_INVOKABLE float getOctreeSizeScale() const { return _octreeSizeScale; } + Q_INVOKABLE float getOctreeSizeScale() const; /**jsdoc * @function LODManager.setBoundaryLevelAdjust * @param {number} boundaryLevelAdjust + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void setBoundaryLevelAdjust(int boundaryLevelAdjust); /**jsdoc * @function LODManager.getBoundaryLevelAdjust * @returns {number} + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; } @@ -196,8 +201,10 @@ public: float getLODAngleDeg() const; void setLODAngleDeg(float lodAngle); - float getLODAngleHalfTan() const; + float getLODHalfAngleTan() const; float getLODAngle() const; + float getVisibilityDistance() const; + void setVisibilityDistance(float distance); float getPidKp() const; float getPidKi() const; @@ -254,7 +261,7 @@ private: float _desktopTargetFPS { LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_DESKTOP_FPS }; float _hmdTargetFPS { LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_HMD_FPS }; - float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; + float _lodHalfAngle = getHalfAngleFromVisibilityDistance(DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT); int _boundaryLevelAdjust = 0; glm::vec4 _pidCoefs{ 1.0f, 0.0f, 0.0f, 1.0f }; // Kp, Ki, Kd, Kv diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index 284118a52a..53c8bd7c18 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -258,6 +258,7 @@ void GraphicsEngine::render_performFrame() { batch.setFramebuffer(finalFramebuffer); batch.enableSkybox(true); batch.enableStereo(isStereo); + batch.clearDepthStencilFramebuffer(1.0, 0); batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); _splashScreen->render(batch, viewFrustum, renderArgs._renderMethod == RenderArgs::RenderMethod::FORWARD); }); diff --git a/interface/src/ui/LodToolsDialog.cpp b/interface/src/ui/LodToolsDialog.cpp index e2f2d9e011..b25b9bc5a6 100644 --- a/interface/src/ui/LodToolsDialog.cpp +++ b/interface/src/ui/LodToolsDialog.cpp @@ -64,7 +64,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : _lodSize->setTickPosition(QSlider::TicksBelow); _lodSize->setFixedWidth(SLIDER_WIDTH); _lodSize->setPageStep(PAGE_STEP_LOD_SIZE); - int sliderValue = lodManager->getOctreeSizeScale() / TREE_SCALE; + int sliderValue = lodManager->getVisibilityDistance(); _lodSize->setValue(sliderValue); form->addRow("Level of Detail:", _lodSize); connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int))); @@ -81,7 +81,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : void LodToolsDialog::reloadSliders() { auto lodManager = DependencyManager::get(); - _lodSize->setValue(lodManager->getOctreeSizeScale() / TREE_SCALE); + _lodSize->setValue(lodManager->getVisibilityDistance()); _feedback->setText(lodManager->getLODFeedbackText()); } @@ -93,15 +93,14 @@ void LodToolsDialog::updateAutomaticLODAdjust() { void LodToolsDialog::sizeScaleValueChanged(int value) { auto lodManager = DependencyManager::get(); - float realValue = value * TREE_SCALE; - lodManager->setOctreeSizeScale(realValue); + lodManager->setVisibilityDistance(value); _feedback->setText(lodManager->getLODFeedbackText()); } void LodToolsDialog::resetClicked(bool checked) { - int sliderValue = DEFAULT_OCTREE_SIZE_SCALE / TREE_SCALE; + int sliderValue = DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT; _lodSize->setValue(sliderValue); _manualLODAdjust->setChecked(false); @@ -124,8 +123,8 @@ void LodToolsDialog::closeEvent(QCloseEvent* event) { lodManager->setAutomaticLODAdjust(true); // if the user adjusted the LOD above "normal" then always revert back to default - if (lodManager->getOctreeSizeScale() > DEFAULT_OCTREE_SIZE_SCALE) { - lodManager->setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE); + if (lodManager->getVisibilityDistance() > DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT) { + lodManager->setVisibilityDistance(DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT); } #endif } diff --git a/launchers/darwin/CMakeLists.txt b/launchers/darwin/CMakeLists.txt index fe7f4298ce..f71976960e 100644 --- a/launchers/darwin/CMakeLists.txt +++ b/launchers/darwin/CMakeLists.txt @@ -43,6 +43,8 @@ set(src_files src/LaunchInterface.h src/CustomUI.h src/CustomUI.m + src/NSTask+NSTaskExecveAdditions.h + src/NSTask+NSTaskExecveAdditions.m src/main.mm nib/Window.xib nib/SplashScreen.xib diff --git a/launchers/darwin/src/Launcher.m b/launchers/darwin/src/Launcher.m index 38027d6fd3..8fb501db55 100644 --- a/launchers/darwin/src/Launcher.m +++ b/launchers/darwin/src/Launcher.m @@ -7,6 +7,7 @@ #import "ProcessScreen.h" #import "ErrorViewController.h" #import "Settings.h" +#import "NSTask+NSTaskExecveAdditions.h" @interface Launcher () @@ -456,8 +457,6 @@ static BOOL const DELETE_ZIP_FILES = TRUE; NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; NSURL *url = [NSURL fileURLWithPath:[workspace fullPathForApplication:[[self getAppPath] stringByAppendingString:@"interface.app/Contents/MacOS/interface"]]]; - NSError *error = nil; - NSString* contentPath = [[self getDownloadPathForContentAndScripts] stringByAppendingString:@"content"]; NSString* displayName = [ self displayName]; NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUIBootstrapper.js"]; @@ -484,13 +483,11 @@ static BOOL const DELETE_ZIP_FILES = TRUE; @"--no-updater", @"--no-launcher", nil]; } - [workspace launchApplicationAtURL:url options:NSWorkspaceLaunchNewInstance configuration:[NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments] error:&error]; - [NSTimer scheduledTimerWithTimeInterval: 3.0 - target: self - selector: @selector(exitLauncher:) - userInfo:nil - repeats: NO]; + NSTask *task = [[NSTask alloc] init]; + task.launchPath = [url path]; + task.arguments = arguments; + [task replaceThisProcess]; } - (ProcessState) currentProccessState @@ -500,15 +497,20 @@ static BOOL const DELETE_ZIP_FILES = TRUE; - (void) callLaunchInterface:(NSTimer*) timer { + NSWindow* mainWindow = [[[NSApplication sharedApplication] windows] objectAtIndex:0]; + ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil]; - [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen]; - [self launchInterface]; -} - - -- (void) exitLauncher:(NSTimer*) timer -{ - [NSApp terminate:self]; + [mainWindow setContentViewController: processScreen]; + @try + { + [self launchInterface]; + } + @catch (NSException *exception) + { + NSLog(@"Caught exception: Name: %@, Reason: %@", exception.name, exception.reason); + ErrorViewController* errorViewController = [[ErrorViewController alloc] initWithNibName:@"ErrorScreen" bundle:nil]; + [mainWindow setContentViewController: errorViewController]; + } } @end diff --git a/launchers/darwin/src/NSTask+NSTaskExecveAdditions.h b/launchers/darwin/src/NSTask+NSTaskExecveAdditions.h new file mode 100644 index 0000000000..f26a4021de --- /dev/null +++ b/launchers/darwin/src/NSTask+NSTaskExecveAdditions.h @@ -0,0 +1,9 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSTask (NSTaskExecveAdditions) +- (void) replaceThisProcess; +@end + +NS_ASSUME_NONNULL_END diff --git a/launchers/darwin/src/NSTask+NSTaskExecveAdditions.m b/launchers/darwin/src/NSTask+NSTaskExecveAdditions.m new file mode 100644 index 0000000000..f204d065fa --- /dev/null +++ b/launchers/darwin/src/NSTask+NSTaskExecveAdditions.m @@ -0,0 +1,73 @@ +#import "NSTask+NSTaskExecveAdditions.h" + +#import + +char ** +toCArray(NSArray *array) +{ + // Add one to count to accommodate the NULL that terminates the array. + char **cArray = (char **) calloc([array count] + 1, sizeof(char *)); + if (cArray == NULL) { + NSException *exception = [NSException + exceptionWithName:@"MemoryException" + reason:@"malloc failed" + userInfo:nil]; + @throw exception; + } + char *str; + for (int i = 0; i < [array count]; i++) { + str = (char *) [array[i] UTF8String]; + if (str == NULL) { + NSException *exception = [NSException + exceptionWithName:@"NULLStringException" + reason:@"UTF8String was NULL" + userInfo:nil]; + @throw exception; + } + if (asprintf(&cArray[i], "%s", str) == -1) { + for (int j = 0; j < i; j++) { + free(cArray[j]); + } + free(cArray); + NSException *exception = [NSException + exceptionWithName:@"MemoryException" + reason:@"malloc failed" + userInfo:nil]; + @throw exception; + } + } + return cArray; +} + +@implementation NSTask (NSTaskExecveAdditions) + +- (void) replaceThisProcess { + char **args = toCArray([@[[self launchPath]] arrayByAddingObjectsFromArray:[self arguments]]); + + NSMutableArray *env = [[NSMutableArray alloc] init]; + NSDictionary* environvment = [[NSProcessInfo processInfo] environment]; + for (NSString* key in environvment) { + NSString* environmentVariable = [[key stringByAppendingString:@"="] stringByAppendingString:environvment[key]]; + [env addObject:environmentVariable]; + } + + char** envp = toCArray(env); + // `execve` replaces the current process with `path`. + // It will only return if it fails to replace the current process. + chdir(dirname(args[0])); + execve(args[0], (char * const *)args, envp); + + // If we're here `execve` failed. :( + for (int i = 0; i < [[self arguments] count]; i++) { + free((void *) args[i]); + } + free((void *) args); + + NSException *exception = [NSException + exceptionWithName:@"ExecveException" + reason:[NSString stringWithFormat:@"couldn't execve: %s", strerror(errno)] + userInfo:nil]; + @throw exception; +} + +@end diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 8d98f9c775..621323575f 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -213,6 +213,12 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std:: } } +float AnimInverseKinematics::getInterpolationAlpha(float timer) { + float alpha = (JOINT_CHAIN_INTERP_TIME - timer) / JOINT_CHAIN_INTERP_TIME; + alpha = 1.0f - powf(2.0f, -10.0f * alpha); + return alpha; +} + void AnimInverseKinematics::solve(const AnimContext& context, const std::vector& targets, float dt, JointChainInfoVec& jointChainInfoVec) { // compute absolute poses that correspond to relative target poses AnimPoseVec absolutePoses; @@ -227,6 +233,8 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector< accumulator.clearAndClean(); } + std::map targetToChainMap; + float maxError = 0.0f; int numLoops = 0; const int MAX_IK_LOOPS = 16; @@ -248,17 +256,13 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector< break; } } - + // on last iteration, interpolate jointChains, if necessary if (numLoops == MAX_IK_LOOPS) { for (size_t i = 0; i < _prevJointChainInfoVec.size(); i++) { + targetToChainMap.insert(std::pair(_prevJointChainInfoVec[i].target.getIndex(), (int)i)); if (_prevJointChainInfoVec[i].timer > 0.0f) { - - float alpha = (JOINT_CHAIN_INTERP_TIME - _prevJointChainInfoVec[i].timer) / JOINT_CHAIN_INTERP_TIME; - - // ease in expo - alpha = 1.0f - powf(2.0f, -10.0f * alpha); - + float alpha = getInterpolationAlpha(_prevJointChainInfoVec[i].timer); size_t chainSize = std::min(_prevJointChainInfoVec[i].jointInfoVec.size(), jointChainInfoVec[i].jointInfoVec.size()); if (jointChainInfoVec[i].target.getType() != IKTarget::Type::Unknown) { @@ -336,22 +340,47 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector< for (auto& target: targets) { int tipIndex = target.getIndex(); int parentIndex = (tipIndex >= 0) ? _skeleton->getParentIndex(tipIndex) : -1; - + int chainIndex = targetToChainMap[tipIndex]; + bool needsInterpolation = _prevJointChainInfoVec[chainIndex].timer > 0.0f; + float alpha = needsInterpolation ? getInterpolationAlpha(_prevJointChainInfoVec[chainIndex].timer) : 0.0f; // update rotationOnly targets that don't lie on the ik chain of other ik targets. - if (parentIndex != -1 && !_rotationAccumulators[tipIndex].isDirty() && target.getType() == IKTarget::Type::RotationOnly) { - const glm::quat& targetRotation = target.getRotation(); - // compute tip's new parent-relative rotation - // Q = Qp * q --> q' = Qp^ * Q - glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot()) * targetRotation; - RotationConstraint* constraint = getConstraint(tipIndex); - if (constraint) { - constraint->apply(newRelativeRotation); - // TODO: ATM the final rotation target just fails but we need to provide - // feedback to the IK system so that it can adjust the bones up the skeleton - // to help this rotation target get met. + if (parentIndex != -1 && !_rotationAccumulators[tipIndex].isDirty() && + (target.getType() == IKTarget::Type::RotationOnly || target.getType() == IKTarget::Type::Unknown)) { + if (target.getType() == IKTarget::Type::RotationOnly) { + const glm::quat& targetRotation = target.getRotation(); + // compute tip's new parent-relative rotation + // Q = Qp * q --> q' = Qp^ * Q + glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot()) * targetRotation; + RotationConstraint* constraint = getConstraint(tipIndex); + if (constraint) { + constraint->apply(newRelativeRotation); + // TODO: ATM the final rotation target just fails but we need to provide + // feedback to the IK system so that it can adjust the bones up the skeleton + // to help this rotation target get met. + } + if (needsInterpolation) { + _relativePoses[tipIndex].rot() = safeMix(_relativePoses[tipIndex].rot(), newRelativeRotation, alpha); + } else { + _relativePoses[tipIndex].rot() = newRelativeRotation; + } + // Add last known rotations to interpolate from + if (_rotationOnlyIKRotations.find(tipIndex) == _rotationOnlyIKRotations.end()) { + _rotationOnlyIKRotations.insert(std::pair(tipIndex, _relativePoses[tipIndex].rot())); + } else { + _rotationOnlyIKRotations[tipIndex] = _relativePoses[tipIndex].rot(); + } + absolutePoses[tipIndex].rot() = targetRotation; + } else { + bool rotationSnapshotExist = _rotationOnlyIKRotations.find(tipIndex) != _rotationOnlyIKRotations.end(); + if (needsInterpolation) { + if (rotationSnapshotExist) { + glm::quat lastKnownRotation = _rotationOnlyIKRotations[tipIndex]; + _relativePoses[tipIndex].rot() = safeMix(_relativePoses[tipIndex].rot(), lastKnownRotation, (1 - alpha)); + } + } else if (rotationSnapshotExist) { + _rotationOnlyIKRotations.erase(tipIndex); + } } - _relativePoses[tipIndex].rot() = newRelativeRotation; - absolutePoses[tipIndex].rot() = targetRotation; } } @@ -928,6 +957,10 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars (jointChainInfoVec[i].target.getType() != _prevJointChainInfoVec[i].target.getType() || jointChainInfoVec[i].target.getPoleVectorEnabled() != _prevJointChainInfoVec[i].target.getPoleVectorEnabled())) { _prevJointChainInfoVec[i].timer = JOINT_CHAIN_INTERP_TIME; + // Clear the rotations when the target is known + if (jointChainInfoVec[i].target.getType() != IKTarget::Type::Unknown) { + _rotationOnlyIKRotations.erase(jointChainInfoVec[i].target.getIndex()); + } } } } diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index 6d58ecedec..8d3f898e67 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -148,6 +148,7 @@ protected: void clearConstraints(); void initConstraints(); void initLimitCenterPoses(); + float getInterpolationAlpha(float timer); // no copies AnimInverseKinematics(const AnimInverseKinematics&) = delete; @@ -181,6 +182,7 @@ protected: AnimPoseVec _defaultRelativePoses; // poses of the relaxed state AnimPoseVec _relativePoses; // current relative poses AnimPoseVec _limitCenterPoses; // relative + std::map _rotationOnlyIKRotations; std::map _secondaryTargetsInRigFrame; diff --git a/libraries/animation/src/AnimRandomSwitch.cpp b/libraries/animation/src/AnimRandomSwitch.cpp index 3cf402cc14..68c7031de8 100644 --- a/libraries/animation/src/AnimRandomSwitch.cpp +++ b/libraries/animation/src/AnimRandomSwitch.cpp @@ -57,14 +57,12 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co lowerBound = upperBound; } if (abs(_randomSwitchEvaluationCount - context.getEvaluationCount()) > 1) { - _duringInterp = false; - switchRandomState(animVars, context, desiredState, _duringInterp); + switchRandomState(animVars, context, desiredState, false); } else { // firing a random switch, be sure that we aren't completing a previously triggered transition if (currentStateHasPriority) { if (desiredState->getID() != _currentState->getID()) { - _duringInterp = true; - switchRandomState(animVars, context, desiredState, _duringInterp); + switchRandomState(animVars, context, desiredState, true); } else { _duringInterp = false; } @@ -79,8 +77,7 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co // evaluate currentState transitions auto transitionState = evaluateTransitions(animVars); if (transitionState != _currentState) { - _duringInterp = true; - switchRandomState(animVars, context, transitionState, _duringInterp); + switchRandomState(animVars, context, transitionState, true); _triggerTime = randFloatInRange(_triggerTimeMin, _triggerTimeMax); _randomSwitchTime = randFloatInRange(_randomSwitchTimeMin, _randomSwitchTimeMax); } @@ -172,6 +169,9 @@ void AnimRandomSwitch::switchRandomState(const AnimVariantMap& animVars, const A _lastPlayedState = nextStateNode->getID(); if (shouldInterp) { + bool interpActive = _duringInterp; + _duringInterp = true; + const float FRAMES_PER_SECOND = 30.0f; auto prevStateNode = _children[_currentState->getChildIndex()]; @@ -195,13 +195,21 @@ void AnimRandomSwitch::switchRandomState(const AnimVariantMap& animVars, const A } _nextPoses = nextStateNode->evaluate(animVars, context, dt, triggers); } else if (_interpType == InterpType::SnapshotPrev) { - // snapshot previoius pose + // snapshot previous pose _prevPoses = _poses; // no need to evaluate _nextPoses we will do it dynamically during the interp, // however we need to set the current frame. if (!desiredState->getResume()) { nextStateNode->setCurrentFrame(desiredState->_interpTarget - duration); } + } else if (_interpType == InterpType::EvaluateBoth) { + // need to set current frame in destination branch. + nextStateNode->setCurrentFrame(desiredState->_interpTarget - duration); + if (interpActive) { + // snapshot previous pose + _prevPoses = _poses; + _interpType = InterpType::SnapshotPrev; + } } else { assert(false); } diff --git a/libraries/animation/src/AnimStateMachine.cpp b/libraries/animation/src/AnimStateMachine.cpp index b2d993abb8..658309ce71 100644 --- a/libraries/animation/src/AnimStateMachine.cpp +++ b/libraries/animation/src/AnimStateMachine.cpp @@ -128,6 +128,7 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, const AnimCon auto prevStateNode = _children[_currentState->getChildIndex()]; auto nextStateNode = _children[desiredState->getChildIndex()]; + bool interpActive = _duringInterp; _duringInterp = true; _alpha = 0.0f; float duration = std::max(0.001f, animVars.lookup(desiredState->_interpDurationVar, desiredState->_interpDuration)); @@ -146,11 +147,19 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, const AnimCon nextStateNode->setCurrentFrame(desiredState->_interpTarget); _nextPoses = nextStateNode->evaluate(animVars, context, dt, triggers); } else if (_interpType == InterpType::SnapshotPrev) { - // snapshot previoius pose + // snapshot previous pose _prevPoses = _poses; // no need to evaluate _nextPoses we will do it dynamically during the interp, // however we need to set the current frame. nextStateNode->setCurrentFrame(desiredState->_interpTarget - duration); + } else if (_interpType == InterpType::EvaluateBoth) { + // need to set current frame in destination branch. + nextStateNode->setCurrentFrame(desiredState->_interpTarget - duration); + if (interpActive) { + // snapshot previous pose + _prevPoses = _poses; + _interpType = InterpType::SnapshotPrev; + } } else { assert(false); } diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index f885f1113f..d0204219ac 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -2112,8 +2112,10 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo } float easeOutInValue = _talkIdleInterpTime < 0.5f ? 4.0f * powf(_talkIdleInterpTime, 3.0f) : 4.0f * powf((_talkIdleInterpTime - 1.0f), 3.0f) + 1.0f; _animVars.set("talkOverlayAlpha", easeOutInValue); + _animVars.set("idleOverlayAlpha", easeOutInValue); // backward compatibility for older anim graphs. } else { _animVars.set("talkOverlayAlpha", 1.0f); + _animVars.set("idleOverlayAlpha", 1.0f); // backward compatibility for older anim graphs. } } else { if (_talkIdleInterpTime < 1.0f) { @@ -2124,8 +2126,10 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo float easeOutInValue = _talkIdleInterpTime < 0.5f ? 4.0f * powf(_talkIdleInterpTime, 3.0f) : 4.0f * powf((_talkIdleInterpTime - 1.0f), 3.0f) + 1.0f; float talkAlpha = 1.0f - easeOutInValue; _animVars.set("talkOverlayAlpha", talkAlpha); + _animVars.set("idleOverlayAlpha", talkAlpha); // backward compatibility for older anim graphs. } else { _animVars.set("talkOverlayAlpha", 0.0f); + _animVars.set("idleOverlayAlpha", 0.0f); // backward compatibility for older anim graphs. } } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 5eebd92fba..a8d7847c09 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -78,7 +78,8 @@ public: void setVsyncEnabled(bool vsyncEnabled) { _vsyncEnabled = vsyncEnabled; } bool isVsyncEnabled() const { return _vsyncEnabled; } // Three threads, one for rendering, one for texture transfers, one reserved for the GL driver - int getRequiredThreadCount() const override { return 3; } + // Drop to one reserved for better other-task performance in desktop + int getRequiredThreadCount() const override { return 1; } virtual std::function getHUDOperator() override; void copyTextureToQuickFramebuffer(NetworkTexturePointer source, diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index 5317ec54da..36810681ad 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -53,6 +53,8 @@ public: void updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition, int visionSqueezePerEye, float visionSqueezeGroundPlaneY, float visionSqueezeSpotlightSize); + // Attempt to reserve two threads. + int getRequiredThreadCount() const override { return 2; } signals: void hmdMountedChanged(); diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.cpp index fef823718f..dd365efc16 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.cpp @@ -33,8 +33,8 @@ using namespace gpu::gl; #define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F #endif -bool GLTexelFormat::isCompressed() const { - switch (internalFormat) { +bool GLTexelFormat::isCompressed(GLenum format) { + switch (format) { case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: @@ -92,6 +92,11 @@ bool GLTexelFormat::isCompressed() const { } } +bool GLTexelFormat::isCompressed() const { + return isCompressed(internalFormat); +} + + GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { GLenum result = GL_RGBA8; switch (dstFormat.getDimension()) { diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.h b/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.h index 8f37f6b604..b5c805c5b8 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.h @@ -14,13 +14,15 @@ namespace gpu { namespace gl { class GLTexelFormat { public: - GLenum internalFormat; - GLenum format; - GLenum type; + GLenum internalFormat{ GL_RGBA8 }; + GLenum format{ GL_RGBA }; + GLenum type{ GL_UNSIGNED_BYTE }; GLTexelFormat(GLenum glinternalFormat, GLenum glformat, GLenum gltype) : internalFormat(glinternalFormat), format(glformat), type(gltype) {} GLTexelFormat(GLenum glinternalFormat) : internalFormat(glinternalFormat) {} + static bool isCompressed(GLenum glinternalFormat); + bool isCompressed() const; static GLTexelFormat evalGLTexelFormat(const Element& dstFormat) { diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h index c1ce074188..3e7392e366 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h @@ -33,6 +33,7 @@ class GL45Backend : public GLBackend { friend class Context; public: + static const GLint RESOURCE_TRANSFER_TEX_UNIT { 32 }; static GLint MAX_COMBINED_SHADER_STORAGE_BLOCKS; static GLint MAX_UNIFORM_LOCATIONS; #if GPU_BINDLESS_TEXTURES diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 81a6b100d0..bb31903d8e 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -226,81 +226,31 @@ void GL45Texture::generateMips() const { Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const { Size amountCopied = sourceSize; + bool compressed = GLTexelFormat::isCompressed(internalFormat); if (GL_TEXTURE_2D == _target) { - switch (internalFormat) { - case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - case GL_COMPRESSED_RED_RGTC1: - case GL_COMPRESSED_RG_RGTC2: - case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: - case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: - case GL_COMPRESSED_RGB8_ETC2: - case GL_COMPRESSED_SRGB8_ETC2: - case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: - case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: - case GL_COMPRESSED_RGBA8_ETC2_EAC: - case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: - case GL_COMPRESSED_R11_EAC: - case GL_COMPRESSED_SIGNED_R11_EAC: - case GL_COMPRESSED_RG11_EAC: - case GL_COMPRESSED_SIGNED_RG11_EAC: - glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, - static_cast(sourceSize), sourcePointer); - break; - default: - glTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); - break; + if (compressed) { + glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, + static_cast(sourceSize), sourcePointer); + } else { + glTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); } } else if (GL_TEXTURE_CUBE_MAP == _target) { - switch (internalFormat) { - case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - case GL_COMPRESSED_RED_RGTC1: - case GL_COMPRESSED_RG_RGTC2: - case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: - case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: - case GL_COMPRESSED_RGB8_ETC2: - case GL_COMPRESSED_SRGB8_ETC2: - case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: - case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: - case GL_COMPRESSED_RGBA8_ETC2_EAC: - case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: - case GL_COMPRESSED_R11_EAC: - case GL_COMPRESSED_SIGNED_R11_EAC: - case GL_COMPRESSED_RG11_EAC: - case GL_COMPRESSED_SIGNED_RG11_EAC: -#if AMD_CUBE_MAP_EXT_WORKAROUND - if (glCompressedTextureSubImage2DEXT) { - auto target = GLTexture::CUBE_FACE_LAYOUT[face]; - glCompressedTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, internalFormat, - static_cast(sourceSize), sourcePointer); - } else -#endif - { - glCompressedTextureSubImage3D(_id, mip, 0, yOffset, face, size.x, size.y, 1, internalFormat, - static_cast(sourceSize), sourcePointer); - } - break; - default: -#if AMD_CUBE_MAP_EXT_WORKAROUND - if (glTextureSubImage2DEXT) { - auto target = GLTexture::CUBE_FACE_LAYOUT[face]; - glTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); - } else -#endif - { - glTextureSubImage3D(_id, mip, 0, yOffset, face, size.x, size.y, 1, format, type, sourcePointer); - } - break; + // DSA and cubemap functions are notoriously buggy. use the 4.1 compatible pathway + glActiveTexture(GL_TEXTURE0 + GL45Backend::RESOURCE_TRANSFER_TEX_UNIT); + glBindTexture(_target, _texture); + auto target = GLTexture::CUBE_FACE_LAYOUT[face]; + if (compressed) { + glCompressedTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, internalFormat, + static_cast(sourceSize), sourcePointer); + } else { + glTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); } + glBindTexture(_target, 0); } else { assert(false); amountCopied = 0; } (void)CHECK_GL_ERROR(); - return amountCopied; } diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 4714160ace..c25075171b 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -334,12 +334,17 @@ void Socket::checkForReadyReadBackup() { qCDebug(networking) << "Socket::checkForReadyReadyBackup() last sequence number" << (uint32_t) _lastReceivedSequenceNumber << "from" << _lastPacketSockAddr << "-" << _lastPacketSizeRead << "bytes"; - +#ifdef DEBUG_EVENT_QUEUE + qCDebug(networking) << "NodeList event queue size:" << ::hifi::qt::getEventQueueSize(thread()); +#endif // drop all of the pending datagrams on the floor + int droppedCount = 0; while (_udpSocket.hasPendingDatagrams()) { _udpSocket.readDatagram(nullptr, 0); + ++droppedCount; } + qCDebug(networking) << "Flushed" << droppedCount << "Packets"; } } diff --git a/libraries/octree/src/OctreeConstants.h b/libraries/octree/src/OctreeConstants.h index 062d4e1ef2..de681402c4 100644 --- a/libraries/octree/src/OctreeConstants.h +++ b/libraries/octree/src/OctreeConstants.h @@ -21,8 +21,9 @@ const int TREE_SCALE = 32768; // ~20 miles.. This is the number of meters of the const int HALF_TREE_SCALE = TREE_SCALE / 2; // This controls the LOD. Larger number will make smaller voxels visible at greater distance. -const float MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT = 400.0f; // max distance where a 1x1x1 cube is visible for 20:20 vision -const float DEFAULT_OCTREE_SIZE_SCALE = TREE_SCALE * MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT; +const float DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT = 400.0f; // max distance where a 1x1x1 cube is visible for 20:20 vision +const float UNIT_ELEMENT_MAX_EXTENT = sqrtf(3.0f) / 2.0f; // A unit cube tilted on its edge will have its edge jutting out sqrt(3)/2 units from the center +const float DEFAULT_OCTREE_SIZE_SCALE = TREE_SCALE * DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT; // Since entities like models live inside of octree cells, and they themselves can have very small mesh parts, // we want to have some constant that controls have big a mesh part must be to render even if the octree cell itself diff --git a/libraries/octree/src/OctreeUtils.cpp b/libraries/octree/src/OctreeUtils.cpp index 7ed9c2ed3c..2aae73c566 100644 --- a/libraries/octree/src/OctreeUtils.cpp +++ b/libraries/octree/src/OctreeUtils.cpp @@ -18,64 +18,31 @@ #include #include -float calculateRenderAccuracy(const glm::vec3& position, - const AABox& bounds, - float octreeSizeScale, - int boundaryLevelAdjust) { - float largestDimension = bounds.getLargestDimension(); - - const float maxScale = (float)TREE_SCALE; - float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO; - - static std::once_flag once; - static QMap shouldRenderTable; - std::call_once(once, [&] { - float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small - float scale = maxScale; - float factor = 1.0f; - - while (scale > SMALLEST_SCALE_IN_TABLE) { - scale /= 2.0f; - factor /= 2.0f; - shouldRenderTable[scale] = factor; - } - }); - - float closestScale = maxScale; - float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale; - QMap::const_iterator lowerBound = shouldRenderTable.lowerBound(largestDimension); - if (lowerBound != shouldRenderTable.constEnd()) { - closestScale = lowerBound.key(); - visibleDistanceAtClosestScale = visibleDistanceAtMaxScale * lowerBound.value(); - } - - if (closestScale < largestDimension) { - visibleDistanceAtClosestScale *= 2.0f; - } - - // FIXME - for now, it's either visible or not visible. We want to adjust this to eventually return - // a floating point for objects that have small angular size to indicate that they may be rendered - // with lower preciscion - float distanceToCamera = glm::length(bounds.calcCenter() - position); - return (distanceToCamera <= visibleDistanceAtClosestScale) ? 1.0f : 0.0f; +float boundaryDistanceForRenderLevel(unsigned int renderLevel, float visibilityDistance) { + return visibilityDistance / powf(2.0f, renderLevel); } -float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) { - return voxelSizeScale / powf(2.0f, renderLevel); +float getPerspectiveAccuracyHalfAngleTan(float visibilityDistance, int boundaryLevelAdjust) { + float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, visibilityDistance); + return UNIT_ELEMENT_MAX_EXTENT / visibleDistanceAtMaxScale; } -float getPerspectiveAccuracyAngleTan(float octreeSizeScale, int boundaryLevelAdjust) { - const float maxScale = (float)TREE_SCALE; - float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO; - return (maxScale / visibleDistanceAtMaxScale); +float getPerspectiveAccuracyHalfAngle(float visibilityDistance, int boundaryLevelAdjust) { + return atan(getPerspectiveAccuracyHalfAngleTan(visibilityDistance, boundaryLevelAdjust)); } -float getPerspectiveAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) { - return atan(getPerspectiveAccuracyAngleTan(octreeSizeScale, boundaryLevelAdjust)); +float getVisibilityDistanceFromHalfAngle(float halfAngle) { + float halfAngleTan = tan(halfAngle); + return UNIT_ELEMENT_MAX_EXTENT / halfAngleTan; } -float getOrthographicAccuracySize(float octreeSizeScale, int boundaryLevelAdjust) { +float getHalfAngleFromVisibilityDistance(float visibilityDistance) { + float halfAngleTan = UNIT_ELEMENT_MAX_EXTENT / visibilityDistance; + return atan(halfAngleTan); +} + +float getOrthographicAccuracySize(float visibilityDistance, int boundaryLevelAdjust) { // Smallest visible element is 1cm const float smallestSize = 0.01f; - return (smallestSize * MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT) / boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale); + return (smallestSize * DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT) / boundaryDistanceForRenderLevel(boundaryLevelAdjust, visibilityDistance); } diff --git a/libraries/octree/src/OctreeUtils.h b/libraries/octree/src/OctreeUtils.h index eedbfe8bda..73d7e12a39 100644 --- a/libraries/octree/src/OctreeUtils.h +++ b/libraries/octree/src/OctreeUtils.h @@ -20,18 +20,13 @@ 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 -/// level it returns 0.0f for things that are so small for the current settings that they could not be visible. -float calculateRenderAccuracy(const glm::vec3& position, - const AABox& bounds, - float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE, - int boundaryLevelAdjust = 0); +float boundaryDistanceForRenderLevel(unsigned int renderLevel, float visibilityDistance); -float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale); - -float getPerspectiveAccuracyAngleTan(float octreeSizeScale, int boundaryLevelAdjust); -float getPerspectiveAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust); -float getOrthographicAccuracySize(float octreeSizeScale, int boundaryLevelAdjust); +float getPerspectiveAccuracyHalfAngleTan(float visibilityDistance, int boundaryLevelAdjust); +float getPerspectiveAccuracyHalfAngle(float visibilityDistance, int boundaryLevelAdjust); +float getVisibilityDistanceFromHalfAngle(float halfAngle); +float getHalfAngleFromVisibilityDistance(float visibilityDistance); +float getOrthographicAccuracySize(float visibilityDistance, int boundaryLevelAdjust); // MIN_ELEMENT_ANGULAR_DIAMETER = angular diameter of 1x1x1m cube at 400m = sqrt(3) / 400 = 0.0043301 radians ~= 0.25 degrees const float MIN_ELEMENT_ANGULAR_DIAMETER = 0.0043301f; // radians diff --git a/libraries/render/src/render/DrawSceneOctree.cpp b/libraries/render/src/render/DrawSceneOctree.cpp index b10c3fef8d..493ed01c3f 100644 --- a/libraries/render/src/render/DrawSceneOctree.cpp +++ b/libraries/render/src/render/DrawSceneOctree.cpp @@ -120,7 +120,7 @@ void DrawSceneOctree::run(const RenderContextPointer& renderContext, const ItemS // Draw the LOD Reticle { - float angle = glm::degrees(getPerspectiveAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust)); + float angle = glm::degrees(getPerspectiveAccuracyHalfAngle(args->_sizeScale, args->_boundaryLevelAdjust)); Transform crosshairModel; crosshairModel.setTranslation(glm::vec3(0.0, 0.0, -1000.0)); crosshairModel.setScale(1000.0f * tanf(glm::radians(angle))); // Scaling at the actual tan of the lod angle => Multiplied by TWO diff --git a/libraries/script-engine/src/XMLHttpRequestClass.cpp b/libraries/script-engine/src/XMLHttpRequestClass.cpp index a74d185c6a..571c0e2a0e 100644 --- a/libraries/script-engine/src/XMLHttpRequestClass.cpp +++ b/libraries/script-engine/src/XMLHttpRequestClass.cpp @@ -30,34 +30,18 @@ Q_DECLARE_METATYPE(QByteArray*) XMLHttpRequestClass::XMLHttpRequestClass(QScriptEngine* engine) : _engine(engine), - _async(true), - _url(), - _method(""), - _responseType(""), - _request(), - _reply(NULL), - _sendData(NULL), - _rawResponseData(), - _responseData(""), - _onTimeout(QScriptValue::NullValue), - _onReadyStateChange(QScriptValue::NullValue), - _readyState(XMLHttpRequestClass::UNSENT), - _errorCode(QNetworkReply::NoError), - _timeout(0), - _timer(this), - _numRedirects(0) { + _timer(this) { _request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); _timer.setSingleShot(true); } XMLHttpRequestClass::~XMLHttpRequestClass() { - if (_reply) { delete _reply; } - if (_sendData) { delete _sendData; } + if (_reply) { _reply->deleteLater(); } } QScriptValue XMLHttpRequestClass::constructor(QScriptContext* context, QScriptEngine* engine) { - return engine->newQObject(new XMLHttpRequestClass(engine)); + return engine->newQObject(new XMLHttpRequestClass(engine), QScriptEngine::ScriptOwnership); } QScriptValue XMLHttpRequestClass::getStatus() const { @@ -169,13 +153,12 @@ void XMLHttpRequestClass::send() { void XMLHttpRequestClass::send(const QScriptValue& data) { if (_readyState == OPENED && !_reply) { + if (!data.isNull()) { - _sendData = new QBuffer(this); if (data.isObject()) { - QByteArray ba = qscriptvalue_cast(data); - _sendData->setData(ba); + _sendData = qscriptvalue_cast(data); } else { - _sendData->setData(data.toString().toUtf8()); + _sendData = data.toString().toUtf8(); } } @@ -237,6 +220,10 @@ void XMLHttpRequestClass::requestFinished() { setReadyState(DONE); emit requestComplete(); + + disconnectFromReply(_reply); + _reply->deleteLater(); + _reply = nullptr; } void XMLHttpRequestClass::abortRequest() { @@ -246,7 +233,7 @@ void XMLHttpRequestClass::abortRequest() { disconnectFromReply(_reply); _reply->abort(); _reply->deleteLater(); - _reply = NULL; + _reply = nullptr; } } diff --git a/libraries/script-engine/src/XMLHttpRequestClass.h b/libraries/script-engine/src/XMLHttpRequestClass.h index c79859e895..d7f3c2e059 100644 --- a/libraries/script-engine/src/XMLHttpRequestClass.h +++ b/libraries/script-engine/src/XMLHttpRequestClass.h @@ -98,23 +98,23 @@ private: void disconnectFromReply(QNetworkReply* reply); void abortRequest(); - QScriptEngine* _engine; - bool _async; + QScriptEngine* _engine { nullptr }; + bool _async { true }; QUrl _url; QString _method; QString _responseType; QNetworkRequest _request; - QNetworkReply* _reply; - QBuffer* _sendData; + QNetworkReply* _reply { nullptr }; + QByteArray _sendData; QByteArray _rawResponseData; QScriptValue _responseData; - QScriptValue _onTimeout; - QScriptValue _onReadyStateChange; - ReadyState _readyState; - QNetworkReply::NetworkError _errorCode; - int _timeout; + QScriptValue _onTimeout { QScriptValue::NullValue }; + QScriptValue _onReadyStateChange { QScriptValue::NullValue }; + ReadyState _readyState { XMLHttpRequestClass::UNSENT }; + QNetworkReply::NetworkError _errorCode { QNetworkReply::NoError }; + int _timeout { 0 }; QTimer _timer; - int _numRedirects; + int _numRedirects { 0 }; private slots: void requestFinished(); diff --git a/libraries/shared/src/Profile.cpp b/libraries/shared/src/Profile.cpp index 1ad7b0785b..420b4ee54a 100644 --- a/libraries/shared/src/Profile.cpp +++ b/libraries/shared/src/Profile.cpp @@ -39,6 +39,10 @@ Q_LOGGING_CATEGORY(trace_baker, "trace.baker") #endif static bool tracingEnabled() { + if (!DependencyManager::isSet()) { + return false; + } + // Cheers, love! The cavalry's here! auto tracer = DependencyManager::get(); return (tracer && tracer->isEnabled()); diff --git a/libraries/shared/src/shared/QtHelpers.h b/libraries/shared/src/shared/QtHelpers.h index cde6ecdbb7..f57ba4af2d 100644 --- a/libraries/shared/src/shared/QtHelpers.h +++ b/libraries/shared/src/shared/QtHelpers.h @@ -12,10 +12,10 @@ #include -#ifdef WIN32 +#if defined(Q_OS_WIN) || defined(Q_OS_LINUX) // Enable event queue debugging #define DEBUG_EVENT_QUEUE -#endif // WIN32 +#endif namespace hifi { namespace qt { void addBlockingForbiddenThread(const QString& name, QThread* thread = nullptr); diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index 892b43d8be..6497fb967e 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -80,7 +80,7 @@ Item { valueVar: LODManager["lodAngleDeg"] valueVarSetter: (function (v) { LODManager["lodAngleDeg"] = v }) max: 90.0 - min: 0.5 + min: 0.01 integral: false anchors.left: parent.left @@ -239,6 +239,7 @@ Item { object: LODManager valueScale: 1.0 valueUnit: "deg" + valueNumDigits: 2 plots: [ { prop: "lodAngleDeg", diff --git a/scripts/modules/request.js b/scripts/modules/request.js index 37f3ac0d7b..48c9913bd6 100644 --- a/scripts/modules/request.js +++ b/scripts/modules/request.js @@ -39,6 +39,10 @@ module.exports = { if (error) { response = { statusCode: httpRequest.status }; } + + // Break circular reference to httpRequest so the engine can garbage collect it. + httpRequest.onreadystatechange = null; + callback(error, response, optionalCallbackParameter); } }; diff --git a/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml b/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml index 72cbe8c9be..aaec6cb9e8 100644 --- a/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml +++ b/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml @@ -17,7 +17,7 @@ import hifi.simplifiedUI.simplifiedConstants 1.0 as SimplifiedConstants Rectangle { id: root - color: simplifiedUI.colors.almostWhite + color: simplifiedUI.colors.white anchors.fill: parent property int originalWidth: 48 @@ -78,7 +78,7 @@ Rectangle { anchors.verticalCenterOffset: -2 horizontalAlignment: Text.AlignHCenter size: 26 - color: simplifiedUI.colors.text.almostWhite + color: simplifiedUI.colors.white } } @@ -91,7 +91,7 @@ Rectangle { Rectangle { id: drawerContainer z: 1 - color: simplifiedUI.colors.almostWhite + color: simplifiedUI.colors.white anchors.top: parent.top anchors.right: parent.right height: parent.height @@ -103,26 +103,28 @@ Rectangle { they probably be switched with Image {} to be supplied by Joshua. */ + ListModel { + id: buttonsModel + ListElement { text: "Z"; method: "happyPressed" } + ListElement { text: "C"; method: "sadPressed" } + ListElement { text: "V"; method: "raiseHandPressed" } + ListElement { text: "B"; method: "applaudPressed" } + ListElement { text: "N"; method: "pointPressed" } + ListElement { text: "😊"; method: "toggleEmojiApp" } + } + Repeater { id: emoteButtonsRepeater - model: ListModel { - id: buttonsModel - ListElement { text: "Z"; method: "happyPressed" } - ListElement { text: "C"; method: "sadPressed" } - ListElement { text: "V"; method: "raiseHandPressed" } - ListElement { text: "B"; method: "applaudPressed" } - ListElement { text: "N"; method: "pointPressed" } - ListElement { text: "😊"; method: "toggleEmojiApp" } - } + model: buttonsModel Rectangle { z: 3 width: root.originalWidth - height: parent.height - color: simplifiedUI.colors.darkBackground + height: drawerContainer.height + color: simplifiedUI.colors.white HifiStylesUit.GraphikRegular { - text: text + text: model.text z: 3 anchors.fill: parent anchors.rightMargin: 1 @@ -140,7 +142,7 @@ Rectangle { onClicked: { sendToScript({ "source": "EmoteAppBar.qml", - "method": method + "method": model.method }); } onEntered: { diff --git a/scripts/simplifiedUI/ui/simplifiedUI.js b/scripts/simplifiedUI/ui/simplifiedUI.js index 7adf932f9b..686fb7752a 100644 --- a/scripts/simplifiedUI/ui/simplifiedUI.js +++ b/scripts/simplifiedUI/ui/simplifiedUI.js @@ -476,7 +476,7 @@ function maybeUpdateOutputDeviceMutedOverlay() { var oldAutomaticLODAdjust; var oldLODAngleDeg; var SIMPLIFIED_UI_AUTO_LOD_ADJUST = false; -var SIMPLIFIED_UI_LOD_ANGLE_DEG = 0.5; +var SIMPLIFIED_UI_LOD_ANGLE_DEG = 0.248; function modifyLODSettings() { oldAutomaticLODAdjust = LODManager.automaticLODAdjust; oldLODAngleDeg = LODManager.lodAngleDeg; diff --git a/scripts/system/libraries/entityCameraTool.js b/scripts/system/libraries/entityCameraTool.js index 4410f19a5e..2968b8e903 100644 --- a/scripts/system/libraries/entityCameraTool.js +++ b/scripts/system/libraries/entityCameraTool.js @@ -355,7 +355,7 @@ CameraManager = function() { return; } - if (event.isRightButton || (event.isLeftButton && event.isControl && !event.isShifted)) { + if (event.isRightButton || (event.isLeftButton && event.isAlt && !event.isShifted)) { that.mode = MODE_ORBIT; } else if (event.isMiddleButton || (event.isLeftButton && event.isControl && event.isShifted)) { that.mode = MODE_PAN; diff --git a/tools/nitpick/CMakeLists.txt b/tools/nitpick/CMakeLists.txt index 6076f80c16..ee534ca24f 100644 --- a/tools/nitpick/CMakeLists.txt +++ b/tools/nitpick/CMakeLists.txt @@ -30,6 +30,8 @@ source_group("UI Files" FILES ${QT_UI_FILES}) # have qt5 wrap them and generate the appropriate header files qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}") +setup_memory_debugger() + # add them to the nitpick source files set(NITPICK_SRCS ${NITPICK_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}") diff --git a/tools/oven/src/OvenCLIApplication.cpp b/tools/oven/src/OvenCLIApplication.cpp index eab8647e71..afcdfbfcd2 100644 --- a/tools/oven/src/OvenCLIApplication.cpp +++ b/tools/oven/src/OvenCLIApplication.cpp @@ -24,12 +24,23 @@ static const QString CLI_OUTPUT_PARAMETER = "o"; static const QString CLI_TYPE_PARAMETER = "t"; static const QString CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER = "disable-texture-compression"; +QUrl OvenCLIApplication::_inputUrlParameter; +QUrl OvenCLIApplication::_outputUrlParameter; +QString OvenCLIApplication::_typeParameter; + OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) : QCoreApplication(argc, argv) { + BakerCLI* cli = new BakerCLI(this); + QMetaObject::invokeMethod(cli, "bakeFile", Qt::QueuedConnection, Q_ARG(QUrl, _inputUrlParameter), + Q_ARG(QString, _outputUrlParameter.toString()), Q_ARG(QString, _typeParameter)); +} + +void OvenCLIApplication::parseCommandLine(int argc, char* argv[]) { // parse the command line parameters QCommandLineParser parser; + parser.setApplicationDescription("High Fidelity Oven"); parser.addOptions({ { CLI_INPUT_PARAMETER, "Path to file that you would like to bake.", "input" }, { CLI_OUTPUT_PARAMETER, "Path to folder that will be used as output.", "output" }, @@ -37,25 +48,45 @@ OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) : { CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER, "Disable texture compression." } }); - parser.addHelpOption(); - parser.process(*this); + auto versionOption = parser.addVersionOption(); + auto helpOption = parser.addHelpOption(); - if (parser.isSet(CLI_INPUT_PARAMETER) && parser.isSet(CLI_OUTPUT_PARAMETER)) { - BakerCLI* cli = new BakerCLI(this); - QUrl inputUrl(QDir::fromNativeSeparators(parser.value(CLI_INPUT_PARAMETER))); - QUrl outputUrl(QDir::fromNativeSeparators(parser.value(CLI_OUTPUT_PARAMETER))); - QString type = parser.isSet(CLI_TYPE_PARAMETER) ? parser.value(CLI_TYPE_PARAMETER) : QString::null; - - if (parser.isSet(CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER)) { - qDebug() << "Disabling texture compression"; - TextureBaker::setCompressionEnabled(false); - } - - QMetaObject::invokeMethod(cli, "bakeFile", Qt::QueuedConnection, Q_ARG(QUrl, inputUrl), - Q_ARG(QString, outputUrl.toString()), Q_ARG(QString, type)); - } else { - parser.showHelp(); - QCoreApplication::quit(); + QStringList arguments; + for (int i = 0; i < argc; ++i) { + arguments << argv[i]; } + if (!parser.parse(arguments)) { + std::cout << parser.errorText().toStdString() << std::endl; // Avoid Qt log spam + QCoreApplication mockApp(argc, argv); // required for call to showHelp() + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (parser.isSet(versionOption)) { + parser.showVersion(); + Q_UNREACHABLE(); + } + if (parser.isSet(helpOption)) { + QCoreApplication mockApp(argc, argv); // required for call to showHelp() + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (!parser.isSet(CLI_INPUT_PARAMETER) || !parser.isSet(CLI_OUTPUT_PARAMETER)) { + std::cout << "Error: Input and Output not set" << std::endl; // Avoid Qt log spam + QCoreApplication mockApp(argc, argv); // required for call to showHelp() + parser.showHelp(); + Q_UNREACHABLE(); + } + + _inputUrlParameter = QDir::fromNativeSeparators(parser.value(CLI_INPUT_PARAMETER)); + _outputUrlParameter = QDir::fromNativeSeparators(parser.value(CLI_OUTPUT_PARAMETER)); + + _typeParameter = parser.isSet(CLI_TYPE_PARAMETER) ? parser.value(CLI_TYPE_PARAMETER) : QString::null; + + if (parser.isSet(CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER)) { + qDebug() << "Disabling texture compression"; + TextureBaker::setCompressionEnabled(false); + } } diff --git a/tools/oven/src/OvenCLIApplication.h b/tools/oven/src/OvenCLIApplication.h index 5d81166f69..21fc9e9ba1 100644 --- a/tools/oven/src/OvenCLIApplication.h +++ b/tools/oven/src/OvenCLIApplication.h @@ -21,7 +21,14 @@ class OvenCLIApplication : public QCoreApplication, public Oven { public: OvenCLIApplication(int argc, char* argv[]); + static void parseCommandLine(int argc, char* argv[]); + static OvenCLIApplication* instance() { return dynamic_cast(QCoreApplication::instance()); } + +private: + static QUrl _inputUrlParameter; + static QUrl _outputUrlParameter; + static QString _typeParameter; }; #endif // hifi_OvenCLIApplication_h diff --git a/tools/oven/src/main.cpp b/tools/oven/src/main.cpp index 7009089402..586dae06a5 100644 --- a/tools/oven/src/main.cpp +++ b/tools/oven/src/main.cpp @@ -18,14 +18,19 @@ int main (int argc, char** argv) { setupHifiApplication("Oven"); - // init the settings interface so we can save and load settings - Setting::init(); - // figure out if we're launching our GUI application or just the simple command line interface if (argc > 1) { + OvenCLIApplication::parseCommandLine(argc, argv); + + // init the settings interface so we can save and load settings + Setting::init(); + OvenCLIApplication app { argc, argv }; return app.exec(); } else { + // init the settings interface so we can save and load settings + Setting::init(); + OvenGUIApplication app { argc, argv }; return app.exec(); }