diff --git a/cmake/externals/LibOVR/CMakeLists.txt b/cmake/externals/LibOVR/CMakeLists.txt
index a98745b404..5b8a689a9a 100644
--- a/cmake/externals/LibOVR/CMakeLists.txt
+++ b/cmake/externals/LibOVR/CMakeLists.txt
@@ -12,19 +12,16 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
# 0.5 public
# URL http://static.oculus.com/sdk-downloads/ovr_sdk_win_0.5.0.1.zip
# URL_MD5 d3fc4c02db9be5ff08af4ef4c97b32f9
-# 0.6 public
-# URL http://static.oculus.com/sdk-downloads/0.6.0.1/Public/1435190862/ovr_sdk_win_0.6.0.1.zip
-# URL_MD5 4b3ef825f9a1d6d3035c9f6820687da9
-# 0.8 public
-# URL http://static.oculus.com/sdk-downloads/0.8.0.0/Public/1445451746/ovr_sdk_win_0.8.0.0.zip
-# URL_MD5 54944b03b95149d6010f84eb701b9647
+# 1.3 public
+# URL http://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.3.0_public.zip
+# URL_MD5 4d26faba0c1f35ff80bf674c96ed9259
if (WIN32)
ExternalProject_Add(
${EXTERNAL_NAME}
- URL http://static.oculus.com/sdk-downloads/0.8.0.0/Public/1445451746/ovr_sdk_win_0.8.0.0.zip
- URL_MD5 54944b03b95149d6010f84eb701b9647
+ URL http://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.3.0_public.zip
+ URL_MD5 a2dcf695e0f03a70fdd1ed7480585e82
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
@@ -33,14 +30,16 @@ if (WIN32)
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
- # FIXME need to account for different architectures
- set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/LibOVR/Include CACHE TYPE INTERNAL)
+ set(LIBOVR_DIR ${SOURCE_DIR}/OculusSDK/LibOVR)
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
- set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/LibOVR/Lib/Windows/x64/Release/VS2013/LibOVR.lib CACHE TYPE INTERNAL)
+ set(LIBOVR_LIB_DIR ${LIBOVR_DIR}/Lib/Windows/x64/Release/VS2013 CACHE TYPE INTERNAL)
else()
- set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/LibOVR/Lib/Windows/Win32/Release/VS2013/LibOVR.lib CACHE TYPE INTERNAL)
+ set(LIBOVR_LIB_DIR ${LIBOVR_DIR}/Lib/Windows/Win32/Release/VS2013 CACHE TYPE INTERNAL)
endif()
+ set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${LIBOVR_DIR}/Include CACHE TYPE INTERNAL)
+ set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${LIBOVR_LIB_DIR}/LibOVR.lib CACHE TYPE INTERNAL)
+
elseif(APPLE)
ExternalProject_Add(
diff --git a/cmake/macros/GenerateInstallers.cmake b/cmake/macros/GenerateInstallers.cmake
index b4744aa172..8d1eca84d7 100644
--- a/cmake/macros/GenerateInstallers.cmake
+++ b/cmake/macros/GenerateInstallers.cmake
@@ -85,8 +85,8 @@ macro(GENERATE_INSTALLERS)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
- cpack_add_component(${CLIENT_COMPONENT} DISPLAY_NAME "High Fidelity Client")
- cpack_add_component(${SERVER_COMPONENT} DISPLAY_NAME "High Fidelity Server")
+ cpack_add_component(${CLIENT_COMPONENT} DISPLAY_NAME "High Fidelity Interface")
+ cpack_add_component(${SERVER_COMPONENT} DISPLAY_NAME "High Fidelity Sandbox")
include(CPack)
endmacro()
diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake
index 92e3273f67..63e7a1a174 100644
--- a/cmake/macros/SetPackagingParameters.cmake
+++ b/cmake/macros/SetPackagingParameters.cmake
@@ -53,7 +53,7 @@ macro(SET_PACKAGING_PARAMETERS)
set(CONSOLE_INSTALL_DIR ${DMG_SUBFOLDER_NAME})
set(INTERFACE_INSTALL_DIR ${DMG_SUBFOLDER_NAME})
- set(CONSOLE_EXEC_NAME "Server Console.app")
+ set(CONSOLE_EXEC_NAME "Sandbox.app")
set(CONSOLE_INSTALL_APP_PATH "${CONSOLE_INSTALL_DIR}/${CONSOLE_EXEC_NAME}")
set(CONSOLE_APP_CONTENTS "${CONSOLE_INSTALL_APP_PATH}/Contents")
@@ -84,12 +84,19 @@ macro(SET_PACKAGING_PARAMETERS)
# shortcut names
if (PRODUCTION_BUILD)
- set(INTERFACE_SHORTCUT_NAME "High Fidelity")
- set(CONSOLE_SHORTCUT_NAME "Server Console")
+ set(INTERFACE_SHORTCUT_NAME "Interface")
+ set(CONSOLE_SHORTCUT_NAME "Sandbox")
else ()
- set(INTERFACE_SHORTCUT_NAME "High Fidelity - ${BUILD_VERSION}")
- set(CONSOLE_SHORTCUT_NAME "Server Console - ${BUILD_VERSION}")
+ set(INTERFACE_SHORTCUT_NAME "Interface - ${BUILD_VERSION}")
+ set(CONSOLE_SHORTCUT_NAME "Sandbox - ${BUILD_VERSION}")
endif ()
+
+ set(INTERFACE_HF_SHORTCUT_NAME "High Fidelity ${INTERFACE_SHORTCUT_NAME}")
+ set(CONSOLE_HF_SHORTCUT_NAME "High Fidelity ${CONSOLE_SHORTCUT_NAME}")
+
+ set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "High Fidelity")
+ set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "Server Console")
+
# check if we need to find signtool
if (PRODUCTION_BUILD OR PR_BUILD)
find_program(SIGNTOOL_EXECUTABLE signtool PATHS "C:/Program Files (x86)/Windows Kits/8.1" PATH_SUFFIXES "bin/x64")
diff --git a/cmake/templates/CPackProperties.cmake.in b/cmake/templates/CPackProperties.cmake.in
index 164e432706..d22ba1f5e1 100644
--- a/cmake/templates/CPackProperties.cmake.in
+++ b/cmake/templates/CPackProperties.cmake.in
@@ -10,10 +10,14 @@
#
set(INTERFACE_SHORTCUT_NAME "@INTERFACE_SHORTCUT_NAME@")
+set(INTERFACE_HF_SHORTCUT_NAME "@INTERFACE_HF_SHORTCUT_NAME@")
set(INTERFACE_WIN_EXEC_NAME "@INTERFACE_EXEC_PREFIX@.exe")
set(CONSOLE_INSTALL_SUBDIR "@CONSOLE_INSTALL_DIR@")
set(CONSOLE_SHORTCUT_NAME "@CONSOLE_SHORTCUT_NAME@")
+set(CONSOLE_HF_SHORTCUT_NAME "@CONSOLE_HF_SHORTCUT_NAME@")
set(CONSOLE_WIN_EXEC_NAME "@CONSOLE_EXEC_NAME@")
+set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@")
+set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@")
set(DS_EXEC_NAME "@DS_EXEC_NAME@")
set(AC_EXEC_NAME "@AC_EXEC_NAME@")
set(HIGH_FIDELITY_PROTOCOL "@HIGH_FIDELITY_PROTOCOL@")
diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in
index ca26be6ab0..0e30d8aa2a 100644
--- a/cmake/templates/NSIS.template.in
+++ b/cmake/templates/NSIS.template.in
@@ -387,7 +387,7 @@ Function PostInstallOptionsPage
StrCpy $OffsetUnits u
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
- ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @INTERFACE_SHORTCUT_NAME@"
+ ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @INTERFACE_HF_SHORTCUT_NAME@"
Pop $DesktopClientCheckbox
IntOp $CurrentOffset $CurrentOffset + 15
@@ -396,7 +396,7 @@ Function PostInstallOptionsPage
${EndIf}
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
- ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for High Fidelity @CONSOLE_SHORTCUT_NAME@"
+ ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @CONSOLE_HF_SHORTCUT_NAME@"
Pop $DesktopServerCheckbox
; set the checkbox state depending on what is present in the registry
@@ -404,7 +404,7 @@ Function PostInstallOptionsPage
IntOp $CurrentOffset $CurrentOffset + 15
- ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch High Fidelity @CONSOLE_SHORTCUT_NAME@ on startup"
+ ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup"
Pop $ServerStartupCheckbox
; set the checkbox state depending on what is present in the registry
@@ -414,9 +414,9 @@ Function PostInstallOptionsPage
${EndIf}
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
- ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch High Fidelity Server Console after install"
+ ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install"
${Else}
- ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch High Fidelity after install"
+ ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @INTERFACE_HF_SHORTCUT_NAME@ after install"
${EndIf}
Pop $LaunchNowCheckbox
@@ -465,10 +465,10 @@ Function ReadPostInstallOptions
${EndIf}
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
- ; check if the user asked for a desktop shortcut to Server Console
+ ; check if the user asked for a desktop shortcut to Sandbox
${NSD_GetState} $DesktopServerCheckbox $DesktopServerState
- ; check if the user asked to have Server Console launched every startup
+ ; check if the user asked to have Sandbox launched every startup
${NSD_GetState} $ServerStartupCheckbox $ServerStartupState
${EndIf}
@@ -485,7 +485,7 @@ Function HandlePostInstallOptions
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
; check if the user asked for a desktop shortcut to High Fidelity
${If} $DesktopClientState == ${BST_CHECKED}
- CreateShortCut "$DESKTOP\@INTERFACE_SHORTCUT_NAME@.lnk" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
+ CreateShortCut "$DESKTOP\@INTERFACE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
!insertmacro WritePostInstallOption "@CLIENT_DESKTOP_SHORTCUT_REG_KEY@" YES
${Else}
!insertmacro WritePostInstallOption @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ NO
@@ -494,23 +494,23 @@ Function HandlePostInstallOptions
${EndIf}
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
- ; check if the user asked for a desktop shortcut to Server Console
+ ; check if the user asked for a desktop shortcut to Sandbox
${If} $DesktopServerState == ${BST_CHECKED}
- CreateShortCut "$DESKTOP\@CONSOLE_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
+ CreateShortCut "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
!insertmacro WritePostInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES
${Else}
!insertmacro WritePostInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO
${EndIf}
- ; check if the user asked to have Server Console launched every startup
+ ; check if the user asked to have Sandbox launched every startup
${If} $ServerStartupState == ${BST_CHECKED}
; in case we added a shortcut in the global context, pull that now
SetShellVarContext all
- Delete "$SMSTARTUP\@CONSOLE_SHORTCUT_NAME@.lnk"
+ Delete "$SMSTARTUP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
; make a startup shortcut in this user's current context
SetShellVarContext current
- CreateShortCut "$SMSTARTUP\@CONSOLE_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
+ CreateShortCut "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
; reset the shell var context back
SetShellVarContext all
@@ -589,6 +589,19 @@ Section "-Core installation"
Delete "$INSTDIR\version"
Delete "$INSTDIR\xinput1_3.dll"
+ ; Delete old desktop shortcuts before they were renamed during Sandbox rename
+ Delete "$DESKTOP\@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@.lnk"
+ Delete "$DESKTOP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
+
+ ; Delete old Start Menu shortcuts before Sandbox rename
+ Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@.lnk"
+ Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
+
+ ; Delete old startup item for Server Console before Sandbox rename
+ SetShellVarContext current
+ Delete "$SMSTARTUP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
+ SetShellVarContext all
+
; Rename the incorrectly cased Raleway font
Rename "$INSTDIR\resources\qml\styles-uit\RalewaySemibold.qml" "$INSTDIR\resources\qml\styles-uit\RalewaySemiBold.qml"
@@ -724,8 +737,8 @@ SectionEnd
!macroend
!macro CheckForRunningApplications action prompter
- !insertmacro PromptForRunningApplication "@INTERFACE_WIN_EXEC_NAME@" "High Fidelity client" ${action} ${prompter}
- !insertmacro PromptForRunningApplication "@CONSOLE_WIN_EXEC_NAME@" "Server Console" ${action} ${prompter}
+ !insertmacro PromptForRunningApplication "@INTERFACE_WIN_EXEC_NAME@" "@CONSOLE_SHORTCUT_NAME@" ${action} ${prompter}
+ !insertmacro PromptForRunningApplication "@CONSOLE_WIN_EXEC_NAME@" "@INTERFACE_SHORTCUT_NAME@" ${action} ${prompter}
!insertmacro PromptForRunningApplication "@DS_EXEC_NAME@" "Domain Server" ${action} ${prompter}
!insertmacro PromptForRunningApplication "@AC_EXEC_NAME@" "Assignment Client" ${action} ${prompter}
!macroend
@@ -869,12 +882,12 @@ Section "Uninstall"
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk"
Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_SHORTCUT_NAME@.lnk"
- Delete "$DESKTOP\@INTERFACE_SHORTCUT_NAME@.lnk"
- Delete "$DESKTOP\@CONSOLE_SHORTCUT_NAME@.lnk"
+ Delete "$DESKTOP\@INTERFACE_HF_SHORTCUT_NAME@.lnk"
+ Delete "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk"
; if it exists, delete the startup shortcut for the current user
SetShellVarContext current
- Delete "$SMSTARTUP\@CONSOLE_SHORTCUT_NAME@.lnk"
+ Delete "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk"
SetShellVarContext all
@CPACK_NSIS_DELETE_ICONS@
diff --git a/examples/utilities/tools/render/BG.qml b/examples/utilities/render/BG.qml
similarity index 100%
rename from examples/utilities/tools/render/BG.qml
rename to examples/utilities/render/BG.qml
diff --git a/examples/utilities/tools/render/ConfigSlider.qml b/examples/utilities/render/configSlider/ConfigSlider.qml
similarity index 100%
rename from examples/utilities/tools/render/ConfigSlider.qml
rename to examples/utilities/render/configSlider/ConfigSlider.qml
diff --git a/examples/utilities/render/configSlider/qmldir b/examples/utilities/render/configSlider/qmldir
new file mode 100644
index 0000000000..6680ec9638
--- /dev/null
+++ b/examples/utilities/render/configSlider/qmldir
@@ -0,0 +1 @@
+ConfigSlider 1.0 ConfigSlider.qml
\ No newline at end of file
diff --git a/examples/utilities/render/culling.qml b/examples/utilities/render/culling.qml
new file mode 100644
index 0000000000..e3f5e67bbe
--- /dev/null
+++ b/examples/utilities/render/culling.qml
@@ -0,0 +1,114 @@
+//
+// culling.qml
+// examples/utilities/render
+//
+// Copyright 2016 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
+//
+import QtQuick 2.5
+import QtQuick.Controls 1.4
+import "configSlider"
+
+Column {
+ id: root
+ spacing: 8
+ property var sceneOctree: Render.getConfig("DrawSceneOctree");
+ property var itemSelection: Render.getConfig("DrawItemSelection");
+
+ Component.onCompleted: {
+ sceneOctree.enabled = true;
+ itemSelection.enabled = true;
+ sceneOctree.showVisibleCells = false;
+ sceneOctree.showEmptyCells = false;
+ itemSelection.showInsideItems = false;
+ itemSelection.showInsideSubcellItems = false;
+ itemSelection.showPartialItems = false;
+ itemSelection.showPartialSubcellItems = false;
+ }
+ Component.onDestruction: {
+ sceneOctree.enabled = false;
+ itemSelection.enabled = false;
+ Render.getConfig("FetchSceneSelection").freezeFrustum = false;
+ Render.getConfig("CullSceneSelection").freezeFrustum = false;
+ }
+
+ GroupBox {
+ title: "Culling"
+ Row {
+ spacing: 8
+ Column {
+ spacing: 8
+
+ CheckBox {
+ text: "Freeze Culling Frustum"
+ checked: false
+ onCheckedChanged: {
+ Render.getConfig("FetchSceneSelection").freezeFrustum = checked;
+ Render.getConfig("CullSceneSelection").freezeFrustum = checked;
+ }
+ }
+ Label {
+ text: "Octree"
+ }
+ CheckBox {
+ text: "Visible Cells"
+ checked: root.sceneOctree.showVisibleCells
+ onCheckedChanged: { root.sceneOctree.showVisibleCells = checked }
+ }
+ CheckBox {
+ text: "Empty Cells"
+ checked: false
+ onCheckedChanged: { root.sceneOctree.showEmptyCells = checked }
+ }
+ }
+ Column {
+ spacing: 8
+
+ Label {
+ text: "Frustum Items"
+ }
+ CheckBox {
+ text: "Inside Items"
+ checked: false
+ onCheckedChanged: { root.itemSelection.showInsideItems = checked }
+ }
+ CheckBox {
+ text: "Inside Sub-cell Items"
+ checked: false
+ onCheckedChanged: { root.itemSelection.showInsideSubcellItems = checked }
+ }
+ CheckBox {
+ text: "Partial Items"
+ checked: false
+ onCheckedChanged: { root.itemSelection.showPartialItems = checked }
+ }
+ CheckBox {
+ text: "Partial Sub-cell Items"
+ checked: false
+ onCheckedChanged: { root.itemSelection.showPartialSubcellItems = checked }
+ }
+ }
+ }
+ }
+
+ GroupBox {
+ title: "Render Items"
+
+ Column{
+ Repeater {
+ model: [ "Opaque:DrawOpaqueDeferred", "Transparent:DrawTransparentDeferred", "Light:DrawLight",
+ "Opaque Overlays:DrawOverlay3DOpaque", "Transparent Overlays:DrawOverlay3DTransparent" ]
+ ConfigSlider {
+ label: qsTr(modelData.split(":")[0])
+ integral: true
+ config: Render.getConfig(modelData.split(":")[1])
+ property: "maxDrawn"
+ max: config.numDrawn
+ min: -1
+ }
+ }
+ }
+ }
+}
diff --git a/examples/utilities/tools/render/debug.js b/examples/utilities/render/debug.js
similarity index 100%
rename from examples/utilities/tools/render/debug.js
rename to examples/utilities/render/debug.js
diff --git a/examples/utilities/tools/render/debugBG.js b/examples/utilities/render/debugBG.js
similarity index 100%
rename from examples/utilities/tools/render/debugBG.js
rename to examples/utilities/render/debugBG.js
diff --git a/examples/utilities/tools/render/debugFramebuffer.js b/examples/utilities/render/debugFramebuffer.js
similarity index 100%
rename from examples/utilities/tools/render/debugFramebuffer.js
rename to examples/utilities/render/debugFramebuffer.js
diff --git a/examples/utilities/render/debugRender.js b/examples/utilities/render/debugRender.js
new file mode 100644
index 0000000000..788c7cb4a0
--- /dev/null
+++ b/examples/utilities/render/debugRender.js
@@ -0,0 +1,21 @@
+//
+// debugRender.js
+// examples/utilities/render
+//
+// Sam Gateau, created on 3/22/2016.
+// Copyright 2016 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+// Set up the qml ui
+var qml = Script.resolvePath('culling.qml');
+var window = new OverlayWindow({
+ title: 'Render Draws',
+ source: qml,
+ width: 300,
+ height: 200
+});
+window.setPosition(200, 50);
+window.closed.connect(function() { Script.stop(); });
\ No newline at end of file
diff --git a/examples/utilities/tools/render/framebuffer.qml b/examples/utilities/render/framebuffer.qml
similarity index 100%
rename from examples/utilities/tools/render/framebuffer.qml
rename to examples/utilities/render/framebuffer.qml
diff --git a/examples/utilities/tools/render/main.qml b/examples/utilities/render/main.qml
similarity index 99%
rename from examples/utilities/tools/render/main.qml
rename to examples/utilities/render/main.qml
index 22f263b2d0..aecd566207 100644
--- a/examples/utilities/tools/render/main.qml
+++ b/examples/utilities/render/main.qml
@@ -10,6 +10,7 @@
//
import QtQuick 2.5
import QtQuick.Controls 1.4
+import "configSlider"
Column {
id: root
diff --git a/examples/utilities/tools/render/plotperf/PlotPerf.qml b/examples/utilities/render/plotperf/PlotPerf.qml
similarity index 67%
rename from examples/utilities/tools/render/plotperf/PlotPerf.qml
rename to examples/utilities/render/plotperf/PlotPerf.qml
index 0e100e4e72..179707c0f1 100644
--- a/examples/utilities/tools/render/plotperf/PlotPerf.qml
+++ b/examples/utilities/render/plotperf/PlotPerf.qml
@@ -1,6 +1,6 @@
//
// PlotPerf.qml
-// examples/utilities/tools/render
+// examples/utilities/render/plotperf
//
// Created by Sam Gateau on 3//2016
// Copyright 2016 High Fidelity, Inc.
@@ -15,40 +15,64 @@ Item {
id: root
width: parent.width
height: 100
+
+ // The title of the graph
property string title
- property var config
- property string parameters
- // THis is my hack to get the name of the first property and assign it to a trigger var in order to get
+ // THe object used as the default source object for the prop plots
+ property var object
+
+ // THis is my hack to get a property and assign it to a trigger var in order to get
// a signal called whenever the value changed
- property var trigger: config[parameters.split(":")[3].split("-")[0]]
+ property var trigger
+
+ // Plots is an array of plot descriptor
+ // a default plot descriptor expects the following object:
+ // prop: [ {
+ // object: {} // Optional: this is the object from which the prop will be fetched,
+ // if nothing than the object from root is used
+ // prop:"bufferCPUCount", // Needed the name of the property from the object to feed the plot
+ // label: "CPU", // Optional: Label as displayed on the plot
+ // color: "#00B4EF" // Optional: Color of the curve
+ // unit: "km/h" // Optional: Unit added to the value displayed, if nothing then the default unit is used
+ // scale: 1 // Optional: Extra scaling used to represent the value, this scale is combined with the global scale.
+ // },
+ property var plots
+
+ // Default value scale used to define the max value of the chart
+ property var valueScale: 1
+
+ // Default value unit appended to the value displayed
+ property var valueUnit: ""
+
+ // Default number of digits displayed
+ property var valueNumDigits: 0
+
- property var inputs: parameters.split(":")
- property var valueScale: +inputs[0]
- property var valueUnit: inputs[1]
- property var valueNumDigits: inputs[2]
- property var input_VALUE_OFFSET: 3
property var valueMax : 1
property var _values : new Array()
property var tick : 0
function createValues() {
- if (inputs.length > input_VALUE_OFFSET) {
- for (var i = input_VALUE_OFFSET; i < inputs.length; i++) {
- var varProps = inputs[i].split("-")
- _values.push( {
- value: varProps[0],
- valueMax: 1,
- numSamplesConstantMax: 0,
- valueHistory: new Array(),
- label: varProps[1],
- color: varProps[2],
- scale: (varProps.length > 3 ? varProps[3] : 1),
- unit: (varProps.length > 4 ? varProps[4] : valueUnit)
- })
- }
- }
+ print("trigger is: " + JSON.stringify(trigger))
+ if (Array.isArray(plots)) {
+ for (var i =0; i < plots.length; i++) {
+ var plot = plots[i];
+ print(" a pnew Plot:" + JSON.stringify(plot));
+ _values.push( {
+ object: (plot["object"] !== undefined ? plot["object"] : root.object),
+ value: plot["prop"],
+ valueMax: 1,
+ numSamplesConstantMax: 0,
+ valueHistory: new Array(),
+ label: (plot["label"] !== undefined ? plot["label"] : ""),
+ color: (plot["color"] !== undefined ? plot["color"] : "white"),
+ scale: (plot["scale"] !== undefined ? plot["scale"] : 1),
+ unit: (plot["unit"] !== undefined ? plot["unit"] : valueUnit)
+ })
+ }
+ }
print("in creator" + JSON.stringify(_values));
}
@@ -69,7 +93,8 @@ Item {
var currentValueMax = 0
for (var i = 0; i < _values.length; i++) {
- var currentVal = config[_values[i].value] * _values[i].scale;
+ var currentVal = _values[i].object[_values[i].value] * _values[i].scale;
+
_values[i].valueHistory.push(currentVal)
_values[i].numSamplesConstantMax++;
diff --git a/examples/utilities/tools/render/plotperf/qmldir b/examples/utilities/render/plotperf/qmldir
similarity index 100%
rename from examples/utilities/tools/render/plotperf/qmldir
rename to examples/utilities/render/plotperf/qmldir
diff --git a/examples/utilities/tools/render/renderStats.js b/examples/utilities/render/renderStats.js
similarity index 100%
rename from examples/utilities/tools/render/renderStats.js
rename to examples/utilities/render/renderStats.js
diff --git a/examples/utilities/render/stats.qml b/examples/utilities/render/stats.qml
new file mode 100644
index 0000000000..0e51cb8834
--- /dev/null
+++ b/examples/utilities/render/stats.qml
@@ -0,0 +1,195 @@
+//
+// stats.qml
+// examples/utilities/render
+//
+// Created by Zach Pomerantz on 2/8/2016
+// Copyright 2016 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
+//
+import QtQuick 2.5
+import QtQuick.Controls 1.4
+import "plotperf"
+
+Item {
+ id: statsUI
+ anchors.fill:parent
+
+ Column {
+ id: stats
+ spacing: 8
+ anchors.fill:parent
+
+ property var config: Render.getConfig("Stats")
+
+ function evalEvenHeight() {
+ // Why do we have to do that manually ? cannot seem to find a qml / anchor / layout mode that does that ?
+ return (height - spacing * (children.length - 1)) / children.length
+ }
+
+ PlotPerf {
+ title: "Num Buffers"
+ height: parent.evalEvenHeight()
+ object: stats.config
+ trigger: stats.config["bufferCPUCount"]
+ plots: [
+ {
+ prop: "bufferCPUCount",
+ label: "CPU",
+ color: "#00B4EF"
+ },
+ {
+ prop: "bufferGPUCount",
+ label: "GPU",
+ color: "#1AC567"
+ }
+ ]
+ }
+ PlotPerf {
+ title: "gpu::Buffer Memory"
+ height: parent.evalEvenHeight()
+ object: stats.config
+ trigger: stats.config["bufferCPUMemoryUsage"]
+ valueScale: 1048576
+ valueUnit: "Mb"
+ valueNumDigits: "1"
+ plots: [
+ {
+ prop: "bufferCPUMemoryUsage",
+ label: "CPU",
+ color: "#00B4EF"
+ },
+ {
+ prop: "bufferGPUMemoryUsage",
+ label: "GPU",
+ color: "#1AC567"
+ }
+ ]
+ }
+ PlotPerf {
+ title: "Num Textures"
+ height: parent.evalEvenHeight()
+ object: stats.config
+ trigger: stats.config["textureCPUCount"]
+ plots: [
+ {
+ prop: "textureCPUCount",
+ label: "CPU",
+ color: "#00B4EF"
+ },
+ {
+ prop: "textureGPUCount",
+ label: "GPU",
+ color: "#1AC567"
+ },
+ {
+ prop: "frameTextureCount",
+ label: "Frame",
+ color: "#E2334D"
+ }
+ ]
+ }
+ PlotPerf {
+ title: "gpu::Texture Memory"
+ height: parent.evalEvenHeight()
+ object: stats.config
+ trigger: stats.config["textureCPUMemoryUsage"]
+ valueScale: 1048576
+ valueUnit: "Mb"
+ valueNumDigits: "1"
+ plots: [
+ {
+ prop: "textureCPUMemoryUsage",
+ label: "CPU",
+ color: "#00B4EF"
+ },
+ {
+ prop: "textureGPUMemoryUsage",
+ label: "GPU",
+ color: "#1AC567"
+ }
+ ]
+ }
+
+ PlotPerf {
+ title: "Triangles"
+ height: parent.evalEvenHeight()
+ object: stats.config
+ trigger: stats.config["frameTriangleCount"]
+ valueScale: 1000
+ valueUnit: "K"
+ plots: [
+ {
+ prop: "frameTriangleCount",
+ label: "Triangles",
+ color: "#1AC567"
+ },
+ {
+ prop: "frameTriangleRate",
+ label: "rate",
+ color: "#E2334D",
+ scale: 0.001,
+ unit: "MT/s"
+ }
+ ]
+ }
+ PlotPerf {
+ title: "Drawcalls"
+ height: parent.evalEvenHeight()
+ object: stats.config
+ trigger: stats.config["frameDrawcallCount"]
+ plots: [
+ {
+ prop: "frameAPIDrawcallCount",
+ label: "API Drawcalls",
+ color: "#00B4EF"
+ },
+ {
+ prop: "frameDrawcallCount",
+ label: "GPU Drawcalls",
+ color: "#1AC567"
+ },
+ {
+ prop: "frameDrawcallRate",
+ label: "rate",
+ color: "#E2334D",
+ scale: 0.001,
+ unit: "K/s"
+ }
+ ]
+ }
+
+ property var drawOpaqueConfig: Render.getConfig("DrawOpaqueDeferred")
+ property var drawTransparentConfig: Render.getConfig("DrawTransparentDeferred")
+ property var drawLightConfig: Render.getConfig("DrawLight")
+
+ PlotPerf {
+ title: "Items"
+ height: parent.evalEvenHeight()
+ object: parent.drawOpaqueConfig
+ trigger: Render.getConfig("DrawOpaqueDeferred")["numDrawn"]
+ plots: [
+ {
+ object: Render.getConfig("DrawOpaqueDeferred"),
+ prop: "numDrawn",
+ label: "Opaques",
+ color: "#1AC567"
+ },
+ {
+ object: Render.getConfig("DrawTransparentDeferred"),
+ prop: "numDrawn",
+ label: "Translucents",
+ color: "#00B4EF"
+ },
+ {
+ object: Render.getConfig("DrawLight"),
+ prop: "numDrawn",
+ label: "Lights",
+ color: "#E2334D"
+ }
+ ]
+ }
+ }
+
+}
diff --git a/examples/utilities/tools/debugRenderCulling.js b/examples/utilities/tools/debugRenderCulling.js
deleted file mode 100644
index dbc5f07e0d..0000000000
--- a/examples/utilities/tools/debugRenderCulling.js
+++ /dev/null
@@ -1,99 +0,0 @@
-//
-// debugRenderOctree.js
-// examples/utilities/tools
-//
-// Sam Gateau
-// Copyright 2016 High Fidelity, Inc.
-//
-// Distributed under the Apache License, Version 2.0.
-// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-//
-
-Script.include("cookies.js");
-
-var panel = new Panel(10, 300);
-var drawOctree = Render.RenderDeferredTask.DrawSceneOctree;
-Render.RenderDeferredTask.DrawSceneOctree.enabled = true;
-Render.RenderDeferredTask.DrawItemSelection.enabled = true;
-
-panel.newCheckbox("Show Octree Cells",
- function(value) { Render.RenderDeferredTask.DrawSceneOctree.showVisibleCells = value; },
- function() { return (Render.RenderDeferredTask.DrawSceneOctree.showVisibleCells); },
- function(value) { return (value); }
-);
-panel.newCheckbox("Show Empty Cells",
- function(value) { Render.RenderDeferredTask.DrawSceneOctree.showEmptyCells = value; },
- function() { return (Render.RenderDeferredTask.DrawSceneOctree.showEmptyCells); },
- function(value) { return (value); }
-);
-panel.newCheckbox("Freeze Frustum",
- function(value) { Render.RenderDeferredTask.FetchSceneSelection.freezeFrustum = value; Render.RenderDeferredTask.CullSceneSelection.freezeFrustum = value; },
- function() { return (Render.RenderDeferredTask.FetchSceneSelection.freezeFrustum); },
- function(value) { return (value); }
-);
-panel.newCheckbox("Show Inside Items",
- function(value) { Render.RenderDeferredTask.DrawItemSelection.showInsideItems = value; },
- function() { return (Render.RenderDeferredTask.DrawItemSelection.showInsideItems); },
- function(value) { return (value); }
-);
-
-panel.newCheckbox("Show Inside Subcell Items",
- function(value) { Render.RenderDeferredTask.DrawItemSelection.showInsideSubcellItems = value; },
- function() { return (Render.RenderDeferredTask.DrawItemSelection.showInsideSubcellItems); },
- function(value) { return (value); }
-);
-
-panel.newCheckbox("Show Partial Items",
- function(value) { Render.RenderDeferredTask.DrawItemSelection.showPartialItems = value; },
- function() { return (Render.RenderDeferredTask.DrawItemSelection.showPartialItems); },
- function(value) { return (value); }
-);
-
-panel.newCheckbox("Show Partial Subcell Items",
- function(value) { Render.RenderDeferredTask.DrawItemSelection.showPartialSubcellItems = value; },
- function() { return (Render.RenderDeferredTask.DrawItemSelection.showPartialSubcellItems); },
- function(value) { return (value); }
-);
-
-/*
-panel.newSlider('Cells Free / Allocated', -1, 1,
- function(value) { value; }, // setter
- function() { return Render.RenderDeferredTask.DrawSceneOctree.numFreeCells; }, // getter
- function(value) { return value; });
-
-this.update = function () {
- var numFree = Render.RenderDeferredTask.DrawSceneOctree.numFreeCells;
- var numAlloc = Render.RenderDeferredTask.DrawSceneOctree.numAllocatedCells;
- var title = [
- ' ' + name,
- numFree + ' / ' + numAlloc
- ].join('\t');
-
- widget.editTitle({ text: title });
- slider.setMaxValue(numAlloc);
-};
-*/
-function mouseMoveEvent(event) {
- panel.mouseMoveEvent(event);
-}
-
-function mousePressEvent(event) {
- panel.mousePressEvent(event);
-}
-
-function mouseReleaseEvent(event) {
- panel.mouseReleaseEvent(event);
-}
-
-Controller.mouseMoveEvent.connect(mouseMoveEvent);
-Controller.mousePressEvent.connect(mousePressEvent);
-Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
-
-function scriptEnding() {
- panel.destroy();
- Render.RenderDeferredTask.DrawSceneOctree.enabled = false;
- Render.RenderDeferredTask.DrawItemSelection.enabled = false;
-}
-Script.scriptEnding.connect(scriptEnding);
-
-
diff --git a/examples/utilities/tools/render/stats.qml b/examples/utilities/tools/render/stats.qml
deleted file mode 100644
index aacc896444..0000000000
--- a/examples/utilities/tools/render/stats.qml
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// stats.qml
-// examples/utilities/tools/render
-//
-// Created by Zach Pomerantz on 2/8/2016
-// Copyright 2016 High Fidelity, Inc.
-//
-// Distributed under the Apache License, Version 2.0.
-// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
-//
-import QtQuick 2.5
-import QtQuick.Controls 1.4
-import "plotperf"
-
-Item {
- id: statsUI
- anchors.fill:parent
-
- Column {
- id: stats
- spacing: 8
- anchors.fill:parent
-
- property var config: Render.getConfig("Stats")
-
- function evalEvenHeight() {
- // Why do we have to do that manually ? cannot seem to find a qml / anchor / layout mode that does that ?
- return (height - spacing * (children.length - 1)) / children.length
- }
-
- PlotPerf {
- title: "Num Buffers"
- config: stats.config
- height: parent.evalEvenHeight()
- parameters: "1::0:bufferCPUCount-CPU-#00B4EF:bufferGPUCount-GPU-#1AC567"
- }
- PlotPerf {
- title: "gpu::Buffer Memory"
- config: stats.config
- height: parent.evalEvenHeight()
- parameters: "1048576:Mb:1:bufferCPUMemoryUsage-CPU-#00B4EF:bufferGPUMemoryUsage-GPU-#1AC567"
- }
-
- PlotPerf {
- title: "Num Textures"
- config: stats.config
- height: parent.evalEvenHeight()
- parameters: "1::0:textureCPUCount-CPU-#00B4EF:textureGPUCount-GPU-#1AC567:frameTextureCount-Frame-#E2334D"
- }
- PlotPerf {
- title: "gpu::Texture Memory"
- config: stats.config
- height: parent.evalEvenHeight()
- parameters: "1048576:Mb:1:textureCPUMemoryUsage-CPU-#00B4EF:textureGPUMemoryUsage-GPU-#1AC567"
- }
- PlotPerf {
- title: "Drawcalls"
- config: stats.config
- height: parent.evalEvenHeight()
- parameters: "1::0:frameDrawcallCount-frame-#E2334D:frameDrawcallRate-rate-#1AC567-0.001-K/s"
- }
- PlotPerf {
- title: "Triangles"
- config: stats.config
- height: parent.evalEvenHeight()
- parameters: "1000:K:0:frameTriangleCount-frame-#E2334D:frameTriangleRate-rate-#1AC567-0.001-MT/s"
- }
- }
-}
diff --git a/ice-server/src/IceServer.cpp b/ice-server/src/IceServer.cpp
index d7fba12f26..a512d5a049 100644
--- a/ice-server/src/IceServer.cpp
+++ b/ice-server/src/IceServer.cpp
@@ -19,6 +19,7 @@
#include
#include
+#include
#include
#include
#include
@@ -33,7 +34,8 @@ IceServer::IceServer(int argc, char* argv[]) :
_id(QUuid::createUuid()),
_serverSocket(),
_activePeers(),
- _httpManager(QHostAddress::AnyIPv4, ICE_SERVER_MONITORING_PORT, QString("%1/web/").arg(QCoreApplication::applicationDirPath()), this)
+ _httpManager(QHostAddress::AnyIPv4, ICE_SERVER_MONITORING_PORT, QString("%1/web/").arg(QCoreApplication::applicationDirPath()), this),
+ _lastInactiveCheckTimestamp(QDateTime::currentMSecsSinceEpoch())
{
// start the ice-server socket
qDebug() << "ice-server socket is listening on" << ICE_SERVER_DEFAULT_PORT;
@@ -68,8 +70,6 @@ bool IceServer::packetVersionMatch(const udt::Packet& packet) {
void IceServer::processPacket(std::unique_ptr packet) {
- _lastPacketTimestamp = QDateTime::currentMSecsSinceEpoch();
-
auto nlPacket = NLPacket::fromBase(std::move(packet));
// make sure that this packet at least looks like something we can read
@@ -201,8 +201,8 @@ bool IceServer::isVerifiedHeartbeat(const QUuid& domainID, const QByteArray& pla
void IceServer::requestDomainPublicKey(const QUuid& domainID) {
// send a request to the metaverse API for the public key for this domain
- QNetworkAccessManager* manager = new QNetworkAccessManager { this };
- connect(manager, &QNetworkAccessManager::finished, this, &IceServer::publicKeyReplyFinished);
+ auto& networkAccessManager = NetworkAccessManager::getInstance();
+ connect(&networkAccessManager, &QNetworkAccessManager::finished, this, &IceServer::publicKeyReplyFinished);
QUrl publicKeyURL { NetworkingConstants::METAVERSE_SERVER_URL };
QString publicKeyPath = QString("/api/v1/domains/%1/public_key").arg(uuidStringWithoutCurlyBraces(domainID));
@@ -213,7 +213,7 @@ void IceServer::requestDomainPublicKey(const QUuid& domainID) {
qDebug() << "Requesting public key for domain with ID" << domainID;
- manager->get(publicKeyRequest);
+ networkAccessManager.get(publicKeyRequest);
}
void IceServer::publicKeyReplyFinished(QNetworkReply* reply) {
@@ -281,6 +281,8 @@ void IceServer::sendPeerInformationPacket(const NetworkPeer& peer, const HifiSoc
void IceServer::clearInactivePeers() {
NetworkPeerHash::iterator peerItem = _activePeers.begin();
+ _lastInactiveCheckTimestamp = QDateTime::currentMSecsSinceEpoch();
+
while (peerItem != _activePeers.end()) {
SharedNetworkPeer peer = peerItem.value();
@@ -309,11 +311,14 @@ bool IceServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, b
const quint64 MAX_PACKET_GAP_MS_FOR_STUCK_SOCKET = 10 * 1000;
- int statusNumber = (QDateTime::currentMSecsSinceEpoch() - _lastPacketTimestamp > MAX_PACKET_GAP_MS_FOR_STUCK_SOCKET)
- ? 1 : 0;
+ auto sinceLastInactiveCheck = QDateTime::currentMSecsSinceEpoch() - _lastInactiveCheckTimestamp;
+ int statusNumber = (sinceLastInactiveCheck > MAX_PACKET_GAP_MS_FOR_STUCK_SOCKET) ? 1 : 0;
connection->respond(HTTPConnection::StatusCode200, QByteArray::number(statusNumber));
+
+ return true;
}
}
- return true;
+
+ return false;
}
diff --git a/ice-server/src/IceServer.h b/ice-server/src/IceServer.h
index 6cc33fd8fc..7d1d05324c 100644
--- a/ice-server/src/IceServer.h
+++ b/ice-server/src/IceServer.h
@@ -58,7 +58,7 @@ private:
using DomainPublicKeyHash = std::unordered_map;
DomainPublicKeyHash _domainPublicKeys;
- quint64 _lastPacketTimestamp;
+ quint64 _lastInactiveCheckTimestamp;
};
#endif // hifi_IceServer_h
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index de9b134b83..1c6fec1c67 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -224,7 +224,6 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).append("/script.js");
#endif
-const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js";
Setting::Handle maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
const QHash Application::_acceptedExtensions {
@@ -1490,11 +1489,15 @@ void Application::paintGL() {
// FIXME not needed anymore?
_offscreenContext->makeCurrent();
- displayPlugin->updateHeadPose(_frameCount);
+ displayPlugin->beginFrameRender(_frameCount);
// update the avatar with a fresh HMD pose
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
+ // update sensorToWorldMatrix for camera and hand controllers
+ getMyAvatar()->updateSensorToWorldMatrix();
+
+
auto lodManager = DependencyManager::get();
@@ -2007,6 +2010,12 @@ void Application::keyPressEvent(QKeyEvent* event) {
}
break;
+ case Qt::Key_Y:
+ if (isShifted && isMeta) {
+ getActiveDisplayPlugin()->cycleDebugOutput();
+ }
+ break;
+
case Qt::Key_B:
if (isMeta) {
auto offscreenUi = DependencyManager::get();
@@ -2572,11 +2581,6 @@ void Application::idle(uint64_t now) {
return; // bail early, nothing to do here.
}
- checkChangeCursor();
-
- Stats::getInstance()->updateStats();
- AvatarInputs::getInstance()->update();
-
// These tasks need to be done on our first idle, because we don't want the showing of
// overlay subwindows to do a showDesktop() until after the first time through
static bool firstIdle = true;
@@ -2625,6 +2629,11 @@ void Application::idle(uint64_t now) {
// We're going to execute idle processing, so restart the last idle timer
_lastTimeUpdated.start();
+ checkChangeCursor();
+
+ Stats::getInstance()->updateStats();
+ AvatarInputs::getInstance()->update();
+
{
static uint64_t lastIdleStart{ now };
uint64_t idleStartToStartDuration = now - lastIdleStart;
@@ -3389,9 +3398,6 @@ void Application::update(float deltaTime) {
qApp->updateMyAvatarLookAtPosition();
- // update sensorToWorldMatrix for camera and hand controllers
- myAvatar->updateSensorToWorldMatrix();
-
{
PROFILE_RANGE_EX("MyAvatar", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount());
avatarManager->updateMyAvatar(deltaTime);
diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp
index 38babc4ef0..6aa6f57e07 100644
--- a/interface/src/avatar/MyAvatar.cpp
+++ b/interface/src/avatar/MyAvatar.cpp
@@ -373,32 +373,34 @@ void MyAvatar::simulate(float deltaTime) {
EntityTreeRenderer* entityTreeRenderer = qApp->getEntities();
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
if (entityTree) {
- auto now = usecTimestampNow();
- EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender();
- MovingEntitiesOperator moveOperator(entityTree);
- forEachDescendant([&](SpatiallyNestablePointer object) {
- // if the queryBox has changed, tell the entity-server
- if (object->computePuffedQueryAACube() && object->getNestableType() == NestableType::Entity) {
- EntityItemPointer entity = std::static_pointer_cast(object);
- bool success;
- AACube newCube = entity->getQueryAACube(success);
- if (success) {
- moveOperator.addEntityToMoveList(entity, newCube);
- }
- if (packetSender) {
- EntityItemProperties properties = entity->getProperties();
- properties.setQueryAACubeDirty();
- properties.setLastEdited(now);
- packetSender->queueEditEntityMessage(PacketType::EntityEdit, entity->getID(), properties);
- entity->setLastBroadcast(usecTimestampNow());
+ entityTree->withWriteLock([&] {
+ auto now = usecTimestampNow();
+ EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender();
+ MovingEntitiesOperator moveOperator(entityTree);
+ forEachDescendant([&](SpatiallyNestablePointer object) {
+ // if the queryBox has changed, tell the entity-server
+ if (object->computePuffedQueryAACube() && object->getNestableType() == NestableType::Entity) {
+ EntityItemPointer entity = std::static_pointer_cast(object);
+ bool success;
+ AACube newCube = entity->getQueryAACube(success);
+ if (success) {
+ moveOperator.addEntityToMoveList(entity, newCube);
+ }
+ if (packetSender) {
+ EntityItemProperties properties = entity->getProperties();
+ properties.setQueryAACubeDirty();
+ properties.setLastEdited(now);
+ packetSender->queueEditEntityMessage(PacketType::EntityEdit, entity->getID(), properties);
+ entity->setLastBroadcast(usecTimestampNow());
+ }
}
+ });
+ // also update the position of children in our local octree
+ if (moveOperator.hasMovingEntities()) {
+ PerformanceTimer perfTimer("recurseTreeWithOperator");
+ entityTree->recurseTreeWithOperator(&moveOperator);
}
});
- // also update the position of children in our local octree
- if (moveOperator.hasMovingEntities()) {
- PerformanceTimer perfTimer("recurseTreeWithOperator");
- entityTree->recurseTreeWithOperator(&moveOperator);
- }
}
}
diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp
index 50e5b7591f..a81a6dab09 100644
--- a/libraries/audio-client/src/AudioClient.cpp
+++ b/libraries/audio-client/src/AudioClient.cpp
@@ -555,7 +555,7 @@ void AudioClient::configureReverb() {
p.wetDryMix = 100.0f;
p.preDelay = 0.0f;
p.earlyGain = -96.0f; // disable ER
- p.lateGain -= 12.0f; // quieter than listener reverb
+ p.lateGain += _reverbOptions->getWetDryMix() * (24.0f/100.0f) - 24.0f; // -0dB to -24dB, based on wetDryMix
p.lateMixLeft = 0.0f;
p.lateMixRight = 0.0f;
diff --git a/libraries/controllers/src/controllers/StandardControls.h b/libraries/controllers/src/controllers/StandardControls.h
index 2b0613321e..f101ba6c51 100644
--- a/libraries/controllers/src/controllers/StandardControls.h
+++ b/libraries/controllers/src/controllers/StandardControls.h
@@ -81,6 +81,9 @@ namespace controller {
// Triggers
LT,
RT,
+ // Grips (Oculus touch squeeze)
+ LG,
+ RG,
NUM_STANDARD_AXES,
LZ = LT,
RZ = RT
diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp
index 8049e2d5a5..e5d98d18f7 100644
--- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp
+++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp
@@ -552,9 +552,9 @@ float OpenGLDisplayPlugin::presentRate() {
{
Lock lock(_mutex);
result = _usecsPerFrame.getAverage();
- result = 1.0f / result;
- result *= USECS_PER_SECOND;
}
+ result = 1.0f / result;
+ result *= USECS_PER_SECOND;
return result;
}
diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h
index b9628deb6c..8c4862ee3d 100644
--- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h
@@ -17,9 +17,9 @@
#include
#include
#include
+#include
#define THREADED_PRESENT 1
-#include
class OpenGLDisplayPlugin : public DisplayPlugin {
protected:
diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp
index 5be3f0d96a..505fa004ab 100644
--- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp
+++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp
@@ -69,10 +69,11 @@ void HmdDisplayPlugin::compositeOverlay() {
// set the alpha
Uniform(*_program, _alphaUniform).Set(overlayAlpha);
+ auto eyePoses = _currentPresentFrameInfo.eyePoses;
_sphereSection->Use();
for_each_eye([&](Eye eye) {
eyeViewport(eye);
- auto modelView = glm::inverse(_currentRenderEyePoses[eye]); // *glm::translate(mat4(), vec3(0, 0, -1));
+ auto modelView = glm::inverse(eyePoses[eye]); // *glm::translate(mat4(), vec3(0, 0, -1));
auto mvp = _eyeProjections[eye] * modelView;
Uniform(*_program, _mvpUniform).Set(mvp);
_sphereSection->Draw();
@@ -95,10 +96,10 @@ void HmdDisplayPlugin::compositePointer() {
// Mouse pointer
_plane->Use();
// Reconstruct the headpose from the eye poses
- auto headPosition = (vec3(_currentRenderEyePoses[Left][3]) + vec3(_currentRenderEyePoses[Right][3])) / 2.0f;
+ auto headPosition = vec3(_currentPresentFrameInfo.headPose[3]);
for_each_eye([&](Eye eye) {
eyeViewport(eye);
- auto reticleTransform = compositorHelper->getReticleTransform(_currentRenderEyePoses[eye], headPosition);
+ auto reticleTransform = compositorHelper->getReticleTransform(_currentPresentFrameInfo.eyePoses[eye], headPosition);
auto mvp = _eyeProjections[eye] * reticleTransform;
Uniform(*_program, _mvpUniform).Set(mvp);
_plane->Draw();
@@ -160,15 +161,28 @@ void HmdDisplayPlugin::internalPresent() {
void HmdDisplayPlugin::setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) {
Lock lock(_mutex);
- _renderEyePoses[frameIndex][eye] = pose;
+ FrameInfo& frame = _frameInfos[frameIndex];
+ frame.eyePoses[eye] = pose;
}
void HmdDisplayPlugin::updateFrameData() {
+ // Check if we have old frame data to discard
+ {
+ Lock lock(_mutex);
+ auto itr = _frameInfos.find(_currentRenderFrameIndex);
+ if (itr != _frameInfos.end()) {
+ _frameInfos.erase(itr);
+ }
+ }
+
Parent::updateFrameData();
- Lock lock(_mutex);
- _currentRenderEyePoses = _renderEyePoses[_currentRenderFrameIndex];
+
+ {
+ Lock lock(_mutex);
+ _currentPresentFrameInfo = _frameInfos[_currentRenderFrameIndex];
+ }
}
glm::mat4 HmdDisplayPlugin::getHeadPose() const {
- return _headPoseCache.get();
+ return _currentRenderFrameInfo.get().headPose;
}
diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h
index 080a44bc66..899dd6636a 100644
--- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h
@@ -28,6 +28,16 @@ public:
virtual glm::mat4 getHeadPose() const override;
+ using EyePoses = std::array;
+
+ struct FrameInfo {
+ EyePoses eyePoses;
+ glm::mat4 headPose;
+ double sensorSampleTime { 0 };
+ double predictedDisplayTime { 0 };
+ };
+
+
protected:
virtual void hmdPresent() = 0;
virtual bool isHmdMounted() const = 0;
@@ -46,10 +56,10 @@ protected:
glm::mat4 _cullingProjection;
glm::uvec2 _renderTargetSize;
float _ipd { 0.064f };
- using EyePoses = std::array;
- QMap _renderEyePoses;
- EyePoses _currentRenderEyePoses;
- ThreadSafeValueCache _headPoseCache { glm::mat4() };
+
+ QMap _frameInfos;
+ FrameInfo _currentPresentFrameInfo;
+ ThreadSafeValueCache _currentRenderFrameInfo;
private:
bool _enablePreview { false };
diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
index 13942dc282..e18f85211f 100644
--- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
@@ -117,12 +117,11 @@ QVariantMap RenderableModelEntityItem::parseTexturesToMap(QString textures) {
QJsonParseError error;
QJsonDocument texturesJson = QJsonDocument::fromJson(textures.toUtf8(), &error);
if (error.error != QJsonParseError::NoError) {
- qCWarning(entitiesrenderer) << "Could not evaluate textures property value:" << _textures;
+ qCWarning(entitiesrenderer) << "Could not evaluate textures property value:" << textures;
return _originalTextures;
}
- auto parsed = texturesJson.toVariant();
- return parsed.toMap();
+ return texturesJson.toVariant().toMap();
}
void RenderableModelEntityItem::remapTextures() {
@@ -144,11 +143,17 @@ void RenderableModelEntityItem::remapTextures() {
_currentTextures = _originalTextures;
}
- auto textures = parseTexturesToMap(_textures);
+ auto textures = getTextures();
+ if (textures == _lastTextures) {
+ return;
+ }
- if (textures != _currentTextures) {
- geometry->setTextures(textures);
- _currentTextures = textures;
+ _lastTextures = textures;
+ auto newTextures = parseTexturesToMap(textures);
+
+ if (newTextures != _currentTextures) {
+ geometry->setTextures(newTextures);
+ _currentTextures = newTextures;
}
}
diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h
index e88b239e41..6d40a80950 100644
--- a/libraries/entities-renderer/src/RenderableModelEntityItem.h
+++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h
@@ -90,6 +90,7 @@ private:
bool _needsInitialSimulation = true;
bool _needsModelReload = true;
EntityTreeRenderer* _myRenderer = nullptr;
+ QString _lastTextures;
QVariantMap _currentTextures;
QVariantMap _originalTextures;
bool _originalTexturesRead = false;
diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp
index bef4406f71..e5511c0b25 100644
--- a/libraries/entities/src/ModelEntityItem.cpp
+++ b/libraries/entities/src/ModelEntityItem.cpp
@@ -42,6 +42,17 @@ ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID) : EntityItem(
_color[0] = _color[1] = _color[2] = 0;
}
+const QString ModelEntityItem::getTextures() const {
+ QReadLocker locker(&_texturesLock);
+ auto textures = _textures;
+ return textures;
+}
+
+void ModelEntityItem::setTextures(const QString& textures) {
+ QWriteLocker locker(&_texturesLock);
+ _textures = textures;
+}
+
EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h
index bce27f1cca..d0e0909b27 100644
--- a/libraries/entities/src/ModelEntityItem.h
+++ b/libraries/entities/src/ModelEntityItem.h
@@ -110,8 +110,8 @@ public:
float getAnimationFPS() const { return _animationLoop.getFPS(); }
static const QString DEFAULT_TEXTURES;
- const QString& getTextures() const { return _textures; }
- void setTextures(const QString& textures) { _textures = textures; }
+ const QString getTextures() const;
+ void setTextures(const QString& textures);
virtual bool shouldBePhysical() const;
@@ -159,7 +159,9 @@ protected:
AnimationPropertyGroup _animationProperties;
AnimationLoop _animationLoop;
+ mutable QReadWriteLock _texturesLock;
QString _textures;
+
ShapeType _shapeType = SHAPE_TYPE_NONE;
// used on client side
diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp
index 31bbc84cb2..8e5579f90b 100644
--- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp
+++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp
@@ -38,11 +38,13 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) {
_context->setShareContext(sharedContext);
}
_context->setFormat(getDefaultOpenGLSurfaceFormat());
+
if (_context->create()) {
_offscreenSurface->setFormat(_context->format());
_offscreenSurface->create();
- return true;
+ return _offscreenSurface->isValid();
}
+ qWarning("Failed to create OffscreenGLCanvas context");
return false;
}
diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp
index 1d9e6d0149..1d7824f789 100644
--- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp
+++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp
@@ -134,14 +134,13 @@ QEvent* OffscreenQmlRenderThread::Queue::take() {
}
OffscreenQmlRenderThread::OffscreenQmlRenderThread(OffscreenQmlSurface* surface, QOpenGLContext* shareContext) : _surface(surface) {
- qDebug() << "Building QML Renderer: creating context";
+ qDebug() << "Building QML Renderer";
if (!_canvas.create(shareContext)) {
- static const char* error = "Failed to create OffscreenGLCanvas";
- qWarning() << error;
- throw error;
+ qWarning("Failed to create OffscreenGLCanvas");
+ _quit = true;
+ return;
};
- qDebug() << "Building QML Renderer: creating render control";
_renderControl = new QMyQuickRenderControl();
QQuickWindow::setDefaultAlphaBuffer(true);
// Create a QQuickWindow that is associated with our render control.
@@ -149,19 +148,15 @@ OffscreenQmlRenderThread::OffscreenQmlRenderThread(OffscreenQmlSurface* surface,
// NOTE: Must be created on the main thread so that OffscreenQmlSurface can send it events
// NOTE: Must be created on the rendering thread or it will refuse to render,
// so we wait until after its ctor to move object/context to this thread.
- qDebug() << "Building QML Renderer: creating window";
_quickWindow = new QQuickWindow(_renderControl);
_quickWindow->setColor(QColor(255, 255, 255, 0));
_quickWindow->setFlags(_quickWindow->flags() | static_cast(Qt::WA_TranslucentBackground));
// We can prepare, but we must wait to start() the thread until after the ctor
- qDebug() << "Building QML Renderer: moving to own thread";
_renderControl->prepareThread(this);
_canvas.getContextObject()->moveToThread(this);
moveToThread(this);
- qDebug() << "Building QML Renderer: complete";
-
_queue.add(INIT);
}
diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h
index b898bddef9..7f442895a5 100644
--- a/libraries/gpu/src/gpu/Context.h
+++ b/libraries/gpu/src/gpu/Context.h
@@ -35,6 +35,7 @@ public:
int _RSNumTextureBounded = 0;
+ int _DSNumAPIDrawcalls = 0;
int _DSNumDrawcalls = 0;
int _DSNumTriangles = 0;
diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp
index e847ad1a42..b5b6437ed8 100644
--- a/libraries/gpu/src/gpu/GLBackend.cpp
+++ b/libraries/gpu/src/gpu/GLBackend.cpp
@@ -326,6 +326,7 @@ void GLBackend::do_draw(Batch& batch, size_t paramOffset) {
glDrawArrays(mode, startVertex, numVertices);
_stats._DSNumTriangles += numVertices / 3;
_stats._DSNumDrawcalls++;
+ _stats._DSNumAPIDrawcalls++;
(void)CHECK_GL_ERROR();
}
@@ -344,6 +345,7 @@ void GLBackend::do_drawIndexed(Batch& batch, size_t paramOffset) {
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
_stats._DSNumTriangles += numIndices / 3;
_stats._DSNumDrawcalls++;
+ _stats._DSNumAPIDrawcalls++;
(void) CHECK_GL_ERROR();
}
@@ -358,6 +360,7 @@ void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) {
glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances);
_stats._DSNumTriangles += (numInstances * numVertices) / 3;
_stats._DSNumDrawcalls += numInstances;
+ _stats._DSNumAPIDrawcalls++;
(void) CHECK_GL_ERROR();
}
@@ -383,6 +386,7 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) {
#endif
_stats._DSNumTriangles += (numInstances * numIndices) / 3;
_stats._DSNumDrawcalls += numInstances;
+ _stats._DSNumAPIDrawcalls++;
(void)CHECK_GL_ERROR();
}
@@ -395,6 +399,8 @@ void GLBackend::do_multiDrawIndirect(Batch& batch, size_t paramOffset) {
glMultiDrawArraysIndirect(mode, reinterpret_cast(_input._indirectBufferOffset), commandCount, (GLsizei)_input._indirectBufferStride);
_stats._DSNumDrawcalls += commandCount;
+ _stats._DSNumAPIDrawcalls++;
+
#else
// FIXME implement the slow path
#endif
@@ -410,7 +416,7 @@ void GLBackend::do_multiDrawIndexedIndirect(Batch& batch, size_t paramOffset) {
glMultiDrawElementsIndirect(mode, indexType, reinterpret_cast(_input._indirectBufferOffset), commandCount, (GLsizei)_input._indirectBufferStride);
_stats._DSNumDrawcalls += commandCount;
-
+ _stats._DSNumAPIDrawcalls++;
#else
// FIXME implement the slow path
#endif
diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp
index 36ce1dd555..5ef77773e8 100644
--- a/libraries/gpu/src/gpu/GLBackendState.cpp
+++ b/libraries/gpu/src/gpu/GLBackendState.cpp
@@ -610,6 +610,8 @@ void GLBackend::do_setStateDepthBias(Vec2 bias) {
glDisable(GL_POLYGON_OFFSET_LINE);
glDisable(GL_POLYGON_OFFSET_POINT);
}
+ (void) CHECK_GL_ERROR();
+
_pipeline._stateCache.depthBias = bias.x;
_pipeline._stateCache.depthBiasSlopeScale = bias.y;
}
@@ -690,6 +692,7 @@ void GLBackend::do_setStateAlphaToCoverageEnable(bool enable) {
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
}
(void) CHECK_GL_ERROR();
+
_pipeline._stateCache.alphaToCoverageEnable = enable;
}
}
@@ -703,6 +706,7 @@ void GLBackend::do_setStateSampleMask(uint32 mask) {
glEnable(GL_SAMPLE_MASK);
glSampleMaski(0, mask);
}
+ (void) CHECK_GL_ERROR();
#endif
_pipeline._stateCache.sampleMask = mask;
}
@@ -743,10 +747,10 @@ void GLBackend::do_setStateBlend(State::BlendFunction function) {
glBlendFuncSeparate(BLEND_ARGS[function.getSourceColor()], BLEND_ARGS[function.getDestinationColor()],
BLEND_ARGS[function.getSourceAlpha()], BLEND_ARGS[function.getDestinationAlpha()]);
- (void) CHECK_GL_ERROR();
} else {
glDisable(GL_BLEND);
}
+ (void) CHECK_GL_ERROR();
_pipeline._stateCache.blendFunction = function;
}
@@ -758,6 +762,7 @@ void GLBackend::do_setStateColorWriteMask(uint32 mask) {
mask & State::ColorMask::WRITE_GREEN,
mask & State::ColorMask::WRITE_BLUE,
mask & State::ColorMask::WRITE_ALPHA );
+ (void) CHECK_GL_ERROR();
_pipeline._stateCache.colorWriteMask = mask;
}
@@ -765,7 +770,6 @@ void GLBackend::do_setStateColorWriteMask(uint32 mask) {
void GLBackend::do_setStateBlendFactor(Batch& batch, size_t paramOffset) {
-
Vec4 factor(batch._params[paramOffset + 0]._float,
batch._params[paramOffset + 1]._float,
batch._params[paramOffset + 2]._float,
diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp
index 09714b5542..3fc7906285 100755
--- a/libraries/gpu/src/gpu/GLBackendTexture.cpp
+++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp
@@ -225,6 +225,12 @@ public:
}
break;
+ case gpu::R11G11B10:
+ texel.format = GL_RGB;
+ // the type should be float
+ texel.internalFormat = GL_R11F_G11F_B10F;
+ break;
+
case gpu::DEPTH:
texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it
texel.internalFormat = GL_DEPTH_COMPONENT;
@@ -302,11 +308,6 @@ public:
case gpu::SRGBA:
texel.internalFormat = GL_SRGB; // standard 2.2 gamma correction color
break;
- case gpu::R11G11B10: {
- // the type should be float
- texel.internalFormat = GL_R11F_G11F_B10F;
- break;
- }
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp
index df93cd76a5..af740ddb65 100755
--- a/libraries/gpu/src/gpu/Texture.cpp
+++ b/libraries/gpu/src/gpu/Texture.cpp
@@ -285,7 +285,7 @@ Texture::Size Texture::resize(Type type, const Element& texelFormat, uint16 widt
}
// Here the Texture has been fully defined from the gpu point of view (size and format)
- _defined = true;
+ _defined = true;
} else {
_stamp++;
}
diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h
index f4f28176c7..77d984f924 100644
--- a/libraries/plugins/src/plugins/DisplayPlugin.h
+++ b/libraries/plugins/src/plugins/DisplayPlugin.h
@@ -122,7 +122,7 @@ public:
}
// will query the underlying hmd api to compute the most recent head pose
- virtual void updateHeadPose(uint32_t frameIndex) {}
+ virtual void beginFrameRender(uint32_t frameIndex) {}
// returns a copy of the most recent head pose, computed via updateHeadPose
virtual glm::mat4 getHeadPose() const {
@@ -142,6 +142,8 @@ public:
virtual float presentRate() { return -1.0f; }
uint32_t presentCount() const { return _presentedFrameIndex; }
+ virtual void cycleDebugOutput() {}
+
static const QString& MENU_PATH();
signals:
diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp
index f3fa4a43b2..ac24b09c40 100644
--- a/libraries/render-utils/src/DeferredLightingEffect.cpp
+++ b/libraries/render-utils/src/DeferredLightingEffect.cpp
@@ -435,8 +435,9 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);
// TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume,
// we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working...
+ const float OVER_CONSERVATIVE_SCALE = 1.1f;
if ((eyeHalfPlaneDistance > -nearRadius) &&
- (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius)) {
+ (glm::distance(eyePoint, glm::vec3(light->getPosition())) < (expandedRadius * OVER_CONSERVATIVE_SCALE) + nearRadius)) {
coneParam.w = 0.0f;
batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));
@@ -452,6 +453,7 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
batch.setProjectionTransform( projMats[side]);
batch.setViewTransform(viewTransforms[side]);
} else {
+ light->setShowContour(false);
coneParam.w = 1.0f;
batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));
diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp
index 7948dfcefe..22bfbfd869 100644
--- a/libraries/render-utils/src/FramebufferCache.cpp
+++ b/libraries/render-utils/src/FramebufferCache.cpp
@@ -97,7 +97,7 @@ void FramebufferCache::createPrimaryFramebuffer() {
// FIXME: Decide on the proper one, let s stick to R11G11B10 for now
//_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, defaultSampler));
- _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::R11G11B10), width, height, defaultSampler));
+ _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::R11G11B10), width, height, defaultSampler));
//_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, defaultSampler));
_lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
_lightingFramebuffer->setRenderBuffer(0, _lightingTexture);
diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp
index 8d59d5f736..c3abd15063 100644
--- a/libraries/render-utils/src/Model.cpp
+++ b/libraries/render-utils/src/Model.cpp
@@ -131,6 +131,8 @@ void Model::setOffset(const glm::vec3& offset) {
void Model::enqueueLocationChange() {
+ _needsUpdateClusterMatrices = true;
+
// queue up this work for later processing, at the end of update and just before rendering.
// the application will ensure only the last lambda is actually invoked.
void* key = (void*)this;
@@ -536,7 +538,7 @@ void Model::setVisibleInScene(bool newValue, std::shared_ptr scen
pendingChanges.resetItem(item, _modelMeshRenderItems[item]);
}
foreach (auto item, _collisionRenderItems.keys()) {
- pendingChanges.resetItem(item, _modelMeshRenderItems[item]);
+ pendingChanges.resetItem(item, _collisionRenderItems[item]);
}
scene->enqueuePendingChanges(pendingChanges);
}
diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h
index 0125ef79fe..9fb6802992 100755
--- a/libraries/render-utils/src/RenderDeferredTask.h
+++ b/libraries/render-utils/src/RenderDeferredTask.h
@@ -32,9 +32,10 @@ public:
class RenderDeferred {
public:
+ using JobModel = render::Job::Model;
+
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
- using JobModel = render::Job::Model;
};
class DrawConfig : public render::Job::Config {
diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf
index 69f8e836aa..8355dcf91b 100644
--- a/libraries/render-utils/src/spot_light.slf
+++ b/libraries/render-utils/src/spot_light.slf
@@ -25,6 +25,7 @@ in vec4 _texCoord0;
out vec4 _fragColor;
void main(void) {
+
DeferredTransform deferredTransform = getDeferredTransform();
// Grab the fragment data from the uv
diff --git a/libraries/render/src/render/DrawSceneOctree.h b/libraries/render/src/render/DrawSceneOctree.h
index 60fc0bb2c4..530b7accac 100644
--- a/libraries/render/src/render/DrawSceneOctree.h
+++ b/libraries/render/src/render/DrawSceneOctree.h
@@ -20,17 +20,14 @@ namespace render {
class DrawSceneOctreeConfig : public Job::Config {
Q_OBJECT
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty())
- Q_PROPERTY(bool showVisibleCells MEMBER showVisibleCells WRITE setShowVisibleCells)
- Q_PROPERTY(bool showEmptyCells MEMBER showEmptyCells WRITE setShowEmptyCells)
+ Q_PROPERTY(bool showVisibleCells READ getShowVisibleCells WRITE setShowVisibleCells NOTIFY dirty())
+ Q_PROPERTY(bool showEmptyCells READ getShowEmptyCells WRITE setShowEmptyCells NOTIFY dirty())
Q_PROPERTY(int numAllocatedCells READ getNumAllocatedCells)
Q_PROPERTY(int numFreeCells READ getNumFreeCells)
public:
DrawSceneOctreeConfig() : Job::Config(false) {}
-
- bool showVisibleCells{ true };
- bool showEmptyCells{ false };
int numAllocatedCells{ 0 };
int numFreeCells{ 0 };
@@ -38,6 +35,12 @@ namespace render {
int getNumAllocatedCells() const { return numAllocatedCells; }
int getNumFreeCells() const { return numFreeCells; }
+ bool showVisibleCells{ true };
+ bool showEmptyCells{ false };
+
+ bool getShowVisibleCells() { return showVisibleCells; }
+ bool getShowEmptyCells() { return showEmptyCells; }
+
public slots:
void setShowVisibleCells(bool show) { showVisibleCells = show; emit dirty(); }
void setShowEmptyCells(bool show) { showEmptyCells = show; emit dirty(); }
@@ -79,10 +82,10 @@ namespace render {
class DrawItemSelectionConfig : public Job::Config {
Q_OBJECT
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty())
- Q_PROPERTY(bool showInsideItems MEMBER showInsideItems WRITE setShowInsideItems)
- Q_PROPERTY(bool showInsideSubcellItems MEMBER showInsideSubcellItems WRITE setShowInsideSubcellItems)
- Q_PROPERTY(bool showPartialItems MEMBER showPartialItems WRITE setShowPartialItems)
- Q_PROPERTY(bool showPartialSubcellItems MEMBER showPartialSubcellItems WRITE setShowPartialSubcellItems)
+ Q_PROPERTY(bool showInsideItems READ getShowInsideItems WRITE setShowInsideItems NOTIFY dirty())
+ Q_PROPERTY(bool showInsideSubcellItems READ getShowInsideSubcellItems WRITE setShowInsideSubcellItems NOTIFY dirty())
+ Q_PROPERTY(bool showPartialItems READ getShowPartialItems WRITE setShowPartialItems NOTIFY dirty())
+ Q_PROPERTY(bool showPartialSubcellItems READ getShowPartialSubcellItems WRITE setShowPartialSubcellItems NOTIFY dirty())
public:
DrawItemSelectionConfig() : Job::Config(false) {}
@@ -92,7 +95,12 @@ namespace render {
bool showPartialItems{ true };
bool showPartialSubcellItems{ true };
- public slots:
+ bool getShowInsideItems() const { return showInsideItems; };
+ bool getShowInsideSubcellItems() const { return showInsideSubcellItems; };
+ bool getShowPartialItems() const { return showPartialItems; };
+ bool getShowPartialSubcellItems() const { return showPartialSubcellItems; };
+
+ public slots:
void setShowInsideItems(bool show) { showInsideItems = show; emit dirty(); }
void setShowInsideSubcellItems(bool show) { showInsideSubcellItems = show; emit dirty(); }
void setShowPartialItems(bool show) { showPartialItems = show; emit dirty(); }
diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp
index 733f7d9e9c..08ff97fd17 100755
--- a/libraries/render/src/render/DrawTask.cpp
+++ b/libraries/render/src/render/DrawTask.cpp
@@ -20,12 +20,16 @@
using namespace render;
-void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
+void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, int maxDrawnItems) {
auto& scene = sceneContext->_scene;
RenderArgs* args = renderContext->args;
- for (const auto& itemDetails : inItems) {
- auto& item = scene->getItem(itemDetails.id);
+ int numItemsToDraw = (int)inItems.size();
+ if (maxDrawnItems != -1) {
+ numItemsToDraw = glm::min(numItemsToDraw, maxDrawnItems);
+ }
+ for (auto i = 0; i < numItemsToDraw; ++i) {
+ auto& item = scene->getItem(inItems[i].id);
item.render(args);
}
}
@@ -69,7 +73,10 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext
// render lights
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch;
- renderItems(sceneContext, renderContext, inLights);
+ renderItems(sceneContext, renderContext, inLights, _maxDrawn);
args->_batch = nullptr;
});
+
+ auto config = std::static_pointer_cast(renderContext->jobConfig);
+ config->setNumDrawn((int)inLights.size());
}
diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h
index fc2ab9682f..8a0f951028 100755
--- a/libraries/render/src/render/DrawTask.h
+++ b/libraries/render/src/render/DrawTask.h
@@ -16,15 +16,37 @@
namespace render {
-void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems);
+void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, int maxDrawnItems = -1);
void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1);
+
+
+class DrawLightConfig : public Job::Config {
+ Q_OBJECT
+ Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged)
+ Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty)
+public:
+ int getNumDrawn() { return numDrawn; }
+ void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); }
+
+ int maxDrawn{ -1 };
+signals:
+ void numDrawnChanged();
+ void dirty();
+
+protected:
+ int numDrawn{ 0 };
+};
+
class DrawLight {
public:
- using JobModel = Job::ModelI;
+ using Config = DrawLightConfig;
+ using JobModel = Job::ModelI;
+ void configure(const Config& config) { _maxDrawn = config.maxDrawn; }
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights);
protected:
+ int _maxDrawn; // initialized by Config
};
}
diff --git a/libraries/render/src/render/EngineStats.cpp b/libraries/render/src/render/EngineStats.cpp
index ee96e0cd86..794f278fcf 100644
--- a/libraries/render/src/render/EngineStats.cpp
+++ b/libraries/render/src/render/EngineStats.cpp
@@ -36,6 +36,7 @@ void EngineStats::run(const SceneContextPointer& sceneContext, const RenderConte
gpu::ContextStats gpuStats(_gpuStats);
renderContext->args->_context->getStats(_gpuStats);
+ config->frameAPIDrawcallCount = _gpuStats._DSNumAPIDrawcalls - gpuStats._DSNumAPIDrawcalls;
config->frameDrawcallCount = _gpuStats._DSNumDrawcalls - gpuStats._DSNumDrawcalls;
config->frameDrawcallRate = config->frameDrawcallCount * frequency;
diff --git a/libraries/render/src/render/EngineStats.h b/libraries/render/src/render/EngineStats.h
index 478d94855e..4a57724644 100644
--- a/libraries/render/src/render/EngineStats.h
+++ b/libraries/render/src/render/EngineStats.h
@@ -34,6 +34,7 @@ namespace render {
Q_PROPERTY(qint64 textureCPUMemoryUsage MEMBER textureCPUMemoryUsage NOTIFY dirty)
Q_PROPERTY(qint64 textureGPUMemoryUsage MEMBER textureGPUMemoryUsage NOTIFY dirty)
+ Q_PROPERTY(quint32 frameAPIDrawcallCount MEMBER frameAPIDrawcallCount NOTIFY dirty)
Q_PROPERTY(quint32 frameDrawcallCount MEMBER frameDrawcallCount NOTIFY dirty)
Q_PROPERTY(quint32 frameDrawcallRate MEMBER frameDrawcallRate NOTIFY dirty)
@@ -57,6 +58,7 @@ namespace render {
qint64 textureCPUMemoryUsage{ 0 };
qint64 textureGPUMemoryUsage{ 0 };
+ quint32 frameAPIDrawcallCount{ 0 };
quint32 frameDrawcallCount{ 0 };
quint32 frameDrawcallRate{ 0 };
diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp
index 79f4b2a269..e091b4842c 100644
--- a/libraries/render/src/render/Scene.cpp
+++ b/libraries/render/src/render/Scene.cpp
@@ -16,8 +16,13 @@
using namespace render;
void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) {
- _resetItems.push_back(id);
- _resetPayloads.push_back(payload);
+ if (payload) {
+ _resetItems.push_back(id);
+ _resetPayloads.push_back(payload);
+ } else {
+ qDebug() << "WARNING: PendingChanges::resetItem with a null payload!";
+ removeItem(id);
+ }
}
void PendingChanges::removeItem(ItemID id) {
diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp
index a6541dc031..94662308fd 100644
--- a/libraries/script-engine/src/ScriptEngine.cpp
+++ b/libraries/script-engine/src/ScriptEngine.cpp
@@ -234,7 +234,7 @@ void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) {
void ScriptEngine::scriptContentsAvailable(const QUrl& url, const QString& scriptContents) {
_scriptContents = scriptContents;
if (_wantSignals) {
- emit scriptLoaded(_fileNameString);
+ emit scriptLoaded(url.toString());
}
}
diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp
index f95209d880..16301dc890 100644
--- a/libraries/script-engine/src/ScriptEngines.cpp
+++ b/libraries/script-engine/src/ScriptEngines.cpp
@@ -13,13 +13,14 @@
#include
#include
+#include
#include "ScriptEngine.h"
#include "ScriptEngineLogging.h"
#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
-#define __LOC__ __FILE__ "("__STR1__(__LINE__)") : Warning Msg: "
+#define __LOC__ __FILE__ "(" __STR1__(__LINE__) ") : Warning Msg: "
#ifndef __APPLE__
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
@@ -41,25 +42,53 @@ ScriptEngines::ScriptEngines()
_scriptsModelFilter.setDynamicSortFilter(true);
}
-QString normalizeScriptUrl(const QString& rawScriptUrl) {
- if (!rawScriptUrl.startsWith("http:") && !rawScriptUrl.startsWith("https:") && !rawScriptUrl.startsWith("atp:")) {
-#ifdef Q_OS_LINUX
- if (rawScriptUrl.startsWith("file:")) {
- return rawScriptUrl;
- }
- return QUrl::fromLocalFile(rawScriptUrl).toString();
-#else
- if (rawScriptUrl.startsWith("file:")) {
- return rawScriptUrl.toLower();
- }
- // Force lowercase on file scripts because of drive letter weirdness.
- return QUrl::fromLocalFile(rawScriptUrl).toString().toLower();
-#endif
+QUrl normalizeScriptURL(const QUrl& rawScriptURL) {
+ if (rawScriptURL.scheme() == "file") {
+ QUrl fullNormal = rawScriptURL;
+ QUrl defaultScriptLoc = defaultScriptsLocation();
+ #ifdef Q_OS_LINUX
+ #else
+ // Force lowercase on file scripts because of drive letter weirdness.
+ if (rawScriptURL.isLocalFile()) {
+ fullNormal.setPath(fullNormal.path().toLower());
+ }
+ #endif
+ // if this url is something "beneath" the default script url, replace the local path with ~
+ if (fullNormal.scheme() == defaultScriptLoc.scheme() &&
+ fullNormal.host() == defaultScriptLoc.host() &&
+ fullNormal.path().startsWith(defaultScriptLoc.path())) {
+ fullNormal.setPath("/~/" + fullNormal.path().mid(defaultScriptLoc.path().size()));
+ }
+ return fullNormal;
+ } else if (rawScriptURL.scheme() == "http" || rawScriptURL.scheme() == "https" || rawScriptURL.scheme() == "atp") {
+ return rawScriptURL;
+ } else {
+ // don't accidently support gopher
+ return QUrl("");
}
- return QUrl(rawScriptUrl).toString();
}
+QUrl expandScriptUrl(const QUrl& normalizedScriptURL) {
+ if (normalizedScriptURL.scheme() == "http" ||
+ normalizedScriptURL.scheme() == "https" ||
+ normalizedScriptURL.scheme() == "atp") {
+ return normalizedScriptURL;
+ } else if (normalizedScriptURL.scheme() == "file") {
+ if (normalizedScriptURL.path().startsWith("/~/")) {
+ QUrl url = normalizedScriptURL;
+ QStringList splitPath = url.path().split("/");
+ QUrl defaultScriptsLoc = defaultScriptsLocation();
+ url.setPath(defaultScriptsLoc.path() + "/" + splitPath.mid(2).join("/")); // 2 to skip the slashes in /~/
+ return url;
+ }
+ return normalizedScriptURL;
+ } else {
+ return QUrl("");
+ }
+}
+
+
QObject* scriptsModel();
void ScriptEngines::registerScriptInitializer(ScriptInitializer initializer) {
@@ -192,19 +221,25 @@ QVariantList ScriptEngines::getLocal() {
}
QVariantList ScriptEngines::getRunning() {
- const int WINDOWS_DRIVE_LETTER_SIZE = 1;
QVariantList result;
auto runningScripts = getRunningScripts();
foreach(const QString& runningScript, runningScripts) {
QUrl runningScriptURL = QUrl(runningScript);
- if (runningScriptURL.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) {
+ if (!runningScriptURL.isValid()) {
runningScriptURL = QUrl::fromLocalFile(runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded)));
}
QVariantMap resultNode;
resultNode.insert("name", runningScriptURL.fileName());
- resultNode.insert("url", runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded)));
+ QUrl displayURL = expandScriptUrl(QUrl(runningScriptURL));
+ QString displayURLString;
+ if (displayURL.isLocalFile()) {
+ displayURLString = displayURL.toLocalFile();
+ } else {
+ displayURLString = displayURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded));
+ }
+ resultNode.insert("url", displayURLString);
// The path contains the exact path/URL of the script, which also is used in the stopScript function.
- resultNode.insert("path", runningScript);
+ resultNode.insert("path", normalizeScriptURL(runningScript).toString());
resultNode.insert("local", runningScriptURL.isLocalFile());
result.append(resultNode);
}
@@ -213,10 +248,11 @@ QVariantList ScriptEngines::getRunning() {
static const QString SETTINGS_KEY = "Settings";
-static const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js";
void ScriptEngines::loadDefaultScripts() {
- loadScript(DEFAULT_SCRIPTS_JS_URL);
+ QUrl defaultScriptsLoc = defaultScriptsLocation();
+ defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "/scripts/defaultScripts.js");
+ loadScript(defaultScriptsLoc.toString());
}
void ScriptEngines::loadOneScript(const QString& scriptFilename) {
@@ -265,7 +301,7 @@ void ScriptEngines::saveScripts() {
for (auto it = runningScripts.begin(); it != runningScripts.end(); ++it) {
if (getScriptEngine(*it)->isUserLoaded()) {
settings.setArrayIndex(i);
- settings.setValue("script", *it);
+ settings.setValue("script", normalizeScriptURL(*it).toString());
++i;
}
}
@@ -307,11 +343,16 @@ void ScriptEngines::stopAllScripts(bool restart) {
}
}
-bool ScriptEngines::stopScript(const QString& rawScriptUrl, bool restart) {
+bool ScriptEngines::stopScript(const QString& rawScriptURL, bool restart) {
bool stoppedScript = false;
{
+ QUrl scriptURL = normalizeScriptURL(QUrl(rawScriptURL));
+ if (!scriptURL.isValid()) {
+ scriptURL = normalizeScriptURL(QUrl::fromLocalFile(rawScriptURL));
+ }
+ const QString scriptURLString = scriptURL.toString();
+
QReadLocker lock(&_scriptEnginesHashLock);
- const QString scriptURLString = normalizeScriptUrl(rawScriptUrl);
if (_scriptEnginesHash.contains(scriptURLString)) {
ScriptEngine* scriptEngine = _scriptEnginesHash[scriptURLString];
if (restart) {
@@ -344,18 +385,30 @@ void ScriptEngines::reloadAllScripts() {
stopAllScripts(true);
}
-ScriptEngine* ScriptEngines::loadScript(const QString& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, bool activateMainWindow, bool reload) {
+ScriptEngine* ScriptEngines::loadScript(const QUrl& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor,
+ bool activateMainWindow, bool reload) {
if (thread() != QThread::currentThread()) {
ScriptEngine* result { nullptr };
QMetaObject::invokeMethod(this, "loadScript", Qt::BlockingQueuedConnection, Q_RETURN_ARG(ScriptEngine*, result),
- Q_ARG(QString, scriptFilename),
+ Q_ARG(QUrl, scriptFilename),
Q_ARG(bool, isUserLoaded),
Q_ARG(bool, loadScriptFromEditor),
Q_ARG(bool, activateMainWindow),
Q_ARG(bool, reload));
return result;
}
- QUrl scriptUrl(scriptFilename);
+ QUrl scriptUrl;
+ if (!scriptFilename.isValid() ||
+ (scriptFilename.scheme() != "http" &&
+ scriptFilename.scheme() != "https" &&
+ scriptFilename.scheme() != "atp" &&
+ scriptFilename.scheme() != "file")) {
+ // deal with a "url" like c:/something
+ scriptUrl = normalizeScriptURL(QUrl::fromLocalFile(scriptFilename.toString()));
+ } else {
+ scriptUrl = normalizeScriptURL(scriptFilename);
+ }
+
auto scriptEngine = getScriptEngine(scriptUrl.toString());
if (scriptEngine) {
return scriptEngine;
@@ -368,7 +421,7 @@ ScriptEngine* ScriptEngines::loadScript(const QString& scriptFilename, bool isUs
}, Qt::QueuedConnection);
- if (scriptFilename.isNull()) {
+ if (scriptFilename.isEmpty()) {
launchScriptEngine(scriptEngine);
} else {
// connect to the appropriate signals of this script engine
@@ -376,17 +429,17 @@ ScriptEngine* ScriptEngines::loadScript(const QString& scriptFilename, bool isUs
connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError);
// get the script engine object to load the script at the designated script URL
- scriptEngine->loadURL(scriptUrl, reload);
+ scriptEngine->loadURL(QUrl(expandScriptUrl(scriptUrl.toString())), reload);
}
return scriptEngine;
}
-ScriptEngine* ScriptEngines::getScriptEngine(const QString& rawScriptUrl) {
+ScriptEngine* ScriptEngines::getScriptEngine(const QString& rawScriptURL) {
ScriptEngine* result = nullptr;
{
QReadLocker lock(&_scriptEnginesHashLock);
- const QString scriptURLString = normalizeScriptUrl(rawScriptUrl);
+ const QString scriptURLString = normalizeScriptURL(QUrl(rawScriptURL)).toString();
auto it = _scriptEnginesHash.find(scriptURLString);
if (it != _scriptEnginesHash.end()) {
result = it.value();
@@ -396,15 +449,17 @@ ScriptEngine* ScriptEngines::getScriptEngine(const QString& rawScriptUrl) {
}
// FIXME - change to new version of ScriptCache loading notification
-void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptUrl) {
- UserActivityLogger::getInstance().loadedScript(rawScriptUrl);
+void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptURL) {
+ UserActivityLogger::getInstance().loadedScript(rawScriptURL);
ScriptEngine* scriptEngine = qobject_cast(sender());
launchScriptEngine(scriptEngine);
{
QWriteLocker lock(&_scriptEnginesHashLock);
- const QString scriptURLString = normalizeScriptUrl(rawScriptUrl);
+ QUrl url = QUrl(rawScriptURL);
+ QUrl normalized = normalizeScriptURL(url);
+ const QString scriptURLString = normalized.toString();
_scriptEnginesHash.insertMulti(scriptURLString, scriptEngine);
}
emit scriptCountChanged();
@@ -427,11 +482,11 @@ void ScriptEngines::launchScriptEngine(ScriptEngine* scriptEngine) {
}
-void ScriptEngines::onScriptFinished(const QString& rawScriptUrl, ScriptEngine* engine) {
+void ScriptEngines::onScriptFinished(const QString& rawScriptURL, ScriptEngine* engine) {
bool removed = false;
{
QWriteLocker lock(&_scriptEnginesHashLock);
- const QString scriptURLString = normalizeScriptUrl(rawScriptUrl);
+ const QString scriptURLString = normalizeScriptURL(QUrl(rawScriptURL)).toString();
for (auto it = _scriptEnginesHash.find(scriptURLString); it != _scriptEnginesHash.end(); ++it) {
if (it.value() == engine) {
_scriptEnginesHash.erase(it);
diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h
index df60d6ff63..a0d914ec64 100644
--- a/libraries/script-engine/src/ScriptEngines.h
+++ b/libraries/script-engine/src/ScriptEngines.h
@@ -51,7 +51,7 @@ public:
ScriptsModelFilter* scriptsModelFilter() { return &_scriptsModelFilter; };
Q_INVOKABLE void loadOneScript(const QString& scriptFilename);
- Q_INVOKABLE ScriptEngine* loadScript(const QString& scriptFilename = QString(),
+ Q_INVOKABLE ScriptEngine* loadScript(const QUrl& scriptFilename = QString(),
bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false);
Q_INVOKABLE bool stopScript(const QString& scriptHash, bool restart = false);
@@ -96,4 +96,7 @@ protected:
ScriptsModelFilter _scriptsModelFilter;
};
+QUrl normalizeScriptURL(const QUrl& rawScriptURL);
+QUrl expandScriptUrl(const QUrl& normalizedScriptURL);
+
#endif // hifi_ScriptEngine_h
diff --git a/libraries/script-engine/src/ScriptsModel.cpp b/libraries/script-engine/src/ScriptsModel.cpp
index 37b2551f39..9513a333bc 100644
--- a/libraries/script-engine/src/ScriptsModel.cpp
+++ b/libraries/script-engine/src/ScriptsModel.cpp
@@ -13,21 +13,19 @@
#include
#include
#include
+#include
#include
+#include
#include "ScriptEngine.h"
#include "ScriptEngines.h"
#include "ScriptEngineLogging.h"
#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
-#define __LOC__ __FILE__ "("__STR1__(__LINE__)") : Warning Msg: "
+#define __LOC__ __FILE__ "(" __STR1__(__LINE__) ") : Warning Msg: "
-
-static const QString S3_URL = "http://s3.amazonaws.com/hifi-public";
-static const QString PUBLIC_URL = "http://public.highfidelity.io";
static const QString MODELS_LOCATION = "scripts/";
-
static const QString PREFIX_PARAMETER_NAME = "prefix";
static const QString MARKER_PARAMETER_NAME = "marker";
static const QString IS_TRUNCATED_NAME = "IsTruncated";
@@ -63,7 +61,7 @@ ScriptsModel::ScriptsModel(QObject* parent) :
connect(&_fsWatcher, &QFileSystemWatcher::directoryChanged, this, &ScriptsModel::reloadLocalFiles);
reloadLocalFiles();
- reloadRemoteFiles();
+ reloadDefaultFiles();
}
ScriptsModel::~ScriptsModel() {
@@ -140,36 +138,56 @@ void ScriptsModel::updateScriptsLocation(const QString& newPath) {
reloadLocalFiles();
}
-void ScriptsModel::reloadRemoteFiles() {
+void ScriptsModel::reloadDefaultFiles() {
if (!_loadingScripts) {
_loadingScripts = true;
for (int i = _treeNodes.size() - 1; i >= 0; i--) {
TreeNodeBase* node = _treeNodes.at(i);
if (node->getType() == TREE_NODE_TYPE_SCRIPT &&
- static_cast(node)->getOrigin() == SCRIPT_ORIGIN_REMOTE)
+ static_cast(node)->getOrigin() == SCRIPT_ORIGIN_DEFAULT)
{
delete node;
_treeNodes.removeAt(i);
}
}
- requestRemoteFiles();
+ requestDefaultFiles();
}
}
-void ScriptsModel::requestRemoteFiles(QString marker) {
- QUrl url(S3_URL);
- QUrlQuery query;
- query.addQueryItem(PREFIX_PARAMETER_NAME, MODELS_LOCATION);
- if (!marker.isEmpty()) {
- query.addQueryItem(MARKER_PARAMETER_NAME, marker);
- }
- url.setQuery(query);
+void ScriptsModel::requestDefaultFiles(QString marker) {
+ QUrl url(defaultScriptsLocation());
- QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
- QNetworkRequest request(url);
- request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
- QNetworkReply* reply = networkAccessManager.get(request);
- connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));
+ if (url.isLocalFile()) {
+ // if the url indicates a local directory, use QDirIterator
+ // QString localDir = url.toLocalFile() + "/scripts";
+ QString localDir = expandScriptUrl(url).toLocalFile() + "/scripts";
+ int localDirPartCount = localDir.split("/").size();
+ #ifdef Q_OS_WIN
+ localDirPartCount++; // one for the drive letter
+ #endif
+ QDirIterator it(localDir, QStringList() << "*.js", QDir::Files, QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ QUrl jsFullPath = QUrl::fromLocalFile(it.next());
+ QString jsPartialPath = jsFullPath.path().split("/").mid(localDirPartCount).join("/");
+ jsFullPath = normalizeScriptURL(jsFullPath);
+ _treeNodes.append(new TreeNodeScript(jsPartialPath, jsFullPath.toString(), SCRIPT_ORIGIN_DEFAULT));
+ }
+ _loadingScripts = false;
+ } else {
+ // the url indicates http(s), use QNetworkRequest
+ QUrlQuery query;
+ query.addQueryItem(PREFIX_PARAMETER_NAME, MODELS_LOCATION);
+ if (!marker.isEmpty()) {
+ query.addQueryItem(MARKER_PARAMETER_NAME, marker);
+ }
+ url.setQuery(query);
+
+ QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
+ QNetworkRequest request(url);
+ request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
+ QNetworkReply* reply = networkAccessManager.get(request);
+ connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));
+ }
}
void ScriptsModel::downloadFinished() {
@@ -182,8 +200,10 @@ void ScriptsModel::downloadFinished() {
if (!data.isEmpty()) {
finished = parseXML(data);
} else {
- qCDebug(scriptengine) << "Error: Received no data when loading remote scripts";
+ qCDebug(scriptengine) << "Error: Received no data when loading default scripts";
}
+ } else {
+ qDebug() << "Error: when loading default scripts --" << reply->error();
}
reply->deleteLater();
@@ -218,7 +238,11 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) {
xml.readNext();
lastKey = xml.text().toString();
if (jsRegex.exactMatch(xml.text().toString())) {
- _treeNodes.append(new TreeNodeScript(lastKey.mid(MODELS_LOCATION.length()), S3_URL + "/" + lastKey, SCRIPT_ORIGIN_REMOTE));
+ QString localPath = lastKey.split("/").mid(1).join("/");
+ QUrl fullPath = defaultScriptsLocation();
+ fullPath.setPath(fullPath.path() + "/" + lastKey);
+ const QString fullPathStr = normalizeScriptURL(fullPath).toString();
+ _treeNodes.append(new TreeNodeScript(localPath, fullPathStr, SCRIPT_ORIGIN_DEFAULT));
}
}
xml.readNext();
@@ -231,12 +255,12 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) {
// Error handling
if (xml.hasError()) {
- qCDebug(scriptengine) << "Error loading remote scripts: " << xml.errorString();
+ qCDebug(scriptengine) << "Error loading default scripts: " << xml.errorString();
return true;
}
if (truncated) {
- requestRemoteFiles(lastKey);
+ requestDefaultFiles(lastKey);
}
// If this request was not truncated, we are done.
@@ -261,7 +285,9 @@ void ScriptsModel::reloadLocalFiles() {
const QFileInfoList localFiles = _localDirectory.entryInfoList();
for (int i = 0; i < localFiles.size(); i++) {
QFileInfo file = localFiles[i];
- _treeNodes.append(new TreeNodeScript(file.fileName(), file.absoluteFilePath(), SCRIPT_ORIGIN_LOCAL));
+ QString fileName = file.fileName();
+ QUrl absPath = normalizeScriptURL(QUrl::fromLocalFile(file.absoluteFilePath()));
+ _treeNodes.append(new TreeNodeScript(fileName, absPath.toString(), SCRIPT_ORIGIN_LOCAL));
}
rebuildTree();
endResetModel();
diff --git a/libraries/script-engine/src/ScriptsModel.h b/libraries/script-engine/src/ScriptsModel.h
index df9716d43b..e1902f4b23 100644
--- a/libraries/script-engine/src/ScriptsModel.h
+++ b/libraries/script-engine/src/ScriptsModel.h
@@ -21,7 +21,7 @@ class TreeNodeFolder;
enum ScriptOrigin {
SCRIPT_ORIGIN_LOCAL,
- SCRIPT_ORIGIN_REMOTE
+ SCRIPT_ORIGIN_DEFAULT
};
enum TreeNodeType {
@@ -84,10 +84,10 @@ protected slots:
void updateScriptsLocation(const QString& newPath);
void downloadFinished();
void reloadLocalFiles();
- void reloadRemoteFiles();
+ void reloadDefaultFiles();
protected:
- void requestRemoteFiles(QString marker = QString());
+ void requestDefaultFiles(QString marker = QString());
bool parseXML(QByteArray xmlFile);
void rebuildTree();
diff --git a/libraries/shared/src/PathUtils.cpp b/libraries/shared/src/PathUtils.cpp
index 79e83e9b40..410a95a4d5 100644
--- a/libraries/shared/src/PathUtils.cpp
+++ b/libraries/shared/src/PathUtils.cpp
@@ -15,6 +15,7 @@
#include
#include
#include
+#include
#include "PathUtils.h"
@@ -53,3 +54,14 @@ QString findMostRecentFileExtension(const QString& originalFileName, QVector possibleExtensions);
QString findMostRecentFileExtension(const QString& originalFileName, QVector possibleExtensions);
+QUrl defaultScriptsLocation();
+
#endif // hifi_PathUtils_h
diff --git a/libraries/shared/src/ThreadSafeValueCache.h b/libraries/shared/src/ThreadSafeValueCache.h
index e4e78ca3d7..37a1258aa1 100644
--- a/libraries/shared/src/ThreadSafeValueCache.h
+++ b/libraries/shared/src/ThreadSafeValueCache.h
@@ -23,6 +23,7 @@
template
class ThreadSafeValueCache {
public:
+ ThreadSafeValueCache() {}
ThreadSafeValueCache(const T& v) : _value { v } {}
// returns atomic copy of the cached value.
diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp
index e23d8cade6..52eb70134d 100644
--- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp
+++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp
@@ -12,14 +12,19 @@
#include "OculusHelpers.h"
void OculusBaseDisplayPlugin::resetSensors() {
- ovr_RecenterPose(_session);
+ ovr_RecenterTrackingOrigin(_session);
}
-void OculusBaseDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
- auto displayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
- auto trackingState = ovr_GetTrackingState(_session, displayTime, true);
- mat4 headPose = toGlm(trackingState.HeadPose.ThePose);
- _headPoseCache.set(headPose);
+void OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
+ FrameInfo frame;
+ frame.sensorSampleTime = ovr_GetTimeInSeconds();;
+ frame.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
+ auto trackingState = ovr_GetTrackingState(_session, frame.predictedDisplayTime, ovrTrue);
+ frame.headPose = toGlm(trackingState.HeadPose.ThePose);
+
+ _currentRenderFrameInfo.set(frame);
+ Lock lock(_mutex);
+ _frameInfos[frameIndex] = frame;
}
bool OculusBaseDisplayPlugin::isSupported() const {
@@ -42,36 +47,30 @@ bool OculusBaseDisplayPlugin::internalActivate() {
_hmdDesc = ovr_GetHmdDesc(_session);
- _ipd = ovr_GetFloat(_session, OVR_KEY_IPD, _ipd);
-
glm::uvec2 eyeSizes[2];
_viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
+ _ipd = 0;
ovr_for_each_eye([&](ovrEyeType eye) {
_eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye];
ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_session, eye, _eyeFovs[eye]);
ovrMatrix4f ovrPerspectiveProjection =
- ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded);
+ ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL);
_eyeProjections[eye] = toGlm(ovrPerspectiveProjection);
- _eyeOffsets[eye] = glm::translate(mat4(), toGlm(erd.HmdToEyeViewOffset));
+ _eyeOffsets[eye] = glm::translate(mat4(), toGlm(erd.HmdToEyeOffset));
eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_session, eye, erd.Fov, 1.0f));
- _viewScaleDesc.HmdToEyeViewOffset[eye] = erd.HmdToEyeViewOffset;
+ _viewScaleDesc.HmdToEyeOffset[eye] = erd.HmdToEyeOffset;
+ _ipd += glm::abs(glm::length(toGlm(erd.HmdToEyeOffset)));
});
auto combinedFov = _eyeFovs[0];
combinedFov.LeftTan = combinedFov.RightTan = std::max(combinedFov.LeftTan, combinedFov.RightTan);
- _cullingProjection = toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded));
+ _cullingProjection = toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL));
_renderTargetSize = uvec2(
eyeSizes[0].x + eyeSizes[1].x,
std::max(eyeSizes[0].y, eyeSizes[1].y));
- if (!OVR_SUCCESS(ovr_ConfigureTracking(_session,
- ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) {
- logWarning("Failed to attach to sensor device");
- }
-
- // Parent class relies on our _session intialization, so it must come after that.
memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov));
_sceneLayer.Header.Type = ovrLayerType_EyeFov;
_sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h
index d21b0561bc..2259a4ca89 100644
--- a/plugins/oculus/src/OculusBaseDisplayPlugin.h
+++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h
@@ -20,7 +20,8 @@ public:
// Stereo specific methods
virtual void resetSensors() override final;
- virtual void updateHeadPose(uint32_t frameIndex) override;
+ virtual void beginFrameRender(uint32_t frameIndex) override;
+
protected:
void customizeContext() override;
@@ -28,9 +29,8 @@ protected:
void internalDeactivate() override;
protected:
- ovrSession _session;
+ ovrSession _session { nullptr };
ovrGraphicsLuid _luid;
- float _ipd{ OVR_DEFAULT_IPD };
ovrEyeRenderDesc _eyeRenderDescs[2];
ovrFovPort _eyeFovs[2];
ovrHmdDesc _hmdDesc;
diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp
new file mode 100644
index 0000000000..f11ec18b10
--- /dev/null
+++ b/plugins/oculus/src/OculusControllerManager.cpp
@@ -0,0 +1,219 @@
+//
+// OculusControllerManager.cpp
+// input-plugins/src/input-plugins
+//
+// Created by Bradley Austin Davis 2016/03/04.
+// Copyright 2013-2016 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#include "OculusControllerManager.h"
+
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include "OculusHelpers.h"
+
+Q_DECLARE_LOGGING_CATEGORY(oculus)
+
+
+static const QString MENU_PARENT = "Avatar";
+static const QString MENU_NAME = "Oculus Touch Controllers";
+static const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
+
+const QString OculusControllerManager::NAME = "Oculus";
+
+bool OculusControllerManager::isSupported() const {
+ return oculusAvailable();
+}
+
+bool OculusControllerManager::activate() {
+ InputPlugin::activate();
+ if (!_session) {
+ _session = acquireOculusSession();
+ }
+ Q_ASSERT(_session);
+
+ // register with UserInputMapper
+ auto userInputMapper = DependencyManager::get();
+ if (_remote) {
+ userInputMapper->registerDevice(_remote);
+ }
+ if (_touch) {
+ userInputMapper->registerDevice(_touch);
+ }
+ return true;
+}
+
+void OculusControllerManager::deactivate() {
+ InputPlugin::deactivate();
+
+ if (_session) {
+ releaseOculusSession();
+ _session = nullptr;
+ }
+
+ // unregister with UserInputMapper
+ auto userInputMapper = DependencyManager::get();
+ if (_touch) {
+ userInputMapper->removeDevice(_touch->getDeviceID());
+ }
+ if (_remote) {
+ userInputMapper->removeDevice(_remote->getDeviceID());
+ }
+}
+
+void OculusControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) {
+ PerformanceTimer perfTimer("OculusControllerManager::TouchDevice::update");
+
+ if (!OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Touch, &_inputState))) {
+ qCWarning(oculus) << "Unable to read oculus input state";
+ return;
+ }
+
+ if (_touch) {
+ _touch->update(deltaTime, inputCalibrationData, jointsCaptured);
+ }
+ if (_remote) {
+ _remote->update(deltaTime, inputCalibrationData, jointsCaptured);
+ }
+}
+
+void OculusControllerManager::pluginFocusOutEvent() {
+ if (_touch) {
+ _touch->focusOutEvent();
+ }
+ if (_remote) {
+ _remote->focusOutEvent();
+ }
+}
+
+using namespace controller;
+
+static const std::vector> BUTTON_MAP { {
+ { ovrButton_X, X },
+ { ovrButton_Y, Y },
+ { ovrButton_A, A },
+ { ovrButton_B, B },
+ { ovrButton_LThumb, LS },
+ { ovrButton_RThumb, RS },
+ { ovrButton_LShoulder, LB },
+ { ovrButton_RShoulder, RB },
+} };
+
+static const std::vector> TOUCH_MAP { {
+ { ovrTouch_X, LEFT_SECONDARY_THUMB_TOUCH },
+ { ovrTouch_Y, LEFT_SECONDARY_THUMB_TOUCH },
+ { ovrTouch_A, RIGHT_SECONDARY_THUMB_TOUCH },
+ { ovrTouch_B, RIGHT_SECONDARY_THUMB_TOUCH },
+ { ovrTouch_LIndexTrigger, LEFT_PRIMARY_INDEX_TOUCH },
+ { ovrTouch_RIndexTrigger, RIGHT_PRIMARY_INDEX_TOUCH },
+ { ovrTouch_LThumb, LS_TOUCH },
+ { ovrTouch_RThumb, RS_TOUCH },
+ { ovrTouch_LThumbUp, LEFT_THUMB_UP },
+ { ovrTouch_RThumbUp, RIGHT_THUMB_UP },
+ { ovrTouch_LIndexPointing, LEFT_INDEX_POINT },
+ { ovrTouch_RIndexPointing, RIGHT_INDEX_POINT },
+} };
+
+void OculusControllerManager::TouchDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) {
+ _poseStateMap.clear();
+ _buttonPressedMap.clear();
+
+ if (!jointsCaptured) {
+ int numTrackedControllers = 0;
+ static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked & ovrStatus_PositionTracked;
+ auto tracking = ovr_GetTrackingState(_parent._session, 0, false);
+ ovr_for_each_hand([&](ovrHandType hand) {
+ ++numTrackedControllers;
+ if (REQUIRED_HAND_STATUS == (tracking.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) {
+ handlePose(deltaTime, inputCalibrationData, hand, tracking.HandPoses[hand]);
+ }
+ });
+ }
+ using namespace controller;
+ // Axes
+ const auto& inputState = _parent._inputState;
+ _axisStateMap[LX] = inputState.Thumbstick[ovrHand_Left].x;
+ _axisStateMap[LY] = inputState.Thumbstick[ovrHand_Left].y;
+ _axisStateMap[LT] = inputState.IndexTrigger[ovrHand_Left];
+ _axisStateMap[LG] = inputState.HandTrigger[ovrHand_Left];
+
+ _axisStateMap[RX] = inputState.Thumbstick[ovrHand_Right].x;
+ _axisStateMap[RY] = inputState.Thumbstick[ovrHand_Right].y;
+ _axisStateMap[RT] = inputState.IndexTrigger[ovrHand_Right];
+ _axisStateMap[RG] = inputState.HandTrigger[ovrHand_Right];
+
+ // Buttons
+ for (const auto& pair : BUTTON_MAP) {
+ if (inputState.Buttons & pair.first) {
+ _buttonPressedMap.insert(pair.second);
+ }
+ }
+ // Touches
+ for (const auto& pair : TOUCH_MAP) {
+ if (inputState.Touches & pair.first) {
+ _buttonPressedMap.insert(pair.second);
+ }
+ }
+}
+
+void OculusControllerManager::TouchDevice::focusOutEvent() {
+ _axisStateMap.clear();
+ _buttonPressedMap.clear();
+};
+
+void OculusControllerManager::TouchDevice::handlePose(float deltaTime,
+ const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand,
+ const ovrPoseStatef& handPose) {
+ auto poseId = hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND;
+ auto& pose = _poseStateMap[poseId];
+ pose.translation = toGlm(handPose.ThePose.Position);
+ pose.rotation = toGlm(handPose.ThePose.Orientation);
+ pose.angularVelocity = toGlm(handPose.AngularVelocity);
+ pose.velocity = toGlm(handPose.LinearVelocity);
+}
+
+controller::Input::NamedVector OculusControllerManager::TouchDevice::getAvailableInputs() const {
+ using namespace controller;
+ QVector availableInputs{
+ // Trackpad analogs
+ makePair(LX, "LX"),
+ makePair(LY, "LY"),
+ makePair(RX, "RX"),
+ makePair(RY, "RY"),
+ // trigger analogs
+ makePair(LT, "LT"),
+ makePair(RT, "RT"),
+
+ makePair(LB, "LB"),
+ makePair(RB, "RB"),
+
+ makePair(LS, "LS"),
+ makePair(RS, "RS"),
+ makePair(LEFT_HAND, "LeftHand"),
+ makePair(RIGHT_HAND, "RightHand"),
+
+ makePair(LEFT_PRIMARY_THUMB, "LeftPrimaryThumb"),
+ makePair(LEFT_SECONDARY_THUMB, "LeftSecondaryThumb"),
+ makePair(RIGHT_PRIMARY_THUMB, "RightPrimaryThumb"),
+ makePair(RIGHT_SECONDARY_THUMB, "RightSecondaryThumb"),
+ };
+ return availableInputs;
+}
+
+QString OculusControllerManager::TouchDevice::getDefaultMappingConfig() const {
+ static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/touch.json";
+ return MAPPING_JSON;
+}
+
+
+
diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h
new file mode 100644
index 0000000000..fc10dcc73d
--- /dev/null
+++ b/plugins/oculus/src/OculusControllerManager.h
@@ -0,0 +1,81 @@
+//
+// Created by Bradley Austin Davis on 2016/03/04
+// Copyright 2013-2016 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#ifndef hifi__OculusControllerManager
+#define hifi__OculusControllerManager
+
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+
+class OculusControllerManager : public InputPlugin {
+ Q_OBJECT
+public:
+ // Plugin functions
+ bool isSupported() const override;
+ bool isJointController() const override { return true; }
+ const QString& getName() const override { return NAME; }
+
+ bool activate() override;
+ void deactivate() override;
+
+ void pluginFocusOutEvent() override;
+ void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) override;
+
+private:
+ class OculusInputDevice : public controller::InputDevice {
+ public:
+ OculusInputDevice(OculusControllerManager& parent, const QString& name) : controller::InputDevice(name), _parent(parent) {}
+
+ OculusControllerManager& _parent;
+ friend class OculusControllerManager;
+ };
+
+ class RemoteDevice : public OculusInputDevice {
+ public:
+ using Pointer = std::shared_ptr;
+ RemoteDevice(OculusControllerManager& parent) : OculusInputDevice(parent, "Oculus Remote") {}
+
+ controller::Input::NamedVector getAvailableInputs() const override;
+ QString getDefaultMappingConfig() const override;
+ void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) override;
+ void focusOutEvent() override;
+
+ friend class OculusControllerManager;
+ };
+
+ class TouchDevice : public OculusInputDevice {
+ public:
+ using Pointer = std::shared_ptr;
+ TouchDevice(OculusControllerManager& parent) : OculusInputDevice(parent, "Oculus Touch") {}
+
+ controller::Input::NamedVector getAvailableInputs() const override;
+ QString getDefaultMappingConfig() const override;
+ void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) override;
+ void focusOutEvent() override;
+
+ private:
+ void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose);
+ int _trackedControllers { 0 };
+ friend class OculusControllerManager;
+ };
+
+ ovrSession _session { nullptr };
+ ovrInputState _inputState {};
+ RemoteDevice::Pointer _remote;
+ TouchDevice::Pointer _touch;
+ static const QString NAME;
+};
+
+#endif // hifi__OculusControllerManager
diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp
index 8c3a676c61..8078e8d6ec 100644
--- a/plugins/oculus/src/OculusDisplayPlugin.cpp
+++ b/plugins/oculus/src/OculusDisplayPlugin.cpp
@@ -10,6 +10,23 @@
#include "OculusHelpers.h"
const QString OculusDisplayPlugin::NAME("Oculus Rift");
+static ovrPerfHudMode currentDebugMode = ovrPerfHud_Off;
+
+bool OculusDisplayPlugin::internalActivate() {
+ bool result = Parent::internalActivate();
+ currentDebugMode = ovrPerfHud_Off;
+ if (result && _session) {
+ ovr_SetInt(_session, OVR_PERF_HUD_MODE, currentDebugMode);
+ }
+ return result;
+}
+
+void OculusDisplayPlugin::cycleDebugOutput() {
+ if (_session) {
+ currentDebugMode = static_cast((currentDebugMode + 1) % ovrPerfHud_Count);
+ ovr_SetInt(_session, OVR_PERF_HUD_MODE, currentDebugMode);
+ }
+}
void OculusDisplayPlugin::customizeContext() {
Parent::customizeContext();
@@ -48,12 +65,6 @@ void blit(const SrcFbo& srcFbo, const DstFbo& dstFbo) {
});
}
-void OculusDisplayPlugin::updateFrameData() {
- Parent::updateFrameData();
- _sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovrPoseFromGlm(_currentRenderEyePoses[Left]);
- _sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovrPoseFromGlm(_currentRenderEyePoses[Right]);
-}
-
void OculusDisplayPlugin::hmdPresent() {
PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentRenderFrameIndex)
@@ -63,12 +74,15 @@ void OculusDisplayPlugin::hmdPresent() {
}
blit(_compositeFramebuffer, _sceneFbo);
+ _sceneFbo->Commit();
{
+ _sceneLayer.SensorSampleTime = _currentPresentFrameInfo.sensorSampleTime;
+ _sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovrPoseFromGlm(_currentPresentFrameInfo.headPose);
+ _sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovrPoseFromGlm(_currentPresentFrameInfo.headPose);
ovrLayerHeader* layers = &_sceneLayer.Header;
ovrResult result = ovr_SubmitFrame(_session, _currentRenderFrameIndex, &_viewScaleDesc, &layers, 1);
if (!OVR_SUCCESS(result)) {
logWarning("Failed to present");
}
}
- _sceneFbo->Increment();
}
diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h
index 9b6b922f69..e7d7791e7f 100644
--- a/plugins/oculus/src/OculusDisplayPlugin.h
+++ b/plugins/oculus/src/OculusDisplayPlugin.h
@@ -22,12 +22,13 @@ public:
float getTargetFrameRate() override { return TARGET_RATE_Oculus; }
protected:
+ bool internalActivate() override;
void hmdPresent() override;
// FIXME update with Oculus API call once it's available in the SDK
bool isHmdMounted() const override { return true; }
void customizeContext() override;
void uncustomizeContext() override;
- void updateFrameData() override;
+ void cycleDebugOutput() override;
private:
static const QString NAME;
diff --git a/plugins/oculus/src/OculusHelpers.cpp b/plugins/oculus/src/OculusHelpers.cpp
index 170be05952..c9e702ecd0 100644
--- a/plugins/oculus/src/OculusHelpers.cpp
+++ b/plugins/oculus/src/OculusHelpers.cpp
@@ -9,7 +9,10 @@
#include "OculusHelpers.h"
#include
+
#include
+#include
+#include
using Mutex = std::mutex;
using Lock = std::unique_lock;
@@ -38,9 +41,23 @@ void logFatal(const char* what) {
qFatal(error.c_str());
}
+static const QString OCULUS_RUNTIME_PATH { "C:\\Program Files (x86)\\Oculus\\Support\\oculus-runtime" };
+static const QString GOOD_OCULUS_RUNTIME_FILE { OCULUS_RUNTIME_PATH + "\\LibOVRRT64_1.dll" };
+
bool oculusAvailable() {
ovrDetectResult detect = ovr_Detect(0);
- return (detect.IsOculusServiceRunning && detect.IsOculusHMDConnected);
+ if (!detect.IsOculusServiceRunning || !detect.IsOculusHMDConnected) {
+ return false;
+ }
+
+ // HACK Explicitly check for the presence of the 1.0 runtime DLL, and fail if it
+ // doesn't exist
+ if (!QFile(GOOD_OCULUS_RUNTIME_FILE).exists()) {
+ qCWarning(oculus) << "Oculus Runtime detected, but no 1.x DLL present: \"" + GOOD_OCULUS_RUNTIME_FILE + "\"";
+ return false;
+ }
+
+ return true;
}
ovrSession acquireOculusSession() {
@@ -98,9 +115,9 @@ SwapFramebufferWrapper::~SwapFramebufferWrapper() {
destroyColor();
}
-void SwapFramebufferWrapper::Increment() {
- ++color->CurrentIndex;
- color->CurrentIndex %= color->TextureCount;
+void SwapFramebufferWrapper::Commit() {
+ auto result = ovr_CommitTextureSwapChain(_session, color);
+ Q_ASSERT(OVR_SUCCESS(result));
}
void SwapFramebufferWrapper::Resize(const uvec2 & size) {
@@ -114,7 +131,7 @@ void SwapFramebufferWrapper::Resize(const uvec2 & size) {
void SwapFramebufferWrapper::destroyColor() {
if (color) {
- ovr_DestroySwapTextureSet(_session, color);
+ ovr_DestroyTextureSwapChain(_session, color);
color = nullptr;
}
}
@@ -122,13 +139,30 @@ void SwapFramebufferWrapper::destroyColor() {
void SwapFramebufferWrapper::initColor() {
destroyColor();
- if (!OVR_SUCCESS(ovr_CreateSwapTextureSetGL(_session, GL_SRGB8_ALPHA8, size.x, size.y, &color))) {
+ ovrTextureSwapChainDesc desc = {};
+ desc.Type = ovrTexture_2D;
+ desc.ArraySize = 1;
+ desc.Width = size.x;
+ desc.Height = size.y;
+ desc.MipLevels = 1;
+ desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
+ desc.SampleCount = 1;
+ desc.StaticImage = ovrFalse;
+
+ ovrResult result = ovr_CreateTextureSwapChainGL(_session, &desc, &color);
+ if (!OVR_SUCCESS(result)) {
logFatal("Failed to create swap textures");
}
- for (int i = 0; i < color->TextureCount; ++i) {
- ovrGLTexture& ovrTex = (ovrGLTexture&)color->Textures[i];
- glBindTexture(GL_TEXTURE_2D, ovrTex.OGL.TexId);
+ int length = 0;
+ result = ovr_GetTextureSwapChainLength(_session, color, &length);
+ if (!OVR_SUCCESS(result) || !length) {
+ qFatal("Unable to count swap chain textures");
+ }
+ for (int i = 0; i < length; ++i) {
+ GLuint chainTexId;
+ ovr_GetTextureSwapChainBufferGL(_session, color, i, &chainTexId);
+ glBindTexture(GL_TEXTURE_2D, chainTexId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -141,8 +175,11 @@ void SwapFramebufferWrapper::initDone() {
}
void SwapFramebufferWrapper::onBind(oglplus::Framebuffer::Target target) {
- ovrGLTexture& tex = (ovrGLTexture&)(color->Textures[color->CurrentIndex]);
- glFramebufferTexture2D(toEnum(target), GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.OGL.TexId, 0);
+ int curIndex;
+ ovr_GetTextureSwapChainCurrentIndex(_session, color, &curIndex);
+ GLuint curTexId;
+ ovr_GetTextureSwapChainBufferGL(_session, color, curIndex, &curTexId);
+ glFramebufferTexture2D(toEnum(target), GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curTexId, 0);
}
void SwapFramebufferWrapper::onUnbind(oglplus::Framebuffer::Target target) {
diff --git a/plugins/oculus/src/OculusHelpers.h b/plugins/oculus/src/OculusHelpers.h
index e10e058ad2..2f13c45466 100644
--- a/plugins/oculus/src/OculusHelpers.h
+++ b/plugins/oculus/src/OculusHelpers.h
@@ -111,10 +111,10 @@ inline ovrPosef ovrPoseFromGlm(const glm::mat4 & m) {
// then submit it and increment to the next texture.
// The Oculus SDK manages the creation and destruction of
// the textures
-struct SwapFramebufferWrapper : public FramebufferWrapper {
+struct SwapFramebufferWrapper : public FramebufferWrapper {
SwapFramebufferWrapper(const ovrSession& session);
~SwapFramebufferWrapper();
- void Increment();
+ void Commit();
void Resize(const uvec2 & size);
protected:
void initColor() override final;
diff --git a/plugins/oculus/src/OculusProvider.cpp b/plugins/oculus/src/OculusProvider.cpp
index be708db932..e723fa839a 100644
--- a/plugins/oculus/src/OculusProvider.cpp
+++ b/plugins/oculus/src/OculusProvider.cpp
@@ -18,6 +18,7 @@
#include "OculusDisplayPlugin.h"
#include "OculusDebugDisplayPlugin.h"
+#include "OculusControllerManager.h"
class OculusProvider : public QObject, public DisplayProvider, InputProvider
{
@@ -51,8 +52,6 @@ public:
}
virtual InputPluginList getInputPlugins() override {
- // FIXME pending full oculus input API and hardware
-#if 0
static std::once_flag once;
std::call_once(once, [&] {
InputPluginPointer plugin(new OculusControllerManager());
@@ -60,7 +59,6 @@ public:
_inputPlugins.push_back(plugin);
}
});
-#endif
return _inputPlugins;
}
diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp
index 396f55b932..7b9dcc0b7d 100644
--- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp
+++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp
@@ -35,10 +35,14 @@ void OculusLegacyDisplayPlugin::resetSensors() {
ovrHmd_RecenterPose(_hmd);
}
-void OculusLegacyDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
+void OculusLegacyDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
+ FrameInfo frame;
+ frame.predictedDisplayTime = frame.sensorSampleTime = ovr_GetTimeInSeconds();
+ _trackingState = ovrHmd_GetTrackingState(_hmd, frame.predictedDisplayTime);
+ frame.headPose = toGlm(_trackingState.HeadPose.ThePose);
+ _currentRenderFrameInfo.set(frame);
Lock lock(_mutex);
- _trackingState = ovrHmd_GetTrackingState(_hmd, ovr_GetTimeInSeconds());
- _headPoseCache.set(toGlm(_trackingState.HeadPose.ThePose));
+ _frameInfos[frameIndex] = frame;
}
bool OculusLegacyDisplayPlugin::isSupported() const {
diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h
index 187c0681e9..2710ab1335 100644
--- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h
+++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h
@@ -26,7 +26,7 @@ public:
// Stereo specific methods
virtual void resetSensors() override;
- virtual void updateHeadPose(uint32_t frameIndex) override;
+ virtual void beginFrameRender(uint32_t frameIndex) override;
virtual float getTargetFrameRate() override;
diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp
index c4d8b252f0..f968ae440e 100644
--- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp
+++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp
@@ -121,22 +121,23 @@ void OpenVrDisplayPlugin::resetSensors() {
_sensorResetMat = glm::inverse(cancelOutRollAndPitch(m));
}
-void OpenVrDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
+void OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
- float displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
- float frameDuration = 1.f / displayFrequency;
- float vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float);
+ double displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
+ double frameDuration = 1.f / displayFrequency;
+ double vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float);
+ FrameInfo frame;
#if THREADED_PRESENT
// 3 frames of prediction + vsyncToPhotons = 44ms total
- const float NUM_PREDICTION_FRAMES = 3.0f;
- float predictedSecondsFromNow = NUM_PREDICTION_FRAMES * frameDuration + vsyncToPhotons;
+ const double NUM_PREDICTION_FRAMES = 3.0f;
+ frame.predictedDisplayTime = NUM_PREDICTION_FRAMES * frameDuration + vsyncToPhotons;
#else
- float predictedSecondsFromNow = frameDuration + vsyncToPhotons;
+ frame.predictedDisplayTime = frameDuration + vsyncToPhotons;
#endif
vr::TrackedDevicePose_t predictedTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
- _system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, predictedSecondsFromNow, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount);
+ _system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, frame.predictedDisplayTime, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount);
// copy and process predictedTrackedDevicePoses
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
@@ -145,8 +146,11 @@ void OpenVrDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
_trackedDeviceLinearVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vVelocity));
_trackedDeviceAngularVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vAngularVelocity));
}
+ frame.headPose = _trackedDevicePoseMat4[0];
+ _currentRenderFrameInfo.set(frame);
- _headPoseCache.set(_trackedDevicePoseMat4[0]);
+ Lock lock(_mutex);
+ _frameInfos[frameIndex] = frame;
}
void OpenVrDisplayPlugin::hmdPresent() {
diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h
index 022af5b06d..0e1e7c5267 100644
--- a/plugins/openvr/src/OpenVrDisplayPlugin.h
+++ b/plugins/openvr/src/OpenVrDisplayPlugin.h
@@ -27,7 +27,7 @@ public:
// Stereo specific methods
virtual void resetSensors() override;
- virtual void updateHeadPose(uint32_t frameIndex) override;
+ virtual void beginFrameRender(uint32_t frameIndex) override;
protected:
bool internalActivate() override;
diff --git a/server-console/.gitignore b/server-console/.gitignore
index 1624823e80..b293c73eb5 100644
--- a/server-console/.gitignore
+++ b/server-console/.gitignore
@@ -1,5 +1,6 @@
Server\ Console-*/
server-console-*/
+Sandbox-*/
electron-packager/
npm-debug.log
logs/
diff --git a/server-console/CMakeLists.txt b/server-console/CMakeLists.txt
index 9a96b07442..1c6e40c582 100644
--- a/server-console/CMakeLists.txt
+++ b/server-console/CMakeLists.txt
@@ -23,7 +23,7 @@ add_dependencies(${TARGET_NAME} assignment-client domain-server)
# set the packaged console folder depending on platform, so we can copy it
if (APPLE)
- set(PACKAGED_CONSOLE_FOLDER "Server\\ Console-darwin-x64/${CONSOLE_EXEC_NAME}")
+ set(PACKAGED_CONSOLE_FOLDER "Sandbox-darwin-x64/${CONSOLE_EXEC_NAME}")
elseif (WIN32)
set(PACKAGED_CONSOLE_FOLDER "server-console-win32-x64")
elseif (UNIX)
diff --git a/server-console/packager.js b/server-console/packager.js
index bf8ddd68d4..657098d2f4 100644
--- a/server-console/packager.js
+++ b/server-console/packager.js
@@ -23,12 +23,12 @@ var options = {
arch: "x64",
platform: platform,
icon: "resources/" + iconName,
- ignore: "logs|(S|s)erver(\\s|-)(C|c)onsole-\\S+|electron-packager|README.md|CMakeLists.txt|packager.js|.gitignore"
+ ignore: "logs|(S|s)erver(\\s|-)(C|c)onsole-\\S+|(S|s)andbox-\\S+|electron-packager|README.md|CMakeLists.txt|packager.js|.gitignore"
}
const EXEC_NAME = "server-console";
-const SHORT_NAME = "Server Console";
-const FULL_NAME = "High Fidelity Server Console";
+const SHORT_NAME = "Sandbox";
+const FULL_NAME = "High Fidelity Sandbox";
// setup per OS options
if (osType == "Darwin") {
diff --git a/server-console/src/images/console-hf-logo-2x.png b/server-console/src/images/console-hf-logo-2x.png
index 4c0afd6777..420fb18fde 100644
Binary files a/server-console/src/images/console-hf-logo-2x.png and b/server-console/src/images/console-hf-logo-2x.png differ
diff --git a/server-console/src/main.js b/server-console/src/main.js
index 18cffdb81b..26ec2dd536 100644
--- a/server-console/src/main.js
+++ b/server-console/src/main.js
@@ -111,8 +111,8 @@ function shutdown() {
dialog.showMessageBox({
type: 'question',
buttons: ['Yes', 'No'],
- title: 'Stopping Server Console',
- message: 'Quitting will stop your Server Console and your Home domain will no longer be running.\nDo you wish to continue?'
+ title: 'Stopping High Fidelity Sandbox',
+ message: 'Quitting will stop your Sandbox and your Home domain will no longer be running.\nDo you wish to continue?'
}, shutdownCallback);
} else {
shutdownCallback(0);
@@ -212,7 +212,7 @@ var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory)
});
if (shouldQuit) {
- console.warn("Another instance of the Server Console is already running - this instance will quit.");
+ console.warn("Another instance of the Sandbox is already running - this instance will quit.");
app.quit();
return;
}
@@ -237,7 +237,7 @@ function binaryMissingMessage(displayName, executableName, required) {
var message = "The " + displayName + " executable was not found.\n";
if (required) {
- message += "It is required for the Server Console to run.\n\n";
+ message += "It is required for the High Fidelity Sandbox to run.\n\n";
} else {
message += "\n";
}
@@ -250,7 +250,7 @@ function binaryMissingMessage(displayName, executableName, required) {
message += paths.join("\n");
} else {
message += "It is expected to be found beside this executable.\n";
- message += "You may need to re-install the Server Console.";
+ message += "You may need to re-install the High Fidelity Sandbox.";
}
return message;
@@ -347,134 +347,6 @@ function goHomeClicked() {
}
}
-function stackManagerBasePath() {
- var dataPath = 'High Fidelity/Stack Manager/resources';
-
- if (process.platform == "win32") {
- return path.resolve(osHomeDir(), 'AppData/Local', dataPath);
- } else if (process.platform == "darwin") {
- return path.resolve(osHomeDir(), 'Library/Application Support', dataPath);
- } else {
- return ""
- }
-}
-
-function isStackManagerContentPresent() {
- var modelsPath = path.resolve(stackManagerBasePath(), 'models.json.gz');
-
- try {
- var stats = fs.lstatSync(modelsPath);
-
- if (stats.isFile()) {
- console.log("Stack Manager entities file discovered at " + modelsPath)
- // we found a content file
- return true;
- }
- } catch (e) {
- console.log("Stack Manager entities file not found at " + modelsPath);
- }
-}
-
-function promptToMigrateContent() {
- dialog.showMessageBox({
- type: 'question',
- buttons: ['Yes', 'No'],
- title: 'Migrate Content',
- message: 'Are you sure?\n\nThis will stop your home server and replace everything in your home with your content from Stack Manager.'
- }, function(index) {
- if (index == 0) {
- if (homeServer.state != ProcessGroupStates.STOPPED) {
- var stopThenMigrateCallback = function(processGroup) {
- if (isShuttingDown) {
- homeServer.removeListener('state-update', stopThenMigrateCallback);
- } else if (processGroup.state == ProcessGroupStates.STOPPED) {
- performContentMigration();
-
- homeServer.removeListener('state-update', stopThenMigrateCallback);
- }
- };
-
- homeServer.on('state-update', stopThenMigrateCallback);
- homeServer.stop();
-
- } else {
- performContentMigration();
- }
- }
- });
-}
-
-function performContentMigration() {
- // check if there is a models file to migrate
- var modelsPath = path.resolve(stackManagerBasePath(), 'models.json.gz');
-
- try {
- var stats = fs.lstatSync(modelsPath);
- } catch (e) {
- // no entities file
- dialog.showMessageBox({
- type: 'info',
- buttons: ['OK'],
- title: 'Models File Not Found',
- message: 'There is no models file at ' + modelsPath + '\n\nStack Manager content migration can not proceed.'
- }, null);
-
- return;
- }
-
- function showMigrationCompletionDialog(copyError) {
- if (!copyError) {
- // show message for successful migration
- dialog.showMessageBox({
- type: 'info',
- buttons: ['OK'],
- title: 'Migration Complete',
- message: 'Your Stack Manager content has been migrated.\n\nYour home server will now be restarted.'
- }, null);
- } else {
- // show error message for copy fail
- dialog.showMessageBox({
- type: 'info',
- buttons: ['OK'],
- title: 'Migration Failed',
- message: 'There was an error copying your Stack Manager content: ' + copyError + '\n\nPlease try again.'
- }, null);
- }
- }
-
- // we have a models file, try and copy it
- var newModelsPath = path.resolve(getAssignmentClientResourcesDirectory(), 'entities/models.json.gz')
- console.log("Copying Stack Manager entity file from " + modelsPath + " to " + newModelsPath);
-
- try {
- fs.copySync(modelsPath, newModelsPath);
-
- // check if there are any assets to copy
- var oldAssetsPath = path.resolve(stackManagerBasePath(), 'assets');
-
- var assets = fs.readdirSync(oldAssetsPath);
-
- if (assets.length > 0) {
- // assume this means the directory is not empty
- // and that we should copy it
- var newAssetsPath = path.resolve(getAssignmentClientResourcesDirectory(), 'assets');
-
- console.log("Copying Stack Manager assets from " + oldAssetsPath + " to " + newAssetsPath);
-
- // attempt to copy the assets folder
- fs.copySync(oldAssetsPath, newAssetsPath, {
- preserveTimestamps: true
- });
- }
-
- showMigrationCompletionDialog(null);
- } catch (error) {
- showMigrationCompletionDialog(error);
- }
-
- homeServer.start();
-}
-
var logWindow = null;
var labels = {
@@ -530,12 +402,6 @@ var labels = {
shell.openExternal('http://localhost:40100/settings/?action=share')
}
},
- migrateContent: {
- label: 'Migrate Stack Manager Content',
- click: function() {
- promptToMigrateContent();
- }
- },
shuttingDown: {
label: "Shutting down...",
enabled: false
@@ -569,13 +435,6 @@ function buildMenuArray(serverState) {
menuArray.push(labels.share);
menuArray.push(separator);
menuArray.push(labels.quit);
-
- var foundStackManagerContent = isStackManagerContentPresent();
- if (foundStackManagerContent) {
- // add a separator and the stack manager content migration option
- menuArray.splice(menuArray.length - 1, 0, labels.migrateContent, separator);
- }
-
}
@@ -724,7 +583,7 @@ function maybeShowSplash() {
var window = new BrowserWindow({
icon: appIcon,
width: 1600 * zoomFactor,
- height: 737 * zoomFactor,
+ height: 650 * zoomFactor,
center: true,
frame: true,
useContentSize: true,
@@ -770,7 +629,7 @@ app.on('ready', function() {
// Create tray icon
tray = new Tray(trayIcons[ProcessGroupStates.STOPPED]);
- tray.setToolTip('High Fidelity Server Console');
+ tray.setToolTip('High Fidelity Sandbox');
tray.on('click', function() {
tray.popUpContextMenu(tray.menu);
diff --git a/server-console/src/splash.css b/server-console/src/splash.css
index bd3a06cbe3..5a911e3872 100644
--- a/server-console/src/splash.css
+++ b/server-console/src/splash.css
@@ -122,11 +122,6 @@ h2 {
#main-content {
height: 350px;
- border-bottom: 2px solid #F5F6F6;
-}
-
-#existing-resources-area {
- padding-top: 20px;
}
.footer {
@@ -143,4 +138,4 @@ h2 {
input[type="checkbox"] {
-webkit-transform: scale(1.4);
display: inline-block;
-}
\ No newline at end of file
+}
diff --git a/server-console/src/splash.html b/server-console/src/splash.html
index 30868ebb6f..b9947bcbaa 100644
--- a/server-console/src/splash.html
+++ b/server-console/src/splash.html
@@ -23,7 +23,7 @@ High Fidelity is now installed and your Home domain is ready for you to explore.
-You can make your home yours by uploading your own models and scripts, and adding items from the Market.
+You can make your home yours by uploading your own models and scripts.
@@ -67,12 +67,6 @@ You can make your home yours by uploading your own models and scripts, and addin
-