diff --git a/.gitignore b/.gitignore index 44561daabc..0a2bcc6689 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ CMakeFiles/ CMakeScripts/ cmake_install.cmake build*/ +ext/ Makefile *.user @@ -32,10 +33,6 @@ DerivedData interface/external/*/* !interface/external/*/readme.txt -# ignore interface optional resources -interface/resources/visage/* -!interface/resources/visage/tracker.cfg - # Ignore interfaceCache for Linux users interface/interfaceCache/ diff --git a/BUILD.md b/BUILD.md index fe0459e7db..ed3fea5c5f 100644 --- a/BUILD.md +++ b/BUILD.md @@ -19,9 +19,9 @@ The following external projects are optional dependencies. You can indicate to C * [SDL2](https://www.libsdl.org/download-2.0.php) ~> 2.0.3 * Enables game controller support in Interface -The above dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build-ext` directory in each of the subfolders for each external project. +The above dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build/ext` folder in each of the subfolders for each external project. -These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build-ext`. Should you want to force a re-download and re-compile of all externals, just remove the `build-ext` folder. +These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build/ext`. Should you want to force a re-download and re-compile of all externals, just remove the `build/ext` folder. If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DGET_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project. diff --git a/CMakeLists.txt b/CMakeLists.txt index d27774e169..32e79c8443 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,6 +177,7 @@ option(GET_SOXR "Get Soxr library automatically as external project" 1) option(GET_TBB "Get Threading Building Blocks library automatically as external project" 1) option(GET_LIBOVR "Get LibOVR library automatically as external project" 1) option(USE_NSIGHT "Attempt to find the nSight libraries" 1) +option(GET_VHACD "Get V-HACD library automatically as external project" 1) if (WIN32) option(GET_GLEW "Get GLEW library automatically as external project" 1) diff --git a/cmake/externals/vhacd/CMakeLists.txt b/cmake/externals/vhacd/CMakeLists.txt new file mode 100644 index 0000000000..3bd17937d7 --- /dev/null +++ b/cmake/externals/vhacd/CMakeLists.txt @@ -0,0 +1,31 @@ +set(EXTERNAL_NAME vhacd) + +if (ANDROID) + set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") +endif () + +include(ExternalProject) +ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://hifi-public.s3.amazonaws.com/dependencies/v-hacd-master.zip + URL_MD5 3bfc94f8dd3dfbfe8f4dc088f4820b3e + CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= + BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 +) + +ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) + +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + +if (WIN32) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/Debug/VHACD_LIB.lib CACHE FILEPATH "Path to V-HACD debug library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/Release/VHACD_LIB.lib CACHE FILEPATH "Path to V-HACD release library") +else () + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Path to V-HACD debug library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libVHACD.a CACHE FILEPATH "Path to V-HACD release library") +endif () + +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE FILEPATH "Path to V-HACD include directory") diff --git a/cmake/macros/SetupExternalsBinaryDir.cmake b/cmake/macros/SetupExternalsBinaryDir.cmake index 04bd00643c..a118dcf543 100644 --- a/cmake/macros/SetupExternalsBinaryDir.cmake +++ b/cmake/macros/SetupExternalsBinaryDir.cmake @@ -22,11 +22,11 @@ macro(SETUP_EXTERNALS_BINARY_DIR) endif () endif () - set(EXTERNALS_BINARY_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build-ext") + set(EXTERNALS_BINARY_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}/ext") if (ANDROID) set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/android/${CMAKE_GENERATOR_FOLDER_NAME}") else () set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/${CMAKE_GENERATOR_FOLDER_NAME}") endif () -endmacro() \ No newline at end of file +endmacro() diff --git a/cmake/modules/FindVHACD.cmake b/cmake/modules/FindVHACD.cmake index 03e30b41d4..8572387f91 100644 --- a/cmake/modules/FindVHACD.cmake +++ b/cmake/modules/FindVHACD.cmake @@ -19,40 +19,16 @@ include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") hifi_library_search_hints("vhacd") -macro(_FIND_VHACD_LIBRARY _var) - set(_${_var}_NAMES ${ARGN}) - find_library(${_var}_LIBRARY_RELEASE - NAMES ${_${_var}_NAMES} - HINTS - ${VHACD_SEARCH_DIRS} - $ENV{VHACD_ROOT_DIR} - PATH_SUFFIXES lib lib/Release - ) - - find_library(${_var}_LIBRARY_DEBUG - NAMES ${_${_var}_NAMES} - HINTS - ${VHACD_SEARCH_DIRS} - $ENV{VHACD_ROOT_DIR} - PATH_SUFFIXES lib lib/Debug - ) - - select_library_configurations(${_var}) - - mark_as_advanced(${_var}_LIBRARY) - mark_as_advanced(${_var}_LIBRARY) -endmacro() - +find_path(VHACD_INCLUDE_DIRS VHACD.h PATH_SUFFIXES include HINTS ${VHACD_SEARCH_DIRS}) -find_path(VHACD_INCLUDE_DIRS VHACD.h PATH_SUFFIXES include HINTS ${VHACD_SEARCH_DIRS} $ENV{VHACD_ROOT_DIR}) -if(NOT WIN32) -_FIND_VHACD_LIBRARY(VHACD libVHACD.a) -else() -_FIND_VHACD_LIBRARY(VHACD VHACD_LIB) -endif() +find_library(VHACD_LIBRARY_DEBUG NAMES VHACD VHACD_LIB PATH_SUFFIXES lib/Debug HINTS ${VHACD_SEARCH_DIRS}) +find_library(VHACD_LIBRARY_RELEASE NAMES VHACD VHACD_LIB PATH_SUFFIXES lib/Release lib HINTS ${VHACD_SEARCH_DIRS}) + +include(SelectLibraryConfigurations) +select_library_configurations(VHACD) + set(VHACD_LIBRARIES ${VHACD_LIBRARY}) -include(FindPackageHandleStandardArgs) find_package_handle_standard_args(VHACD "Could NOT find VHACD, try to set the path to VHACD root folder in the system variable VHACD_ROOT_DIR or create a directory vhacd in HIFI_LIB_DIR and paste the necessary files there" VHACD_INCLUDE_DIRS VHACD_LIBRARIES) diff --git a/cmake/modules/FindVisage.cmake b/cmake/modules/FindVisage.cmake deleted file mode 100644 index 2b288f4681..0000000000 --- a/cmake/modules/FindVisage.cmake +++ /dev/null @@ -1,68 +0,0 @@ -# -# FindVisage.cmake -# -# Try to find the Visage controller library -# -# You must provide a VISAGE_ROOT_DIR which contains lib and include directories -# -# Once done this will define -# -# VISAGE_FOUND - system found Visage -# VISAGE_INCLUDE_DIRS - the Visage include directory -# VISAGE_LIBRARIES - Link this to use Visage -# -# Created on 2/11/2014 by Andrzej Kapolka -# Copyright 2014 High Fidelity, Inc. -# -# Distributed under the Apache License, Version 2.0. -# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -# - -include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") -hifi_library_search_hints("visage") - -find_path(VISAGE_BASE_INCLUDE_DIR VisageTracker2.h PATH_SUFFIXES include HINTS ${VISAGE_SEARCH_DIRS}) - -if (APPLE) - find_path(VISAGE_XML_INCLUDE_DIR libxml/xmlreader.h HINTS /usr/include/libxml2 ${VISAGE_SEARCH_DIRS}) - find_path(VISAGE_OPENCV_INCLUDE_DIR cv.h PATH_SUFFIXES dependencies/OpenCV_MacOSX/include HINTS ${VISAGE_SEARCH_DIRS}) - find_path(VISAGE_OPENCV2_INCLUDE_DIR opencv.hpp PATH_SUFFIXES dependencies/OpenCV_MacOSX/include/opencv2 HINTS ${VISAGE_SEARCH_DIRS}) - - find_library(VISAGE_CORE_LIBRARY NAME vscore PATH_SUFFIXES lib HINTS ${VISAGE_SEARCH_DIRS}) - find_library(VISAGE_VISION_LIBRARY NAME vsvision PATH_SUFFIXES lib HINTS ${VISAGE_SEARCH_DIRS}) - find_library(VISAGE_OPENCV_LIBRARY NAME OpenCV PATH_SUFFIXES dependencies/OpenCV_MacOSX/lib HINTS ${VISAGE_SEARCH_DIRS}) - - find_library(CoreVideo CoreVideo) - find_library(QTKit QTKit) - find_library(IOKit IOKit) - -elseif (WIN32) - find_path(VISAGE_XML_INCLUDE_DIR libxml/xmlreader.h PATH_SUFFIXES dependencies/libxml2/include HINTS ${VISAGE_SEARCH_DIRS}) - find_path(VISAGE_OPENCV_INCLUDE_DIR opencv/cv.h PATH_SUFFIXES dependencies/OpenCV/include HINTS ${VISAGE_SEARCH_DIRS}) - find_path(VISAGE_OPENCV2_INCLUDE_DIR cv.h PATH_SUFFIXES dependencies/OpenCV/include/opencv HINTS ${VISAGE_SEARCH_DIRS}) - - find_library(VISAGE_CORE_LIBRARY NAME vscore PATH_SUFFIXES lib HINTS ${VISAGE_SEARCH_DIRS}) - find_library(VISAGE_VISION_LIBRARY NAME vsvision PATH_SUFFIXES lib HINTS ${VISAGE_SEARCH_DIRS}) - find_library(VISAGE_OPENCV_LIBRARY NAME opencv_core243 PATH_SUFFIXES dependencies/OpenCV/lib HINTS ${VISAGE_SEARCH_DIRS}) -endif () - -include(FindPackageHandleStandardArgs) - -list(APPEND VISAGE_ARGS_LIST VISAGE_BASE_INCLUDE_DIR VISAGE_XML_INCLUDE_DIR - VISAGE_OPENCV_INCLUDE_DIR VISAGE_OPENCV2_INCLUDE_DIR - VISAGE_CORE_LIBRARY VISAGE_VISION_LIBRARY) - -if (APPLE) - list(APPEND VISAGE_ARGS_LIST CoreVideo QTKit IOKit) -endif () - -find_package_handle_standard_args(Visage DEFAULT_MSG ${VISAGE_ARGS_LIST}) - -set(VISAGE_INCLUDE_DIRS "${VISAGE_XML_INCLUDE_DIR}" "${VISAGE_OPENCV_INCLUDE_DIR}" "${VISAGE_OPENCV2_INCLUDE_DIR}" "${VISAGE_BASE_INCLUDE_DIR}") -set(VISAGE_LIBRARIES "${VISAGE_CORE_LIBRARY}" "${VISAGE_VISION_LIBRARY}") - -if (APPLE) - list(APPEND VISAGE_LIBRARIES "${CoreVideo}" "${QTKit}" "${IOKit}") -endif () - -mark_as_advanced(VISAGE_INCLUDE_DIRS VISAGE_LIBRARIES) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 9ce15b7507..d7cd7ec47d 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -302,6 +302,9 @@ bool DomainServer::didSetupAccountManagerWithAccessToken() { << "at keypath metaverse.access_token or in your ENV at key DOMAIN_SERVER_ACCESS_TOKEN"; return false; } + } else { + qDebug() << "Using access token from DOMAIN_SERVER_ACCESS_TOKEN in env. This overrides any access token present" + << " in the user or master config."; } // give this access token to the AccountManager diff --git a/examples/acScripts/rain.js b/examples/acScripts/rain.js new file mode 100644 index 0000000000..ee8a1e19a6 --- /dev/null +++ b/examples/acScripts/rain.js @@ -0,0 +1,163 @@ +// +// rain.js +// examples +// +// Created by David Rowe on 9 Apr 2015. +// Copyright 2015 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 +// + +var RainSquall = function (properties) { + var // Properties + squallOrigin, + squallRadius, + dropsPerMinute = 60, + dropSize = { x: 0.1, y: 0.1, z: 0.1 }, + dropFallSpeed = 1, // m/s + dropLifetime = 60, // Seconds + dropSpinMax = 0, // Maximum angular velocity per axis; deg/s + debug = false, // Display origin circle; don't use running on Stack Manager + // Other + squallCircle, + SQUALL_CIRCLE_COLOR = { red: 255, green: 0, blue: 0 }, + SQUALL_CIRCLE_ALPHA = 0.5, + SQUALL_CIRCLE_ROTATION = Quat.fromPitchYawRollDegrees(90, 0, 0), + raindropProperties, + RAINDROP_MODEL_URL = "https://s3.amazonaws.com/hifi-public/ozan/Polyworld/Sets/sky/tetrahedron_v1-Faceted2.fbx", + raindropTimer, + raindrops = [], // HACK: Work around raindrops not always getting velocities + raindropVelocities = [], // HACK: Work around raindrops not always getting velocities + DEGREES_TO_RADIANS = Math.PI / 180; + + function processProperties() { + if (!properties.hasOwnProperty("origin")) { + print("ERROR: Rain squall origin must be specified"); + return; + } + squallOrigin = properties.origin; + + if (!properties.hasOwnProperty("radius")) { + print("ERROR: Rain squall radius must be specified"); + return; + } + squallRadius = properties.radius; + + if (properties.hasOwnProperty("dropsPerMinute")) { + dropsPerMinute = properties.dropsPerMinute; + } + + if (properties.hasOwnProperty("dropSize")) { + dropSize = properties.dropSize; + } + + if (properties.hasOwnProperty("dropFallSpeed")) { + dropFallSpeed = properties.dropFallSpeed; + } + + if (properties.hasOwnProperty("dropLifetime")) { + dropLifetime = properties.dropLifetime; + } + + if (properties.hasOwnProperty("dropSpinMax")) { + dropSpinMax = properties.dropSpinMax; + } + + if (properties.hasOwnProperty("debug")) { + debug = properties.debug; + } + + raindropProperties = { + type: "Model", + modelURL: RAINDROP_MODEL_URL, + lifetime: dropLifetime, + dimensions: dropSize, + velocity: { x: 0, y: -dropFallSpeed, z: 0 }, + damping: 0, + angularDamping: 0, + ignoreForCollisions: true + }; + } + + function createRaindrop() { + var angle, + radius, + offset, + drop, + spin = { x: 0, y: 0, z: 0 }, + maxSpinRadians = properties.dropSpinMax * DEGREES_TO_RADIANS, + i; + + // HACK: Work around rain drops not always getting velocities set at creation + for (i = 0; i < raindrops.length; i += 1) { + Entities.editEntity(raindrops[i], raindropVelocities[i]); + } + + angle = Math.random() * 360; + radius = Math.random() * squallRadius; + offset = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, angle, 0), { x: 0, y: -0.1, z: radius }); + raindropProperties.position = Vec3.sum(squallOrigin, offset); + if (properties.dropSpinMax > 0) { + spin = { + x: Math.random() * maxSpinRadians, + y: Math.random() * maxSpinRadians, + z: Math.random() * maxSpinRadians + }; + raindropProperties.angularVelocity = spin; + } + drop = Entities.addEntity(raindropProperties); + + // HACK: Work around rain drops not always getting velocities set at creation + raindrops.push(drop); + raindropVelocities.push({ + velocity: raindropProperties.velocity, + angularVelocity: spin + }); + if (raindrops.length > 5) { + raindrops.shift(); + raindropVelocities.shift(); + } + } + + function setUp() { + if (debug) { + squallCircle = Overlays.addOverlay("circle3d", { + size: { x: 2 * squallRadius, y: 2 * squallRadius }, + color: SQUALL_CIRCLE_COLOR, + alpha: SQUALL_CIRCLE_ALPHA, + solid: true, + visible: debug, + position: squallOrigin, + rotation: SQUALL_CIRCLE_ROTATION + }); + } + + raindropTimer = Script.setInterval(createRaindrop, 60000 / dropsPerMinute); + } + + function tearDown() { + Script.clearInterval(raindropTimer); + if (debug) { + Overlays.deleteOverlay(squallCircle); + } + } + + processProperties(); + setUp(); + Script.scriptEnding.connect(tearDown); + + return { + }; +}; + +var rainSquall1 = new RainSquall({ + origin: { x: 1195, y: 1223, z: 1020 }, + radius: 25, + dropsPerMinute: 120, + dropSize: { x: 0.1, y: 0.1, z: 0.1 }, + dropFallSpeed: 3, + dropLifetime: 30, + dropSpinMax: 180, + debug: false +}); diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index e6c06bb1ae..45cf353620 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -41,7 +41,8 @@ panel.newSlider("Year Time", 0, 364, ); panel.newSlider("Day Time", 0, 24, - function(value) { Scene.setStageDayTime(value); }, + + function(value) { Scene.setStageDayTime(value); panel.update("Light Direction"); }, function() { return Scene.getStageDayTime(); }, function(value) { var hour = Math.floor(value); @@ -72,12 +73,36 @@ function runStageTime() { } Script.setInterval(runStageTime, tickTackPeriod); +panel.newCheckbox("Enable Sun Model", + function(value) { Scene.setStageSunModelEnable((value != 0)); }, + function() { return Scene.isStageSunModelEnabled(); }, + function(value) { return (value); } +); + +panel.newDirectionBox("Light Direction", + function(value) { Scene.setKeyLightDirection(value); }, + function() { return Scene.getKeyLightDirection(); }, + function(value) { return value.x.toFixed(2) + "," + value.y.toFixed(2) + "," + value.z.toFixed(2); } +); + panel.newSlider("Light Intensity", 0.0, 5, - function(value) { Scene.setSunIntensity(value); }, - function() { return Scene.getSunIntensity(); }, + function(value) { Scene.setKeyLightIntensity(value); }, + function() { return Scene.getKeyLightIntensity(); }, function(value) { return (value).toFixed(2); } ); +panel.newSlider("Ambient Light Intensity", 0.0, 1.0, + function(value) { Scene.setKeyLightAmbientIntensity(value); }, + function() { return Scene.getKeyLightAmbientIntensity(); }, + function(value) { return (value).toFixed(2); } +); + +panel.newColorBox("Light Color", + function(value) { Scene.setKeyLightColor(value); }, + function() { return Scene.getKeyLightColor(); }, + function(value) { return (value); } // "(" + value.x + "," = value.y + "," + value.z + ")"; } +); + Controller.mouseMoveEvent.connect(function panelMouseMoveEvent(event) { return panel.mouseMoveEvent(event); }); Controller.mousePressEvent.connect( function panelMousePressEvent(event) { return panel.mousePressEvent(event); }); Controller.mouseReleaseEvent.connect(function(event) { return panel.mouseReleaseEvent(event); }); diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index 205b19c9f9..0182bf8db0 100755 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -12,6 +12,129 @@ // The Slider class Slider = function(x,y,width,thumbSize) { + this.background = Overlays.addOverlay("text", { + backgroundColor: { red: 125, green: 125, blue: 255 }, + x: x, + y: y, + width: width, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true + }); + this.thumb = Overlays.addOverlay("text", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + x: x, + y: y, + width: thumbSize, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); + + + this.thumbSize = thumbSize; + this.thumbHalfSize = 0.5 * thumbSize; + + this.minThumbX = x + this.thumbHalfSize; + this.maxThumbX = x + width - this.thumbHalfSize; + this.thumbX = this.minThumbX; + + this.minValue = 0.0; + this.maxValue = 1.0; + + this.clickOffsetX = 0; + this.isMoving = false; + + this.updateThumb = function() { + thumbTruePos = this.thumbX - 0.5 * this.thumbSize; + Overlays.editOverlay(this.thumb, { x: thumbTruePos } ); + }; + + this.isClickableOverlayItem = function(item) { + return (item == this.thumb) || (item == this.background); + }; + + this.onMouseMoveEvent = function(event) { + if (this.isMoving) { + newThumbX = event.x - this.clickOffsetX; + if (newThumbX < this.minThumbX) { + newThumbX = this.minThumbX; + } + if (newThumbX > this.maxThumbX) { + newThumbX = this.maxThumbX; + } + this.thumbX = newThumbX; + this.updateThumb(); + this.onValueChanged(this.getValue()); + } + }; + + this.onMousePressEvent = function(event, clickedOverlay) { + if (!this.isClickableOverlayItem(clickedOverlay)) { + this.isMoving = false; + return; + } + this.isMoving = true; + var clickOffset = event.x - this.thumbX; + if ((clickOffset > -this.thumbHalfSize) && (clickOffset < this.thumbHalfSize)) { + this.clickOffsetX = clickOffset; + } else { + this.clickOffsetX = 0; + this.thumbX = event.x; + this.updateThumb(); + this.onValueChanged(this.getValue()); + } + + }; + + this.onMouseReleaseEvent = function(event) { + this.isMoving = false; + }; + + // Public members: + + this.setNormalizedValue = function(value) { + if (value < 0.0) { + this.thumbX = this.minThumbX; + } else if (value > 1.0) { + this.thumbX = this.maxThumbX; + } else { + this.thumbX = value * (this.maxThumbX - this.minThumbX) + this.minThumbX; + } + this.updateThumb(); + }; + this.getNormalizedValue = function() { + return (this.thumbX - this.minThumbX) / (this.maxThumbX - this.minThumbX); + }; + + this.setValue = function(value) { + var normValue = (value - this.minValue) / (this.maxValue - this.minValue); + this.setNormalizedValue(normValue); + }; + + this.getValue = function() { + return this.getNormalizedValue() * (this.maxValue - this.minValue) + this.minValue; + }; + + this.onValueChanged = function(value) {}; + + this.destroy = function() { + Overlays.deleteOverlay(this.background); + Overlays.deleteOverlay(this.thumb); + }; + + this.setThumbColor = function(color) { + Overlays.editOverlay(this.thumb, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); + }; + this.setBackgroundColor = function(color) { + Overlays.editOverlay(this.background, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); + }; +} + +// The Checkbox class +Checkbox = function(x,y,width,thumbSize) { this.thumb = Overlays.addOverlay("text", { backgroundColor: { red: 255, green: 255, blue: 255 }, @@ -52,6 +175,10 @@ Slider = function(x,y,width,thumbSize) { Overlays.editOverlay(this.thumb, { x: thumbTruePos } ); }; + this.isClickableOverlayItem = function(item) { + return item == this.background; + }; + this.onMouseMoveEvent = function(event) { if (this.isMoving) { newThumbX = event.x - this.clickOffsetX; @@ -67,7 +194,11 @@ Slider = function(x,y,width,thumbSize) { } }; - this.onMousePressEvent = function(event) { + this.onMousePressEvent = function(event, clickedOverlay) { + if (this.background != clickedOverlay) { + this.isMoving = false; + return; + } this.isMoving = true; var clickOffset = event.x - this.thumbX; if ((clickOffset > -this.thumbHalfSize) && (clickOffset < this.thumbHalfSize)) { @@ -118,6 +249,167 @@ Slider = function(x,y,width,thumbSize) { }; } +// The ColorBox class +ColorBox = function(x,y,width,thumbSize) { + var self = this; + + var slideHeight = thumbSize / 3; + var sliderWidth = width; + this.red = new Slider(x, y, width, slideHeight); + this.green = new Slider(x, y + slideHeight, width, slideHeight); + this.blue = new Slider(x, y + 2 * slideHeight, width, slideHeight); + this.red.setBackgroundColor({x: 1, y: 0, z: 0}); + this.green.setBackgroundColor({x: 0, y: 1, z: 0}); + this.blue.setBackgroundColor({x: 0, y: 0, z: 1}); + + this.isClickableOverlayItem = function(item) { + return this.red.isClickableOverlayItem(item) + || this.green.isClickableOverlayItem(item) + || this.blue.isClickableOverlayItem(item); + }; + + this.onMouseMoveEvent = function(event) { + this.red.onMouseMoveEvent(event); + this.green.onMouseMoveEvent(event); + this.blue.onMouseMoveEvent(event); + }; + + this.onMousePressEvent = function(event, clickedOverlay) { + this.red.onMousePressEvent(event, clickedOverlay); + if (this.red.isMoving) { + return; + } + + this.green.onMousePressEvent(event, clickedOverlay); + if (this.green.isMoving) { + return; + } + + this.blue.onMousePressEvent(event, clickedOverlay); + }; + + this.onMouseReleaseEvent = function(event) { + this.red.onMouseReleaseEvent(event); + this.green.onMouseReleaseEvent(event); + this.blue.onMouseReleaseEvent(event); + }; + + this.setterFromWidget = function(value) { + var color = self.getValue(); + self.onValueChanged(color); + self.updateRGBSliders(color); + }; + + this.red.onValueChanged = this.setterFromWidget; + this.green.onValueChanged = this.setterFromWidget; + this.blue.onValueChanged = this.setterFromWidget; + + this.updateRGBSliders = function(color) { + this.red.setThumbColor({x: color.x, y: 0, z: 0}); + this.green.setThumbColor({x: 0, y: color.y, z: 0}); + this.blue.setThumbColor({x: 0, y: 0, z: color.z}); + }; + + // Public members: + this.setValue = function(value) { + this.red.setValue(value.x); + this.green.setValue(value.y); + this.blue.setValue(value.z); + this.updateRGBSliders(value); + }; + + this.getValue = function() { + var value = {x:this.red.getValue(), y:this.green.getValue(),z:this.blue.getValue()}; + return value; + }; + + this.destroy = function() { + this.red.destroy(); + this.green.destroy(); + this.blue.destroy(); + }; + + this.onValueChanged = function(value) {}; +} + +// The DirectionBox class +DirectionBox = function(x,y,width,thumbSize) { + var self = this; + + var slideHeight = thumbSize / 2; + var sliderWidth = width; + this.yaw = new Slider(x, y, width, slideHeight); + this.pitch = new Slider(x, y + slideHeight, width, slideHeight); + + this.yaw.setThumbColor({x: 1, y: 0, z: 0}); + this.yaw.minValue = -180; + this.yaw.maxValue = +180; + + this.pitch.setThumbColor({x: 0, y: 0, z: 1}); + this.pitch.minValue = -1; + this.pitch.maxValue = +1; + + this.isClickableOverlayItem = function(item) { + return this.yaw.isClickableOverlayItem(item) + || this.pitch.isClickableOverlayItem(item); + }; + + this.onMouseMoveEvent = function(event) { + this.yaw.onMouseMoveEvent(event); + this.pitch.onMouseMoveEvent(event); + }; + + this.onMousePressEvent = function(event, clickedOverlay) { + this.yaw.onMousePressEvent(event, clickedOverlay); + if (this.yaw.isMoving) { + return; + } + this.pitch.onMousePressEvent(event, clickedOverlay); + }; + + this.onMouseReleaseEvent = function(event) { + this.yaw.onMouseReleaseEvent(event); + this.pitch.onMouseReleaseEvent(event); + }; + + this.setterFromWidget = function(value) { + var yawPitch = self.getValue(); + self.onValueChanged(yawPitch); + }; + + this.yaw.onValueChanged = this.setterFromWidget; + this.pitch.onValueChanged = this.setterFromWidget; + + // Public members: + this.setValue = function(direction) { + var flatXZ = Math.sqrt(direction.x * direction.x + direction.z * direction.z); + if (flatXZ > 0.0) { + var flatX = direction.x / flatXZ; + var flatZ = direction.z / flatXZ; + var yaw = Math.acos(flatX) * 180 / Math.PI; + if (flatZ < 0) { + yaw = -yaw; + } + this.yaw.setValue(yaw); + } + this.pitch.setValue(direction.y); + }; + + this.getValue = function() { + var dirZ = this.pitch.getValue(); + var yaw = this.yaw.getValue() * Math.PI / 180; + var cosY = Math.sqrt(1 - dirZ*dirZ); + var value = {x:cosY * Math.cos(yaw), y:dirZ, z: cosY * Math.sin(yaw)}; + return value; + }; + + this.destroy = function() { + this.yaw.destroy(); + this.pitch.destroy(); + }; + + this.onValueChanged = function(value) {}; +} var textFontSize = 16; @@ -167,7 +459,12 @@ function PanelItem(name, setter, getter, displayer, x, y, textWidth, valueWidth, }; this.setterFromWidget = function(value) { setter(value); - Overlays.editOverlay(this.value, {text: this.displayer(getter())}); + // ANd loop back the value after the final setter has been called + var value = getter(); + if (this.widget) { + this.widget.setValue(value); + } + Overlays.editOverlay(this.value, {text: this.displayer(value)}); }; @@ -219,9 +516,9 @@ Panel = function(x, y) { for (var i in this.items) { var widget = this.items[i].widget; - if (clickedOverlay == widget.background) { + if (widget.isClickableOverlayItem(clickedOverlay)) { this.activeWidget = widget; - this.activeWidget.onMousePressEvent(event); + this.activeWidget.onMousePressEvent(event, clickedOverlay); // print("clicked... widget=" + i); break; } @@ -237,21 +534,63 @@ Panel = function(x, y) { this.newSlider = function(name, minValue, maxValue, setValue, getValue, displayValue) { - var sliderItem = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); var slider = new Slider(this.widgetX, this.nextY, widgetWidth, rawHeight); slider.minValue = minValue; slider.maxValue = maxValue; - slider.onValueChanged = function(value) { sliderItem.setterFromWidget(value); }; - sliderItem.widget = slider; - sliderItem.setter(getValue()); - this.items[name] = sliderItem; + item.widget = slider; + item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; + item.setter(getValue()); + this.items[name] = item; this.nextY += rawYDelta; // print("created Item... slider=" + name); }; + this.newCheckbox = function(name, setValue, getValue, displayValue) { + + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); + + var checkbox = new Checkbox(this.widgetX, this.nextY, widgetWidth, rawHeight); + + item.widget = checkbox; + item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; + item.setter(getValue()); + this.items[name] = item; + this.nextY += rawYDelta; + // print("created Item... slider=" + name); + }; + + this.newColorBox = function(name, setValue, getValue, displayValue) { + + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); + + var colorBox = new ColorBox(this.widgetX, this.nextY, widgetWidth, rawHeight); + + item.widget = colorBox; + item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; + item.setter(getValue()); + this.items[name] = item; + this.nextY += rawYDelta; + // print("created Item... colorBox=" + name); + }; + + this.newDirectionBox= function(name, setValue, getValue, displayValue) { + + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); + + var directionBox = new DirectionBox(this.widgetX, this.nextY, widgetWidth, rawHeight); + + item.widget = directionBox; + item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; + item.setter(getValue()); + this.items[name] = item; + this.nextY += rawYDelta; + // print("created Item... directionBox=" + name); + }; + this.destroy = function() { for (var i in this.items) { this.items[i].destroy(); @@ -273,6 +612,15 @@ Panel = function(x, y) { } return null; } + + this.update = function(name) { + var item = this.items[name]; + if (item != null) { + return item.setter(item.getter()); + } + return null; + } + }; diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 5d2fe5ae38..7688036c94 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -170,15 +170,6 @@ foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) endif () endforeach() -# special APPLE modifications for Visage library -if (VISAGE_FOUND AND NOT DISABLE_VISAGE AND APPLE) - add_definitions(-DMAC_OS_X) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment") - find_library(AVFoundation AVFoundation) - find_library(CoreMedia CoreMedia) - target_link_libraries(${TARGET_NAME} ${AVFoundation} ${CoreMedia} ${NEW_STD_LIBRARY}) -endif () - # special OS X modifications for RtMidi library if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI AND APPLE) find_library(CoreMIDI CoreMIDI) diff --git a/interface/external/visage/readme.txt b/interface/external/visage/readme.txt deleted file mode 100644 index 3aff1039dc..0000000000 --- a/interface/external/visage/readme.txt +++ /dev/null @@ -1,14 +0,0 @@ - -Instructions for adding the Visage driver to Interface -Andrzej Kapolka, February 11, 2014 - -1. Copy the Visage sdk folders (lib, include, dependencies) into the interface/external/visage folder. - This readme.txt should be there as well. - -2. Copy the contents of the Visage configuration data folder (visageSDK-MacOS/Samples/MacOSX/data/) to - interface/resources/visage (i.e., so that interface/resources/visage/candide3.wfm is accessible) - -3. Copy the Visage license file to interface/resources/visage/license.vlc. - -4. Delete your build directory, run cmake and build, and you should be all set. - diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 18a325080c..e7f8096e33 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -108,7 +108,6 @@ #include "devices/MIDIManager.h" #include "devices/OculusManager.h" #include "devices/TV3DManager.h" -#include "devices/Visage.h" #include "gpu/Batch.h" #include "gpu/GLBackend.h" @@ -247,7 +246,6 @@ bool setupEssentials(int& argc, char** argv) { auto ambientOcclusionEffect = DependencyManager::set(); auto textureCache = DependencyManager::set(); auto animationCache = DependencyManager::set(); - auto visage = DependencyManager::set(); auto ddeFaceTracker = DependencyManager::set(); auto modelBlender = DependencyManager::set(); auto audioToolBox = DependencyManager::set(); @@ -1834,12 +1832,10 @@ int Application::getMouseDragStartedY() const { FaceTracker* Application::getActiveFaceTracker() { auto faceshift = DependencyManager::get(); - auto visage = DependencyManager::get(); auto dde = DependencyManager::get(); return (dde->isActive() ? static_cast(dde.data()) : - (faceshift->isActive() ? static_cast(faceshift.data()) : - (visage->isActive() ? static_cast(visage.data()) : NULL))); + (faceshift->isActive() ? static_cast(faceshift.data()) : NULL)); } void Application::setActiveFaceTracker() { @@ -1847,10 +1843,11 @@ void Application::setActiveFaceTracker() { DependencyManager::get()->setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift)); #endif #ifdef HAVE_DDE - DependencyManager::get()->setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression)); -#endif -#ifdef HAVE_VISAGE - DependencyManager::get()->updateEnabled(); + bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression); + Menu::getInstance()->getActionForOption(MenuOption::UseAudioForMouth)->setVisible(isUsingDDE); + Menu::getInstance()->getActionForOption(MenuOption::DDEFiltering)->setVisible(isUsingDDE); + Menu::getInstance()->getActionForOption(MenuOption::ResetDDETracking)->setVisible(isUsingDDE); + DependencyManager::get()->setEnabled(isUsingDDE); #endif } @@ -2025,7 +2022,6 @@ void Application::init() { // initialize our face trackers after loading the menu settings DependencyManager::get()->init(); DependencyManager::get()->init(); - DependencyManager::get()->init(); Leapmotion::init(); RealSense::init(); @@ -3144,7 +3140,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs { DependencyManager::get()->setAmbientLightMode(getRenderAmbientLight()); auto skyStage = DependencyManager::get()->getSkyStage(); - DependencyManager::get()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity()); + DependencyManager::get()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity()); DependencyManager::get()->setGlobalAtmosphere(skyStage->getAtmosphere()); PROFILE_RANGE("DeferredLighting"); @@ -3359,7 +3355,6 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { void Application::resetSensors() { DependencyManager::get()->reset(); - DependencyManager::get()->reset(); DependencyManager::get()->reset(); OculusManager::reset(); @@ -3966,6 +3961,9 @@ void Application::stopAllScripts(bool restart) { // stops all current running scripts for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); it != _scriptEnginesHash.constEnd(); it++) { + if (it.value()->isFinished()) { + continue; + } if (restart && it.value()->isUserLoaded()) { connect(it.value(), SIGNAL(finished(const QString&)), SLOT(loadScript(const QString&))); } diff --git a/interface/src/Application.h b/interface/src/Application.h index f510ec7caa..cb54f7dc79 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -213,7 +213,6 @@ public: bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; } FaceTracker* getActiveFaceTracker(); - void setActiveFaceTracker(); QSystemTrayIcon* getTrayIcon() { return _trayIcon; } ApplicationOverlay& getApplicationOverlay() { return _applicationOverlay; } @@ -388,6 +387,8 @@ public slots: void setVSyncEnabled(); void resetSensors(); + void setActiveFaceTracker(); + void aboutApp(); void showEditEntitiesHelp(); diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index 6622a27145..230f4202c8 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -18,6 +18,7 @@ #include #include "DiscoverabilityManager.h" +#include "Menu.h" const Discoverability::Mode DEFAULT_DISCOVERABILITY_MODE = Discoverability::All; @@ -96,4 +97,32 @@ void DiscoverabilityManager::setDiscoverabilityMode(Discoverability::Mode discov emit discoverabilityModeChanged(discoverabilityMode); } -} \ No newline at end of file +} + +void DiscoverabilityManager::setVisibility() { + Menu* menu = Menu::getInstance(); + + if (menu->isOptionChecked(MenuOption::VisibleToEveryone)) { + this->setDiscoverabilityMode(Discoverability::All); + } else if (menu->isOptionChecked(MenuOption::VisibleToFriends)) { + this->setDiscoverabilityMode(Discoverability::Friends); + } else if (menu->isOptionChecked(MenuOption::VisibleToNoOne)) { + this->setDiscoverabilityMode(Discoverability::None); + } else { + qDebug() << "ERROR DiscoverabilityManager::setVisibility() called with unrecognized value."; + } +} + +void DiscoverabilityManager::visibilityChanged(Discoverability::Mode discoverabilityMode) { + Menu* menu = Menu::getInstance(); + + if (discoverabilityMode == Discoverability::All) { + menu->setIsOptionChecked(MenuOption::VisibleToEveryone, true); + } else if (discoverabilityMode == Discoverability::Friends) { + menu->setIsOptionChecked(MenuOption::VisibleToFriends, true); + } else if (discoverabilityMode == Discoverability::None) { + menu->setIsOptionChecked(MenuOption::VisibleToNoOne, true); + } else { + qDebug() << "ERROR DiscoverabilityManager::visibilityChanged() called with unrecognized value."; + } +} diff --git a/interface/src/DiscoverabilityManager.h b/interface/src/DiscoverabilityManager.h index 9daa9408f8..1b5adcdb5d 100644 --- a/interface/src/DiscoverabilityManager.h +++ b/interface/src/DiscoverabilityManager.h @@ -36,6 +36,9 @@ public slots: Discoverability::Mode getDiscoverabilityMode() { return static_cast(_mode.get()); } void setDiscoverabilityMode(Discoverability::Mode discoverabilityMode); + void setVisibility(); + void visibilityChanged(Discoverability::Mode discoverabilityMode); + signals: void discoverabilityModeChanged(Discoverability::Mode discoverabilityMode); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 5d02cf9094..84c810ac0d 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -30,7 +30,6 @@ #include "devices/Faceshift.h" #include "devices/RealSense.h" #include "devices/SixenseManager.h" -#include "devices/Visage.h" #include "MainWindow.h" #include "scripting/MenuScriptingInterface.h" #if defined(Q_OS_MAC) || defined(Q_OS_WIN) @@ -164,21 +163,21 @@ Menu::Menu() { QAction* visibleToEveryone = addCheckableActionToQMenuAndActionHash(visibilityMenu, MenuOption::VisibleToEveryone, 0, discoverabilityManager->getDiscoverabilityMode() == Discoverability::All, - this, SLOT(setVisibility())); + discoverabilityManager.data(), SLOT(setVisibility())); visibilityGroup->addAction(visibleToEveryone); QAction* visibleToFriends = addCheckableActionToQMenuAndActionHash(visibilityMenu, MenuOption::VisibleToFriends, 0, discoverabilityManager->getDiscoverabilityMode() == Discoverability::Friends, - this, SLOT(setVisibility())); + discoverabilityManager.data(), SLOT(setVisibility())); visibilityGroup->addAction(visibleToFriends); QAction* visibleToNoOne = addCheckableActionToQMenuAndActionHash(visibilityMenu, MenuOption::VisibleToNoOne, 0, discoverabilityManager->getDiscoverabilityMode() == Discoverability::None, - this, SLOT(setVisibility())); + discoverabilityManager.data(), SLOT(setVisibility())); visibilityGroup->addAction(visibleToNoOne); connect(discoverabilityManager.data(), &DiscoverabilityManager::discoverabilityModeChanged, - this, &Menu::visibilityChanged); + discoverabilityManager.data(), &DiscoverabilityManager::visibilityChanged); } addActionToQMenuAndActionHash(toolsMenu, @@ -236,17 +235,13 @@ Menu::Menu() { QMenu* viewMenu = addMenu("View"); + addCheckableActionToQMenuAndActionHash(viewMenu, + MenuOption::Fullscreen, #ifdef Q_OS_MAC - addCheckableActionToQMenuAndActionHash(viewMenu, - MenuOption::Fullscreen, Qt::CTRL | Qt::META | Qt::Key_F, - false, - qApp, - SLOT(setFullscreen(bool))); #else - addCheckableActionToQMenuAndActionHash(viewMenu, - MenuOption::Fullscreen, Qt::CTRL | Qt::Key_F, +#endif false, qApp, SLOT(setFullscreen(bool))); @@ -261,12 +256,16 @@ Menu::Menu() { 0, // QML Qt::Key_H, false, qApp, SLOT(cameraMenuChanged())); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, Qt::CTRL | Qt::SHIFT | Qt::Key_H, + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, +#ifdef Q_OS_MAC + Qt::META | Qt::Key_H, +#else + Qt::CTRL | Qt::Key_H, +#endif false, dialogsManager.data(), SLOT(hmdTools(bool))); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0, false, qApp, @@ -376,30 +375,28 @@ Menu::Menu() { QAction* noFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::NoFaceTracking, 0, true, - this, SLOT(setActiveFaceTracker())); + qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(noFaceTracker); #ifdef HAVE_FACESHIFT QAction* faceshiftFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Faceshift, 0, false, - this, SLOT(setActiveFaceTracker())); + qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(faceshiftFaceTracker); #endif #ifdef HAVE_DDE QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFaceRegression, 0, false, - this, SLOT(setActiveFaceTracker())); + qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(ddeFaceTracker); -#endif -#ifdef HAVE_VISAGE - QAction* visageFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Visage, - 0, false, - this, SLOT(setActiveFaceTracker())); - faceTrackerGroup->addAction(visageFaceTracker); #endif } #ifdef HAVE_DDE faceTrackingMenu->addSeparator(); + QAction* useAudioForMouth = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseAudioForMouth, 0, true); + useAudioForMouth->setVisible(false); + QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFiltering, 0, true); + ddeFiltering->setVisible(false); QAction* ddeFaceTrackerReset = addActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::ResetDDETracking, Qt::CTRL | Qt::Key_Apostrophe, DependencyManager::get().data(), SLOT(resetTracking())); @@ -975,37 +972,3 @@ bool Menu::menuItemExists(const QString& menu, const QString& menuitem) { } return false; }; - -void Menu::setVisibility() { - auto discoverabilityManager = DependencyManager::get(); - - if (Menu::getInstance()->isOptionChecked(MenuOption::VisibleToEveryone)) { - discoverabilityManager->setDiscoverabilityMode(Discoverability::All); - } else if (Menu::getInstance()->isOptionChecked(MenuOption::VisibleToFriends)) { - discoverabilityManager->setDiscoverabilityMode(Discoverability::Friends); - } else if (Menu::getInstance()->isOptionChecked(MenuOption::VisibleToNoOne)) { - discoverabilityManager->setDiscoverabilityMode(Discoverability::None); - } else { - qCDebug(interfaceapp) << "ERROR Menu::setVisibility() called with unrecognized value."; - } -} - -void Menu::visibilityChanged(Discoverability::Mode discoverabilityMode) { - if (discoverabilityMode == Discoverability::All) { - setIsOptionChecked(MenuOption::VisibleToEveryone, true); - } else if (discoverabilityMode == Discoverability::Friends) { - setIsOptionChecked(MenuOption::VisibleToFriends, true); - } else if (discoverabilityMode == Discoverability::None) { - setIsOptionChecked(MenuOption::VisibleToNoOne, true); - } else { - qCDebug(interfaceapp) << "ERROR Menu::visibilityChanged() called with unrecognized value."; - } -} - -void Menu::setActiveFaceTracker() { -#ifdef HAVE_DDE - bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression); - Menu::getInstance()->getActionForOption(MenuOption::ResetDDETracking)->setVisible(isUsingDDE); -#endif - qApp->setActiveFaceTracker(); -} diff --git a/interface/src/Menu.h b/interface/src/Menu.h index f580b9204b..0df1b5a83a 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -66,10 +66,6 @@ public slots: bool isOptionChecked(const QString& menuOption) const; void setIsOptionChecked(const QString& menuOption, bool isChecked); -private slots: - void setVisibility(); - void setActiveFaceTracker(); - private: static Menu* _instance; Menu(); @@ -100,8 +96,6 @@ private: int findPositionOfMenuItem(QMenu* menu, const QString& searchMenuItem); int positionBeforeSeparatorIfNeeded(QMenu* menu, int requestedPosition); - void visibilityChanged(Discoverability::Mode discoverabilityMode); - QHash _actionHash; }; @@ -137,6 +131,7 @@ namespace MenuOption { const QString CopyAddress = "Copy Address to Clipboard"; const QString CopyPath = "Copy Path to Clipboard"; const QString DDEFaceRegression = "DDE Face Regression"; + const QString DDEFiltering = "DDE Filtering"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DeleteBookmark = "Delete Bookmark..."; const QString DisableActivityLogger = "Disable Activity Logger"; @@ -192,6 +187,7 @@ namespace MenuOption { const QString OctreeStats = "Entity Statistics"; const QString OffAxisProjection = "Off-Axis Projection"; const QString OnlyDisplayTopTen = "Only Display Top Ten"; + const QString PackageModel = "Package Model..."; const QString Pair = "Pair"; const QString PipelineWarnings = "Log Render Pipeline Warnings"; const QString Preferences = "Preferences..."; @@ -250,8 +246,7 @@ namespace MenuOption { const QString ToolWindow = "Tool Window"; const QString TransmitterDrive = "Transmitter Drive"; const QString TurnWithHead = "Turn using Head"; - const QString PackageModel = "Package Model..."; - const QString Visage = "Visage"; + const QString UseAudioForMouth = "Use Audio for Mouth"; const QString VisibleToEveryone = "Everyone"; const QString VisibleToFriends = "Friends"; const QString VisibleToNoOne = "No one"; diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index b90b693139..b84fd23614 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -76,12 +76,41 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { if (isMine) { MyAvatar* myAvatar = static_cast(_owningAvatar); + // Update audio trailing average for rendering facial animations + const float AUDIO_AVERAGING_SECS = 0.05f; + const float AUDIO_LONG_TERM_AVERAGING_SECS = 30.0f; + _averageLoudness = glm::mix(_averageLoudness, _audioLoudness, glm::min(deltaTime / AUDIO_AVERAGING_SECS, 1.0f)); + + if (_longTermAverageLoudness == -1.0) { + _longTermAverageLoudness = _averageLoudness; + } else { + _longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f)); + } + // Only use face trackers when not playing back a recording. if (!myAvatar->isPlaying()) { FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); _isFaceTrackerConnected = faceTracker != NULL; if (_isFaceTrackerConnected) { _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); + + if (typeid(*faceTracker) == typeid(DdeFaceTracker) + && Menu::getInstance()->isOptionChecked(MenuOption::UseAudioForMouth)) { + + calculateMouthShapes(); + + const int JAW_OPEN_BLENDSHAPE = 21; + const int MMMM_BLENDSHAPE = 34; + const int FUNNEL_BLENDSHAPE = 40; + const int SMILE_LEFT_BLENDSHAPE = 28; + const int SMILE_RIGHT_BLENDSHAPE = 29; + _blendshapeCoefficients[JAW_OPEN_BLENDSHAPE] += _audioJawOpen; + _blendshapeCoefficients[SMILE_LEFT_BLENDSHAPE] += _mouth4; + _blendshapeCoefficients[SMILE_RIGHT_BLENDSHAPE] += _mouth4; + _blendshapeCoefficients[MMMM_BLENDSHAPE] += _mouth2; + _blendshapeCoefficients[FUNNEL_BLENDSHAPE] += _mouth3; + + } } } // Twist the upper body to follow the rotation of the head, but only do this with my avatar, @@ -92,17 +121,6 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { setTorsoTwist(currentTwist + (getFinalYaw() * BODY_FOLLOW_HEAD_FACTOR - currentTwist) * BODY_FOLLOW_HEAD_YAW_RATE); } - // Update audio trailing average for rendering facial animations - const float AUDIO_AVERAGING_SECS = 0.05f; - const float AUDIO_LONG_TERM_AVERAGING_SECS = 30.0f; - _averageLoudness = glm::mix(_averageLoudness, _audioLoudness, glm::min(deltaTime / AUDIO_AVERAGING_SECS, 1.0f)); - - if (_longTermAverageLoudness == -1.0) { - _longTermAverageLoudness = _averageLoudness; - } else { - _longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f)); - } - if (!(_isFaceTrackerConnected || billboard)) { // Update eye saccades const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f; @@ -177,33 +195,7 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { } // use data to update fake Faceshift blendshape coefficients - - const float JAW_OPEN_SCALE = 0.015f; - const float JAW_OPEN_RATE = 0.9f; - const float JAW_CLOSE_RATE = 0.90f; - float audioDelta = sqrtf(glm::max(_averageLoudness - _longTermAverageLoudness, 0.0f)) * JAW_OPEN_SCALE; - if (audioDelta > _audioJawOpen) { - _audioJawOpen += (audioDelta - _audioJawOpen) * JAW_OPEN_RATE; - } else { - _audioJawOpen *= JAW_CLOSE_RATE; - } - _audioJawOpen = glm::clamp(_audioJawOpen, 0.0f, 1.0f); - - // _mouth2 = "mmmm" shape - // _mouth3 = "funnel" shape - // _mouth4 = "smile" shape - const float FUNNEL_PERIOD = 0.985f; - const float FUNNEL_RANDOM_PERIOD = 0.01f; - const float MMMM_POWER = 0.25f; - const float MMMM_PERIOD = 0.91f; - const float MMMM_RANDOM_PERIOD = 0.15f; - const float SMILE_PERIOD = 0.925f; - const float SMILE_RANDOM_PERIOD = 0.05f; - - _mouth3 = glm::mix(_audioJawOpen, _mouth3, FUNNEL_PERIOD + randFloat() * FUNNEL_RANDOM_PERIOD); - _mouth2 = glm::mix(_audioJawOpen * MMMM_POWER, _mouth2, MMMM_PERIOD + randFloat() * MMMM_RANDOM_PERIOD); - _mouth4 = glm::mix(_audioJawOpen, _mouth4, SMILE_PERIOD + randFloat() * SMILE_RANDOM_PERIOD); - + calculateMouthShapes(); DependencyManager::get()->updateFakeCoefficients(_leftEyeBlink, _rightEyeBlink, _browAudioLift, @@ -230,6 +222,34 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { } +void Head::calculateMouthShapes() { + const float JAW_OPEN_SCALE = 0.015f; + const float JAW_OPEN_RATE = 0.9f; + const float JAW_CLOSE_RATE = 0.90f; + float audioDelta = sqrtf(glm::max(_averageLoudness - _longTermAverageLoudness, 0.0f)) * JAW_OPEN_SCALE; + if (audioDelta > _audioJawOpen) { + _audioJawOpen += (audioDelta - _audioJawOpen) * JAW_OPEN_RATE; + } else { + _audioJawOpen *= JAW_CLOSE_RATE; + } + _audioJawOpen = glm::clamp(_audioJawOpen, 0.0f, 1.0f); + + // _mouth2 = "mmmm" shape + // _mouth3 = "funnel" shape + // _mouth4 = "smile" shape + const float FUNNEL_PERIOD = 0.985f; + const float FUNNEL_RANDOM_PERIOD = 0.01f; + const float MMMM_POWER = 0.25f; + const float MMMM_PERIOD = 0.91f; + const float MMMM_RANDOM_PERIOD = 0.15f; + const float SMILE_PERIOD = 0.925f; + const float SMILE_RANDOM_PERIOD = 0.05f; + + _mouth3 = glm::mix(_audioJawOpen, _mouth3, FUNNEL_PERIOD + randFloat() * FUNNEL_RANDOM_PERIOD); + _mouth2 = glm::mix(_audioJawOpen * MMMM_POWER, _mouth2, MMMM_PERIOD + randFloat() * MMMM_RANDOM_PERIOD); + _mouth4 = glm::mix(_audioJawOpen, _mouth4, SMILE_PERIOD + randFloat() * SMILE_RANDOM_PERIOD); +} + void Head::relaxLean(float deltaTime) { // restore rotation, lean to neutral positions const float LEAN_RELAXATION_PERIOD = 0.25f; // seconds diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 5465d74172..d6d4cc1352 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -154,6 +154,7 @@ private: // private methods void renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition); + void calculateMouthShapes(); friend class FaceModel; }; diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index a701160198..50601421c2 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -17,6 +17,8 @@ #include #include +#include + #include "DdeFaceTracker.h" #include "FaceshiftConstants.h" #include "InterfaceLogging.h" @@ -27,9 +29,9 @@ static const QHostAddress DDE_SERVER_ADDR("127.0.0.1"); static const quint16 DDE_SERVER_PORT = 64204; static const quint16 DDE_CONTROL_PORT = 64205; #if defined(Q_OS_WIN) -static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde/dde.exe"; +static const QString DDE_PROGRAM_PATH = "/dde/dde.exe"; #elif defined(Q_OS_MAC) -static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde.app/Contents/MacOS/dde"; +static const QString DDE_PROGRAM_PATH = "/dde.app/Contents/MacOS/dde"; #endif static const QStringList DDE_ARGUMENTS = QStringList() << "--udp=" + DDE_SERVER_ADDR.toString() + ":" + QString::number(DDE_SERVER_PORT) @@ -132,6 +134,8 @@ struct Packet { char name[MAX_NAME_SIZE + 1]; }; +const float STARTING_DDE_MESSAGE_TIME = 0.033f; + DdeFaceTracker::DdeFaceTracker() : DdeFaceTracker(QHostAddress::Any, DDE_SERVER_PORT, DDE_CONTROL_PORT) { @@ -157,11 +161,16 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui _mouthSmileLeftIndex(28), _mouthSmileRightIndex(29), _jawOpenIndex(21), - _previousTranslation(glm::vec3()), - _previousRotation(glm::quat()) + _lastMessageReceived(0), + _averageMessageTime(STARTING_DDE_MESSAGE_TIME), + _lastHeadTranslation(glm::vec3(0.0f)), + _filteredHeadTranslation(glm::vec3(0.0f)), + _lastLeftEyeBlink(0.0f), + _filteredLeftEyeBlink(0.0f), + _lastRightEyeBlink(0.0f), + _filteredRightEyeBlink(0.0f) { _coefficients.resize(NUM_FACESHIFT_BLENDSHAPES); - _previousCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES); _blendshapeCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES); @@ -182,9 +191,10 @@ void DdeFaceTracker::setEnabled(bool enabled) { _udpSocket.bind(_host, _serverPort); } + const char* DDE_EXIT_COMMAND = "exit"; + if (enabled && !_ddeProcess) { // Terminate any existing DDE process, perhaps left running after an Interface crash - const char* DDE_EXIT_COMMAND = "exit"; _udpSocket.writeDatagram(DDE_EXIT_COMMAND, DDE_SERVER_ADDR, _controlPort); qDebug() << "[Info] DDE Face Tracker Starting"; @@ -194,7 +204,8 @@ void DdeFaceTracker::setEnabled(bool enabled) { } if (!enabled && _ddeProcess) { - _ddeProcess->kill(); // More robust than trying to send an "exit" command to DDE + _udpSocket.writeDatagram(DDE_EXIT_COMMAND, DDE_SERVER_ADDR, _controlPort); + delete _ddeProcess; _ddeProcess = NULL; qDebug() << "[Info] DDE Face Tracker Stopped"; } @@ -270,6 +281,8 @@ float DdeFaceTracker::getBlendshapeCoefficient(int index) const { void DdeFaceTracker::decodePacket(const QByteArray& buffer) { if(buffer.size() > MIN_PACKET_SIZE) { + bool isFiltering = Menu::getInstance()->isOptionChecked(MenuOption::DDEFiltering); + Packet packet; int bytesToCopy = glm::min((int)sizeof(packet), buffer.size()); memset(&packet.name, '\n', MAX_NAME_SIZE + 1); @@ -290,13 +303,36 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { translation -= _referenceTranslation; translation /= LEAN_DAMPING_FACTOR; translation.x *= -1; - _headTranslation = (translation + _previousTranslation) / 2.0f; - _previousTranslation = translation; + if (isFiltering) { + glm::vec3 linearVelocity = (translation - _lastHeadTranslation) / _averageMessageTime; + const float LINEAR_VELOCITY_FILTER_STRENGTH = 0.3f; + float velocityFilter = glm::clamp(1.0f - glm::length(linearVelocity) * + LINEAR_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f); + _filteredHeadTranslation = velocityFilter * _filteredHeadTranslation + (1.0f - velocityFilter) * translation; + _lastHeadTranslation = translation; + _headTranslation = _filteredHeadTranslation; + } else { + _headTranslation = translation; + } // Compute relative rotation rotation = glm::inverse(_referenceRotation) * rotation; - _headRotation = (rotation + _previousRotation) / 2.0f; - _previousRotation = rotation; + if (isFiltering) { + glm::quat r = rotation * glm::inverse(_headRotation); + float theta = 2 * acos(r.w); + glm::vec3 angularVelocity; + if (theta > EPSILON) { + float rMag = glm::length(glm::vec3(r.x, r.y, r.z)); + angularVelocity = theta / _averageMessageTime * glm::vec3(r.x, r.y, r.z) / rMag; + } else { + angularVelocity = glm::vec3(0, 0, 0); + } + const float ANGULAR_VELOCITY_FILTER_STRENGTH = 0.3f; + _headRotation = safeMix(_headRotation, rotation, glm::clamp(glm::length(angularVelocity) * + ANGULAR_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f)); + } else { + _headRotation = rotation; + } // Translate DDE coefficients to Faceshift compatible coefficients for (int i = 0; i < NUM_EXPRESSIONS; i += 1) { @@ -305,8 +341,23 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { // Use EyeBlink values to control both EyeBlink and EyeOpen static const float RELAXED_EYE_VALUE = 0.1f; - float leftEye = (_coefficients[_leftBlinkIndex] + _previousCoefficients[_leftBlinkIndex]) / 2.0f; - float rightEye = (_coefficients[_rightBlinkIndex] + _previousCoefficients[_rightBlinkIndex]) / 2.0f; + float leftEye = _coefficients[_leftBlinkIndex]; + float rightEye = _coefficients[_rightBlinkIndex]; + if (isFiltering) { + const float BLINK_VELOCITY_FILTER_STRENGTH = 0.3f; + + float velocity = fabs(leftEye - _lastLeftEyeBlink) / _averageMessageTime; + float velocityFilter = glm::clamp(velocity * BLINK_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f); + _filteredLeftEyeBlink = velocityFilter * leftEye + (1.0f - velocityFilter) * _filteredLeftEyeBlink; + _lastLeftEyeBlink = leftEye; + leftEye = _filteredLeftEyeBlink; + + velocity = fabs(rightEye - _lastRightEyeBlink) / _averageMessageTime; + velocityFilter = glm::clamp(velocity * BLINK_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f); + _filteredRightEyeBlink = velocityFilter * rightEye + (1.0f - velocityFilter) * _filteredRightEyeBlink; + _lastRightEyeBlink = rightEye; + rightEye = _filteredRightEyeBlink; + } if (leftEye > RELAXED_EYE_VALUE) { _coefficients[_leftBlinkIndex] = leftEye - RELAXED_EYE_VALUE; _coefficients[_leftEyeOpenIndex] = 0.0f; @@ -341,10 +392,18 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { // Scale all coefficients for (int i = 0; i < NUM_EXPRESSIONS; i += 1) { _blendshapeCoefficients[i] - = glm::clamp(DDE_COEFFICIENT_SCALES[i] * (_coefficients[i] + _previousCoefficients[i]) / 2.0f, 0.0f, 1.0f); - _previousCoefficients[i] = _coefficients[i]; + = glm::clamp(DDE_COEFFICIENT_SCALES[i] * _coefficients[i], 0.0f, 1.0f); } + // Calculate average frame time + const float FRAME_AVERAGING_FACTOR = 0.99f; + quint64 usecsNow = usecTimestampNow(); + if (_lastMessageReceived != 0) { + _averageMessageTime = FRAME_AVERAGING_FACTOR * _averageMessageTime + + (1.0f - FRAME_AVERAGING_FACTOR) * (float)(usecsNow - _lastMessageReceived) / 1000000.0f; + } + _lastMessageReceived = usecsNow; + } else { qCDebug(interfaceapp) << "[Error] DDE Face Tracker Decode Error"; } diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 490020e511..aa3e9f3b81 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -101,10 +101,14 @@ private: QVector _coefficients; - // Previous values for simple smoothing - glm::vec3 _previousTranslation; - glm::quat _previousRotation; - QVector _previousCoefficients; + quint64 _lastMessageReceived; + float _averageMessageTime; + glm::vec3 _lastHeadTranslation; + glm::vec3 _filteredHeadTranslation; + float _lastLeftEyeBlink; + float _filteredLeftEyeBlink; + float _lastRightEyeBlink; + float _filteredRightEyeBlink; }; #endif // hifi_DdeFaceTracker_h \ No newline at end of file diff --git a/interface/src/devices/FaceTracker.h b/interface/src/devices/FaceTracker.h index 362099aaf6..db6fdd74b9 100644 --- a/interface/src/devices/FaceTracker.h +++ b/interface/src/devices/FaceTracker.h @@ -18,7 +18,7 @@ #include #include -/// Base class for face trackers (Faceshift, Visage, DDE). +/// Base class for face trackers (Faceshift, DDE). class FaceTracker : public QObject { Q_OBJECT diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp deleted file mode 100644 index 010b872bc6..0000000000 --- a/interface/src/devices/Visage.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// -// Visage.cpp -// interface/src/devices -// -// Created by Andrzej Kapolka on 2/11/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - - -#include -#include -#include -#include -#include - -#include "Application.h" -#include "Faceshift.h" -#include "Visage.h" - -// this has to go after our normal includes, because its definition of HANDLE conflicts with Qt's -#ifdef HAVE_VISAGE -#include -#endif - -namespace VisageSDK { -#ifdef WIN32 - void __declspec(dllimport) initializeLicenseManager(char* licenseKeyFileName); -#else - void initializeLicenseManager(char* licenseKeyFileName); -#endif -} - -using namespace VisageSDK; - -const glm::vec3 DEFAULT_HEAD_ORIGIN(0.0f, 0.0f, 0.7f); - -Visage::Visage() : - _enabled(false), - _headOrigin(DEFAULT_HEAD_ORIGIN) { - -#ifdef HAVE_VISAGE -#ifdef WIN32 - QByteArray licensePath = PathUtils::resourcesPath().toLatin1() + "visage"; -#else - QByteArray licensePath = PathUtils::resourcesPath().toLatin1() + "visage/license.vlc"; -#endif - initializeLicenseManager(licensePath.data()); - _tracker = new VisageTracker2(PathUtils::resourcesPath().toLatin1() + "visage/tracker.cfg"); - _data = new FaceData(); -#endif -} - -Visage::~Visage() { -#ifdef HAVE_VISAGE - _tracker->stop(); - // deleting the tracker crashes windows; disable for now - //delete _tracker; - delete _data; -#endif -} - -#ifdef HAVE_VISAGE -static int leftEyeBlinkIndex = 0; -static int rightEyeBlinkIndex = 1; - -static QMultiHash > createActionUnitNameMap() { - QMultiHash > blendshapeMap; - blendshapeMap.insert("JawFwd", QPair("au_jaw_z_push", 1.0f)); - blendshapeMap.insert("JawLeft", QPair("au_jaw_x_push", 1.0f)); - blendshapeMap.insert("JawOpen", QPair("au_jaw_drop", 1.0f)); - blendshapeMap.insert("LipsLowerDown", QPair("au_lower_lip_drop", 1.0f)); - blendshapeMap.insert("LipsUpperOpen", QPair("au_upper_lip_raiser", 1.0f)); - blendshapeMap.insert("LipsStretch_R", QPair("au_lip_stretcher_left", 0.5f)); - blendshapeMap.insert("MouthSmile_L", QPair("au_lip_corner_depressor", -1.0f)); - blendshapeMap.insert("MouthSmile_R", QPair("au_lip_corner_depressor", -1.0f)); - blendshapeMap.insert("BrowsU_R", QPair("au_left_outer_brow_raiser", 1.0f)); - blendshapeMap.insert("BrowsU_C", QPair("au_left_inner_brow_raiser", 1.0f)); - blendshapeMap.insert("BrowsD_R", QPair("au_left_brow_lowerer", 1.0f)); - blendshapeMap.insert("EyeBlink_L", QPair("au_leye_closed", 1.0f)); - blendshapeMap.insert("EyeBlink_R", QPair("au_reye_closed", 1.0f)); - blendshapeMap.insert("EyeOpen_L", QPair("au_upper_lid_raiser", 1.0f)); - blendshapeMap.insert("EyeOpen_R", QPair("au_upper_lid_raiser", 1.0f)); - blendshapeMap.insert("LipLowerOpen", QPair("au_lower_lip_x_push", 1.0f)); - blendshapeMap.insert("LipsStretch_L", QPair("au_lip_stretcher_right", 0.5f)); - blendshapeMap.insert("BrowsU_L", QPair("au_right_outer_brow_raiser", 1.0f)); - blendshapeMap.insert("BrowsU_C", QPair("au_right_inner_brow_raiser", 1.0f)); - blendshapeMap.insert("BrowsD_L", QPair("au_right_brow_lowerer", 1.0f)); - - QMultiHash > actionUnitNameMap; - for (int i = 0;; i++) { - QByteArray blendshape = FACESHIFT_BLENDSHAPES[i]; - if (blendshape.isEmpty()) { - break; - } - if (blendshape == "EyeBlink_L") { - leftEyeBlinkIndex = i; - - } else if (blendshape == "EyeBlink_R") { - rightEyeBlinkIndex = i; - } - for (QMultiHash >::const_iterator it = blendshapeMap.constFind(blendshape); - it != blendshapeMap.constEnd() && it.key() == blendshape; it++) { - actionUnitNameMap.insert(it.value().first, QPair(i, it.value().second)); - } - } - - return actionUnitNameMap; -} - -static const QMultiHash >& getActionUnitNameMap() { - static QMultiHash > actionUnitNameMap = createActionUnitNameMap(); - return actionUnitNameMap; -} -#endif - - -#ifdef HAVE_VISAGE -const float TRANSLATION_SCALE = 20.0f; -void Visage::init() { - connect(DependencyManager::get().data(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled())); - updateEnabled(); -} - -void Visage::update(float deltaTime) { - if (!isActive()) { - return; - } - FaceTracker::update(deltaTime); - - _headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2])); - _headTranslation = (glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) - - _headOrigin) * TRANSLATION_SCALE; - _estimatedEyePitch = glm::degrees(-_data->gazeDirection[1]); - _estimatedEyeYaw = glm::degrees(-_data->gazeDirection[0]); - - if (_actionUnitIndexMap.isEmpty()) { - int maxIndex = -1; - for (int i = 0; i < _data->actionUnitCount; i++) { - QByteArray name = _data->actionUnitsNames[i]; - for (QMultiHash >::const_iterator it = getActionUnitNameMap().constFind(name); - it != getActionUnitNameMap().constEnd() && it.key() == name; it++) { - _actionUnitIndexMap.insert(i, it.value()); - maxIndex = qMax(maxIndex, it.value().first); - } - } - _blendshapeCoefficients.resize(maxIndex + 1); - } - - qFill(_blendshapeCoefficients.begin(), _blendshapeCoefficients.end(), 0.0f); - for (int i = 0; i < _data->actionUnitCount; i++) { - if (!_data->actionUnitsUsed[i]) { - continue; - } - for (QMultiHash >::const_iterator it = _actionUnitIndexMap.constFind(i); - it != _actionUnitIndexMap.constEnd() && it.key() == i; it++) { - _blendshapeCoefficients[it.value().first] += _data->actionUnits[i] * it.value().second; - } - } - _blendshapeCoefficients[leftEyeBlinkIndex] = 1.0f - _data->eyeClosure[1]; - _blendshapeCoefficients[rightEyeBlinkIndex] = 1.0f - _data->eyeClosure[0]; -} - -void Visage::reset() { - _headOrigin += _headTranslation / TRANSLATION_SCALE; -} -#endif - -void Visage::updateEnabled() { - setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) && - !(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && - DependencyManager::get()->isConnectedOrConnecting()) && - !Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression)); -} - -void Visage::setEnabled(bool enabled) { -#ifdef HAVE_VISAGE - if (_enabled == enabled) { - return; - } - if ((_enabled = enabled)) { - _tracker->trackFromCam(); - } else { - _tracker->stop(); - } -#endif -} diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h deleted file mode 100644 index 3ff1ea8c27..0000000000 --- a/interface/src/devices/Visage.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// Visage.h -// interface/src/devices -// -// Created by Andrzej Kapolka on 2/11/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Visage_h -#define hifi_Visage_h - -#include -#include -#include - -#include - -#include "FaceTracker.h" - -namespace VisageSDK { - class VisageTracker2; - struct FaceData; -} - -/// Handles input from the Visage webcam feature tracking software. -class Visage : public FaceTracker, public Dependency { - Q_OBJECT - SINGLETON_DEPENDENCY - -public: -#ifdef HAVE_VISAGE - virtual void init(); - virtual void update(float deltaTime); - virtual void reset(); - - virtual bool isActive() const { return _tracker->getTrackingData(_data) == TRACK_STAT_OK; } - virtual bool isTracking() const { return isActive(); } -#endif - -public slots: - void updateEnabled(); - -private: - Visage(); - virtual ~Visage(); - -#ifdef HAVE_VISAGE - VisageSDK::VisageTracker2* _tracker; - VisageSDK::FaceData* _data; - QMultiHash > _actionUnitIndexMap; -#endif - - void setEnabled(bool enabled); - - bool _enabled; - - glm::vec3 _headOrigin; -}; - -#endif // hifi_Visage_h diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index b9b2f24034..25ea9ef8e1 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1705,7 +1705,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, material._material->setDiffuse(material.diffuse); material._material->setSpecular(material.specular); material._material->setShininess(material.shininess); - material._material->setOpacity(material.opacity); + + if (material.opacity <= 0.0f) { + material._material->setOpacity(1.0f); + } else { + material._material->setOpacity(material.opacity); + } materials.insert(material.id, material); diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index ea77412140..e8c01c68aa 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -64,6 +64,10 @@ void Light::setIntensity(float intensity) { editSchema()._intensity = intensity; } +void Light::setAmbientIntensity(float intensity) { + editSchema()._ambientIntensity = intensity; +} + void Light::setMaximumRadius(float radius) { if (radius <= 0.f) { radius = 1.0f; diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index 8f6c663668..30e3a8edad 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -244,6 +244,10 @@ public: void setShowContour(float show); float getShowContour() const { return getSchema()._control.w; } + // If the light has an ambient (Indirect) component, then the Ambientintensity can be used to control its contribution to the lighting + void setAmbientIntensity(float intensity); + float getAmbientIntensity() const { return getSchema()._ambientIntensity; } + // Spherical Harmonics storing the Ambien lighting approximation used for the Sun typed light void setAmbientSphere(const SphericalHarmonics& sphere) { _ambientSphere = sphere; } const SphericalHarmonics& getAmbientSphere() const { return _ambientSphere; } @@ -254,14 +258,14 @@ public: public: Vec4 _position{0.0f, 0.0f, 0.0f, 1.0f}; Vec3 _direction{0.0f, 0.0f, -1.0f}; - float _spare0{0.0f}; + float _ambientIntensity{0.0f}; Color _color{1.0f}; float _intensity{1.0f}; Vec4 _attenuation{1.0f}; Vec4 _spot{0.0f, 0.0f, 0.0f, 3.0f}; Vec4 _shadow{0.0f}; - Vec4 _control{0.0f}; + Vec4 _control{0.0f, 0.0f, 0.0f, 0.0f}; Schema() {} }; diff --git a/libraries/model/src/model/Light.slh b/libraries/model/src/model/Light.slh index 41c6e075cf..1aaf0e8327 100644 --- a/libraries/model/src/model/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -27,6 +27,7 @@ vec3 getLightDirection(Light l) { return l._direction.xyz; } // direction is -Z vec3 getLightColor(Light l) { return l._color.rgb; } float getLightIntensity(Light l) { return l._color.w; } +float getLightAmbientIntensity(Light l) { return l._direction.w; } float evalLightAttenuation(Light l, float r) { float d = max(r - l._attenuation.x, 0.0); diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index b72aa16497..77bc3f03f0 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -203,6 +203,7 @@ SunSkyStage::SunSkyStage() : _sunLight->setType(Light::SUN); setSunIntensity(1.0f); + setSunAmbientIntensity(0.5f); setSunColor(Vec3(1.0f, 1.0f, 1.0f)); // Default origin location is a special place in the world... @@ -249,12 +250,26 @@ void SunSkyStage::setOriginLocation(float longitude, float latitude, float altit invalidate(); } +void SunSkyStage::setSunModelEnable(bool isEnabled) { + _sunModelEnable = isEnabled; + invalidate(); +} + void SunSkyStage::setSunColor(const Vec3& color) { _sunLight->setColor(color); } void SunSkyStage::setSunIntensity(float intensity) { _sunLight->setIntensity(intensity); } +void SunSkyStage::setSunAmbientIntensity(float intensity) { + _sunLight->setAmbientIntensity(intensity); +} + +void SunSkyStage::setSunDirection(const Vec3& direction) { + if (!isSunModelEnabled()) { + _sunLight->setDirection(direction); + } +} // THe sun declinaison calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun double evalSunDeclinaison(double dayNumber) { @@ -271,19 +286,19 @@ void SunSkyStage::updateGraphicsObject() const { // And update the sunLAtitude as the declinaison depending of the time of the year _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); - Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); - _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); + if (isSunModelEnabled()) { + Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); + _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); - double originAlt = _earthSunModel.getAltitude(); - _sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f)); + double originAlt = _earthSunModel.getAltitude(); + _sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f)); + } static int firstTime = 0; if (firstTime == 0) { firstTime++; gpu::Shader::makeProgram(*(_skyPipeline->getProgram())); - } - } void SunSkyStage::setSkybox(const SkyboxPointer& skybox) { diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index 30c96259ca..237265ed12 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -203,12 +203,22 @@ public: float getOriginLongitude() const { return _earthSunModel.getLongitude(); } float getOriginSurfaceAltitude() const { return _earthSunModel.getAltitude(); } + // Enable / disable the effect of the time and location on the sun direction and color + void setSunModelEnable(bool isEnabled); + bool isSunModelEnabled() const { return _sunModelEnable; } + // Sun properties void setSunColor(const Vec3& color); const Vec3& getSunColor() const { return getSunLight()->getColor(); } void setSunIntensity(float intensity); float getSunIntensity() const { return getSunLight()->getIntensity(); } + void setSunAmbientIntensity(float intensity); + float getSunAmbientIntensity() const { return getSunLight()->getAmbientIntensity(); } + // The sun direction is expressed in the world space + void setSunDirection(const Vec3& direction); + const Vec3& getSunDirection() const { return getSunLight()->getDirection(); } + LightPointer getSunLight() const { valid(); return _sunLight; } AtmospherePointer getAtmosphere() const { valid(); return _atmosphere; } @@ -223,10 +233,10 @@ protected: gpu::PipelinePointer _skyPipeline; - float _dayTime; - int _yearTime; - + float _dayTime = 12.0f; + int _yearTime = 0; mutable EarthSunModel _earthSunModel; + bool _sunModelEnable = true; mutable bool _invalid = true; void invalidate() const { _invalid = true; } diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 1f1ada5592..2830a13ca7 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -366,7 +366,7 @@ void AccountManager::setAccessTokenForCurrentAuthURL(const QString& accessToken) OAuthAccessToken newOAuthToken; newOAuthToken.token = accessToken; - qCDebug(networking) << "Setting new account manager access token to" << accessToken; + qCDebug(networking) << "Setting new account manager access token. F2C:" << accessToken.left(2) << "L2C:" << accessToken.right(2); _accountInfo.setAccessToken(newOAuthToken); } diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index fd4d447b25..9b2bb87b80 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -12,4 +12,16 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) +if (WIN32) + if (USE_NSIGHT) + # try to find the Nsight package and add it to the build if we find it + find_package(NSIGHT) + if (NSIGHT_FOUND) + include_directories(${NSIGHT_INCLUDE_DIRS}) + add_definitions(-DNSIGHT_FOUND) + target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}") + endif () + endif() +endif (WIN32) + link_hifi_libraries(animation fbx shared gpu) \ No newline at end of file diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index ecb1f503c7..cbf7c31d1f 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -66,7 +66,7 @@ vec3 evalAmbienGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec4 fragEyeVector = invViewMat * vec4(-position, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - vec3 color = diffuse.rgb * getLightColor(light) * 0.5; + vec3 color = diffuse.rgb * getLightColor(light) * getLightAmbientIntensity(light); vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); @@ -83,7 +83,7 @@ vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 no vec3 fragEyeDir = normalize(fragEyeVector.xyz); vec3 ambientNormal = fragNormal.xyz; - vec3 color = diffuse.rgb * 0.5 * evalSphericalLight(ambientSphere, ambientNormal).xyz; + vec3 color = diffuse.rgb * evalSphericalLight(ambientSphere, ambientNormal).xyz * getLightAmbientIntensity(light); vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); @@ -112,7 +112,7 @@ vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, ve vec3 diffuseLight = lightAttenuation * lightmap; // ambient is a tiny percentage of the lightmap and only when in the shadow - vec3 ambientLight = (1 - lightAttenuation) * 0.5 * lightmap; + vec3 ambientLight = (1 - lightAttenuation) * lightmap * getLightAmbientIntensity(light); return diffuse * (ambientLight + diffuseLight); } diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 440f75e32e..bddb1815bf 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -554,11 +554,12 @@ void DeferredLightingEffect::setAmbientLightMode(int preset) { } } -void DeferredLightingEffect::setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity) { +void DeferredLightingEffect::setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity, float ambientIntensity) { auto light = _allocatedLights.front(); light->setDirection(direction); light->setColor(diffuse); light->setIntensity(intensity); + light->setAmbientIntensity(ambientIntensity); } void DeferredLightingEffect::setGlobalSkybox(const model::SkyboxPointer& skybox) { diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 6d0d131029..0d3d370fd4 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -73,7 +73,7 @@ public: // update global lighting void setAmbientLightMode(int preset); - void setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity); + void setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity, float ambientIntensity); void setGlobalAtmosphere(const model::AtmospherePointer& atmosphere) { _atmosphere = atmosphere; } void setGlobalSkybox(const model::SkyboxPointer& skybox); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 0a36ffa76a..4bc69f1bea 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -244,13 +244,6 @@ void Model::initJointTransforms() { void Model::init() { if (_renderPipelineLib.empty()) { - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1)); - slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2)); - slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3)); - // Vertex shaders auto modelVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_vert))); auto modelNormalMapVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_normal_map_vert))); @@ -291,10 +284,24 @@ void Model::init() { RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), modelNormalMapVertex, modelNormalSpecularMapPixel); + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_TRANSLUCENT), modelVertex, modelTranslucentPixel); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT), + modelNormalMapVertex, modelTranslucentPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + modelVertex, modelTranslucentPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + modelNormalMapVertex, modelTranslucentPixel); + + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::HAS_LIGHTMAP), modelLightmapVertex, modelLightmapPixel); @@ -310,6 +317,7 @@ void Model::init() { RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_SKINNED), skinModelVertex, modelPixel); @@ -326,15 +334,29 @@ void Model::init() { RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), skinModelNormalMapVertex, modelNormalSpecularMapPixel); + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_TRANSLUCENT), skinModelVertex, modelTranslucentPixel); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT), + skinModelNormalMapVertex, modelTranslucentPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + skinModelVertex, modelTranslucentPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + skinModelNormalMapVertex, modelTranslucentPixel); + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), modelShadowVertex, modelShadowPixel); + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), skinModelShadowVertex, modelShadowPixel); @@ -1732,6 +1754,12 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) { void Model::endScene(RenderMode mode, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); + +#if (GPU_TRANSFORM_PROFILE == GPU_LEGACY) + // with legacy transform profile, we still to protect that transform stack... + glPushMatrix(); +#endif + RenderArgs::RenderSide renderSide = RenderArgs::MONO; if (args) { renderSide = args->_renderSide; @@ -1899,6 +1927,12 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { backend.render(_sceneRenderBatch); } + +#if (GPU_TRANSFORM_PROFILE == GPU_LEGACY) + // with legacy transform profile, we still to protect that transform stack... + glPopMatrix(); +#endif + // restore all the default material settings _viewState->setupWorldLight(); @@ -1935,55 +1969,7 @@ bool Model::renderInScene(float alpha, RenderArgs* args) { } void Model::segregateMeshGroups() { - _meshesTranslucentTangents.clear(); - _meshesTranslucent.clear(); - _meshesTranslucentTangentsSpecular.clear(); - _meshesTranslucentSpecular.clear(); - - _meshesTranslucentTangentsSkinned.clear(); - _meshesTranslucentSkinned.clear(); - _meshesTranslucentTangentsSpecularSkinned.clear(); - _meshesTranslucentSpecularSkinned.clear(); - - _meshesOpaqueTangents.clear(); - _meshesOpaque.clear(); - _meshesOpaqueTangentsSpecular.clear(); - _meshesOpaqueSpecular.clear(); - - _meshesOpaqueTangentsSkinned.clear(); - _meshesOpaqueSkinned.clear(); - _meshesOpaqueTangentsSpecularSkinned.clear(); - _meshesOpaqueSpecularSkinned.clear(); - - _meshesOpaqueLightmapTangents.clear(); - _meshesOpaqueLightmap.clear(); - _meshesOpaqueLightmapTangentsSpecular.clear(); - _meshesOpaqueLightmapSpecular.clear(); - - _unsortedMeshesTranslucentTangents.clear(); - _unsortedMeshesTranslucent.clear(); - _unsortedMeshesTranslucentTangentsSpecular.clear(); - _unsortedMeshesTranslucentSpecular.clear(); - - _unsortedMeshesTranslucentTangentsSkinned.clear(); - _unsortedMeshesTranslucentSkinned.clear(); - _unsortedMeshesTranslucentTangentsSpecularSkinned.clear(); - _unsortedMeshesTranslucentSpecularSkinned.clear(); - - _unsortedMeshesOpaqueTangents.clear(); - _unsortedMeshesOpaque.clear(); - _unsortedMeshesOpaqueTangentsSpecular.clear(); - _unsortedMeshesOpaqueSpecular.clear(); - - _unsortedMeshesOpaqueTangentsSkinned.clear(); - _unsortedMeshesOpaqueSkinned.clear(); - _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); - _unsortedMeshesOpaqueSpecularSkinned.clear(); - - _unsortedMeshesOpaqueLightmapTangents.clear(); - _unsortedMeshesOpaqueLightmap.clear(); - _unsortedMeshesOpaqueLightmapTangentsSpecular.clear(); - _unsortedMeshesOpaqueLightmapSpecular.clear(); + _renderBuckets.clear(); const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); @@ -2017,201 +2003,19 @@ void Model::segregateMeshGroups() { qCDebug(renderutils) << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - if (!hasLightmap) { - if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + RenderKey key(translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned); - _unsortedMeshesTranslucent.insertMulti(materialID, i); - - } else if (translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - - _unsortedMeshesTranslucentTangents.insertMulti(materialID, i); - - } else if (translucentMesh && hasTangents && hasSpecular && !isSkinned) { - - _unsortedMeshesTranslucentTangentsSpecular.insertMulti(materialID, i); - - } else if (translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - - _unsortedMeshesTranslucentSpecular.insertMulti(materialID, i); - - } else if (translucentMesh && hasTangents && !hasSpecular && isSkinned) { - - _unsortedMeshesTranslucentTangentsSkinned.insertMulti(materialID, i); - - } else if (translucentMesh && !hasTangents && !hasSpecular && isSkinned) { - - _unsortedMeshesTranslucentSkinned.insertMulti(materialID, i); - - } else if (translucentMesh && hasTangents && hasSpecular && isSkinned) { - - _unsortedMeshesTranslucentTangentsSpecularSkinned.insertMulti(materialID, i); - - } else if (translucentMesh && !hasTangents && hasSpecular && isSkinned) { - - _unsortedMeshesTranslucentSpecularSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - - _unsortedMeshesOpaque.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueTangents.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueTangentsSpecular.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueSpecular.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueTangentsSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueTangentsSpecularSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueSpecularSkinned.insertMulti(materialID, i); - } else { - qCDebug(renderutils) << "unexpected!!! this mesh didn't fall into any or our groups???"; - } - } else { - if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueLightmap.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueLightmapTangents.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueLightmapTangentsSpecular.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueLightmapSpecular.insertMulti(materialID, i); - - } else { - qCDebug(renderutils) << "unexpected!!! this mesh didn't fall into any or our groups???"; - } - } + // reuse or create the bucket corresponding to that key and insert the mesh as unsorted + _renderBuckets[key.getRaw()]._unsortedMeshes.insertMulti(materialID, i); } - foreach(int i, _unsortedMeshesTranslucent) { - _meshesTranslucent.append(i); + for(auto& b : _renderBuckets) { + foreach(auto i, b.second._unsortedMeshes) { + b.second._meshes.append(i); + b.second._unsortedMeshes.clear(); + } } - foreach(int i, _unsortedMeshesTranslucentTangents) { - _meshesTranslucentTangents.append(i); - } - - foreach(int i, _unsortedMeshesTranslucentTangentsSpecular) { - _meshesTranslucentTangentsSpecular.append(i); - } - - foreach(int i, _unsortedMeshesTranslucentSpecular) { - _meshesTranslucentSpecular.append(i); - } - - foreach(int i, _unsortedMeshesTranslucentSkinned) { - _meshesTranslucentSkinned.append(i); - } - - foreach(int i, _unsortedMeshesTranslucentTangentsSkinned) { - _meshesTranslucentTangentsSkinned.append(i); - } - - foreach(int i, _unsortedMeshesTranslucentTangentsSpecularSkinned) { - _meshesTranslucentTangentsSpecularSkinned.append(i); - } - - foreach(int i, _unsortedMeshesTranslucentSpecularSkinned) { - _meshesTranslucentSpecularSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaque) { - _meshesOpaque.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueTangents) { - _meshesOpaqueTangents.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueTangentsSpecular) { - _meshesOpaqueTangentsSpecular.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueSpecular) { - _meshesOpaqueSpecular.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueSkinned) { - _meshesOpaqueSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueTangentsSkinned) { - _meshesOpaqueTangentsSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueTangentsSpecularSkinned) { - _meshesOpaqueTangentsSpecularSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueSpecularSkinned) { - _meshesOpaqueSpecularSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueLightmap) { - _meshesOpaqueLightmap.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueLightmapTangents) { - _meshesOpaqueLightmapTangents.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueLightmapTangentsSpecular) { - _meshesOpaqueLightmapTangentsSpecular.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueLightmapSpecular) { - _meshesOpaqueLightmapSpecular.append(i); - } - - _unsortedMeshesTranslucentTangents.clear(); - _unsortedMeshesTranslucent.clear(); - _unsortedMeshesTranslucentTangentsSpecular.clear(); - _unsortedMeshesTranslucentSpecular.clear(); - - _unsortedMeshesTranslucentTangentsSkinned.clear(); - _unsortedMeshesTranslucentSkinned.clear(); - _unsortedMeshesTranslucentTangentsSpecularSkinned.clear(); - _unsortedMeshesTranslucentSpecularSkinned.clear(); - - _unsortedMeshesOpaqueTangents.clear(); - _unsortedMeshesOpaque.clear(); - _unsortedMeshesOpaqueTangentsSpecular.clear(); - _unsortedMeshesOpaqueSpecular.clear(); - - _unsortedMeshesOpaqueTangentsSkinned.clear(); - _unsortedMeshesOpaqueSkinned.clear(); - _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); - _unsortedMeshesOpaqueSpecularSkinned.clear(); - - _unsortedMeshesOpaqueLightmapTangents.clear(); - _unsortedMeshesOpaqueLightmap.clear(); - _unsortedMeshesOpaqueLightmapTangentsSpecular.clear(); - _unsortedMeshesOpaqueLightmapSpecular.clear(); - _meshGroupsKnown = true; } @@ -2220,52 +2024,14 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h // depending on which parameters we were called with, pick the correct mesh group to render QVector* whichList = NULL; - if (translucent && !hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesTranslucent; - } else if (translucent && hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesTranslucentTangents; - } else if (translucent && hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesTranslucentTangentsSpecular; - } else if (translucent && !hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesTranslucentSpecular; - } else if (translucent && hasTangents && !hasSpecular && isSkinned) { - whichList = &_meshesTranslucentTangentsSkinned; - } else if (translucent && !hasTangents && !hasSpecular && isSkinned) { - whichList = &_meshesTranslucentSkinned; - } else if (translucent && hasTangents && hasSpecular && isSkinned) { - whichList = &_meshesTranslucentTangentsSpecularSkinned; - } else if (translucent && !hasTangents && hasSpecular && isSkinned) { - whichList = &_meshesTranslucentSpecularSkinned; - } else if (!translucent && !hasLightmap && !hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesOpaque; - } else if (!translucent && !hasLightmap && hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueTangents; - } else if (!translucent && !hasLightmap && hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueTangentsSpecular; - } else if (!translucent && !hasLightmap && !hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueSpecular; - } else if (!translucent && !hasLightmap && hasTangents && !hasSpecular && isSkinned) { - whichList = &_meshesOpaqueTangentsSkinned; - } else if (!translucent && !hasLightmap && !hasTangents && !hasSpecular && isSkinned) { - whichList = &_meshesOpaqueSkinned; - } else if (!translucent && !hasLightmap && hasTangents && hasSpecular && isSkinned) { - whichList = &_meshesOpaqueTangentsSpecularSkinned; - } else if (!translucent && !hasLightmap && !hasTangents && hasSpecular && isSkinned) { - whichList = &_meshesOpaqueSpecularSkinned; + RenderKey key(translucent, hasLightmap, hasTangents, hasSpecular, isSkinned); - } else if (!translucent && hasLightmap && !hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueLightmap; - } else if (!translucent && hasLightmap && hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueLightmapTangents; - } else if (!translucent && hasLightmap && hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueLightmapTangentsSpecular; - } else if (!translucent && hasLightmap && !hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueLightmapSpecular; - - } else { - qCDebug(renderutils) << "unexpected!!! this mesh didn't fall into any or our groups???"; + auto bucket = _renderBuckets.find(key.getRaw()); + if (bucket != _renderBuckets.end()) { + whichList = &(*bucket).second._meshes; } + return whichList; } @@ -2277,6 +2043,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f auto pipeline = _renderPipelineLib.find(key.getRaw()); if (pipeline == _renderPipelineLib.end()) { qDebug() << "No good, couldn't find a pipeline from the key ?" << key.getRaw(); + locations = 0; return; } @@ -2303,7 +2070,7 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool int meshPartsRendered = 0; bool pickProgramsNeeded = true; - Locations* locations; + Locations* locations = nullptr; foreach(Model* model, _modelsInScene) { QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); @@ -2331,20 +2098,19 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; - QVector* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); - + //Pick the mesh list with the requested render flags + QVector* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); if (!whichList) { - qCDebug(renderutils) << "unexpected!!! we don't know which list of meshes to render..."; return 0; } QVector& list = *whichList; // If this list has nothing to render, then don't bother proceeding. This saves us on binding to programs - if (list.size() == 0) { + if (list.empty()) { return 0; } - Locations* locations; + Locations* locations = nullptr; pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations); meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index fce5629b8d..1559e73e61 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -350,58 +350,6 @@ private: bool _meshGroupsKnown; - QMap _unsortedMeshesTranslucent; - QMap _unsortedMeshesTranslucentTangents; - QMap _unsortedMeshesTranslucentTangentsSpecular; - QMap _unsortedMeshesTranslucentSpecular; - - QMap _unsortedMeshesTranslucentSkinned; - QMap _unsortedMeshesTranslucentTangentsSkinned; - QMap _unsortedMeshesTranslucentTangentsSpecularSkinned; - QMap _unsortedMeshesTranslucentSpecularSkinned; - - QMap _unsortedMeshesOpaque; - QMap _unsortedMeshesOpaqueTangents; - QMap _unsortedMeshesOpaqueTangentsSpecular; - QMap _unsortedMeshesOpaqueSpecular; - - QMap _unsortedMeshesOpaqueSkinned; - QMap _unsortedMeshesOpaqueTangentsSkinned; - QMap _unsortedMeshesOpaqueTangentsSpecularSkinned; - QMap _unsortedMeshesOpaqueSpecularSkinned; - - QMap _unsortedMeshesOpaqueLightmap; - QMap _unsortedMeshesOpaqueLightmapTangents; - QMap _unsortedMeshesOpaqueLightmapTangentsSpecular; - QMap _unsortedMeshesOpaqueLightmapSpecular; - - typedef std::unordered_map> MeshListMap; - MeshListMap _sortedMeshes; - - QVector _meshesTranslucent; - QVector _meshesTranslucentTangents; - QVector _meshesTranslucentTangentsSpecular; - QVector _meshesTranslucentSpecular; - - QVector _meshesTranslucentSkinned; - QVector _meshesTranslucentTangentsSkinned; - QVector _meshesTranslucentTangentsSpecularSkinned; - QVector _meshesTranslucentSpecularSkinned; - - QVector _meshesOpaque; - QVector _meshesOpaqueTangents; - QVector _meshesOpaqueTangentsSpecular; - QVector _meshesOpaqueSpecular; - - QVector _meshesOpaqueSkinned; - QVector _meshesOpaqueTangentsSkinned; - QVector _meshesOpaqueTangentsSpecularSkinned; - QVector _meshesOpaqueSpecularSkinned; - - QVector _meshesOpaqueLightmap; - QVector _meshesOpaqueLightmapTangents; - QVector _meshesOpaqueLightmapTangentsSpecular; - QVector _meshesOpaqueLightmapSpecular; // debug rendering support void renderDebugMeshBoxes(); @@ -490,6 +438,17 @@ private: int getRaw() { return *reinterpret_cast(this); } + + RenderKey( + bool translucent, bool hasLightmap, + bool hasTangents, bool hasSpecular, bool isSkinned) : + RenderKey( (translucent ? IS_TRANSLUCENT : 0) + | (hasLightmap ? HAS_LIGHTMAP : 0) + | (hasTangents ? HAS_TANGENTS : 0) + | (hasSpecular ? HAS_SPECULAR : 0) + | (isSkinned ? IS_SKINNED : 0) + ) {} + RenderKey(RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned) : @@ -527,6 +486,19 @@ private: }; static RenderPipelineLib _renderPipelineLib; + + class RenderBucket { + public: + QVector _meshes; + QMap _unsortedMeshes; + }; + typedef std::unordered_map BaseRenderBucketMap; + class RenderBucketMap : public BaseRenderBucketMap { + public: + typedef RenderKey Key; + }; + RenderBucketMap _renderBuckets; + bool _renderCollisionHull; }; diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp index 5a8f591410..2461487414 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.cpp +++ b/libraries/script-engine/src/SceneScriptingInterface.cpp @@ -46,22 +46,46 @@ int SceneScriptingInterface::getStageYearTime() const { return _skyStage->getYearTime(); } -void SceneScriptingInterface::setSunColor(const glm::vec3& color) { +void SceneScriptingInterface::setKeyLightColor(const glm::vec3& color) { _skyStage->setSunColor(color); } -const glm::vec3& SceneScriptingInterface::getSunColor() const { +glm::vec3 SceneScriptingInterface::getKeyLightColor() const { return _skyStage->getSunColor(); } -void SceneScriptingInterface::setSunIntensity(float intensity) { +void SceneScriptingInterface::setKeyLightIntensity(float intensity) { _skyStage->setSunIntensity(intensity); } -float SceneScriptingInterface::getSunIntensity() const { +float SceneScriptingInterface::getKeyLightIntensity() const { return _skyStage->getSunIntensity(); } +void SceneScriptingInterface::setKeyLightAmbientIntensity(float intensity) { + _skyStage->setSunAmbientIntensity(intensity); +} + +float SceneScriptingInterface::getKeyLightAmbientIntensity() const { + return _skyStage->getSunAmbientIntensity(); +} + +void SceneScriptingInterface::setKeyLightDirection(const glm::vec3& direction) { + _skyStage->setSunDirection(direction); +} + +glm::vec3 SceneScriptingInterface::getKeyLightDirection() const { + return _skyStage->getSunDirection(); +} + +void SceneScriptingInterface::setStageSunModelEnable(bool isEnabled) { + _skyStage->setSunModelEnable(isEnabled); +} + +bool SceneScriptingInterface::isStageSunModelEnabled() const { + return _skyStage->isSunModelEnabled(); +} + model::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const { return _skyStage; } diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 352bc1e78f..c384153a0f 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -38,10 +38,26 @@ public: Q_INVOKABLE void setStageYearTime(int day); Q_INVOKABLE int getStageYearTime() const; - Q_INVOKABLE void setSunColor(const glm::vec3& color); - Q_INVOKABLE const glm::vec3& getSunColor() const; - Q_INVOKABLE void setSunIntensity(float intensity); - Q_INVOKABLE float getSunIntensity() const; + // Enable/disable the stage sun model which uses the key light to simulate + // the sun light based on the location of the stage trelative to earth and the current time + Q_INVOKABLE void setStageSunModelEnable(bool isEnabled); + Q_INVOKABLE bool isStageSunModelEnabled() const; + + + Q_INVOKABLE void setKeyLightColor(const glm::vec3& color); + Q_INVOKABLE glm::vec3 getKeyLightColor() const; + Q_INVOKABLE void setKeyLightIntensity(float intensity); + Q_INVOKABLE float getKeyLightIntensity() const; + Q_INVOKABLE void setKeyLightAmbientIntensity(float intensity); + Q_INVOKABLE float getKeyLightAmbientIntensity() const; + + // setKeyLightDIrection is only effective if stage Sun model is disabled + Q_INVOKABLE void setKeyLightDirection(const glm::vec3& direction); + + Q_INVOKABLE glm::vec3 getKeyLightDirection() const; + + + model::SunSkyStagePointer getSkyStage() const; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 2f9427a63d..ac2c212001 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -647,8 +647,10 @@ void ScriptEngine::stopAllTimers() { } void ScriptEngine::stop() { - _isFinished = true; - emit runningStateChanged(); + if (!_isFinished) { + _isFinished = true; + emit runningStateChanged(); + } } void ScriptEngine::timerFired() { diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index ba2938aaa6..55994f3d89 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,12 +1,10 @@ # add the tool directories add_subdirectory(mtc) set_target_properties(mtc PROPERTIES FOLDER "Tools") + add_subdirectory(scribe) set_target_properties(scribe PROPERTIES FOLDER "Tools") +add_subdirectory(vhacd-util) +set_target_properties(vhacd-util PROPERTIES FOLDER "Tools") -find_package(VHACD) -if(VHACD_FOUND) -add_subdirectory(vhacd) -# set_target_properties(vhacd PROPERTIES FOLDER "Tools") -endif() diff --git a/tools/vhacd-util/CMakeLists.txt b/tools/vhacd-util/CMakeLists.txt new file mode 100644 index 0000000000..c94b2ad083 --- /dev/null +++ b/tools/vhacd-util/CMakeLists.txt @@ -0,0 +1,18 @@ +set(TARGET_NAME vhacd-util) +setup_hifi_project(Core Widgets) +link_hifi_libraries(shared fbx model gpu) + +add_dependency_external_projects(vhacd) + +find_package(VHACD REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${VHACD_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${VHACD_LIBRARIES}) + +if (UNIX AND NOT APPLE) + include(FindOpenMP) + if(OPENMP_FOUND) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") + endif() +endif () diff --git a/tools/vhacd/src/VHACDUtil.cpp b/tools/vhacd-util/src/VHACDUtil.cpp similarity index 100% rename from tools/vhacd/src/VHACDUtil.cpp rename to tools/vhacd-util/src/VHACDUtil.cpp diff --git a/tools/vhacd/src/VHACDUtil.h b/tools/vhacd-util/src/VHACDUtil.h similarity index 100% rename from tools/vhacd/src/VHACDUtil.h rename to tools/vhacd-util/src/VHACDUtil.h diff --git a/tools/vhacd/src/VHACDUtilApp.cpp b/tools/vhacd-util/src/VHACDUtilApp.cpp similarity index 100% rename from tools/vhacd/src/VHACDUtilApp.cpp rename to tools/vhacd-util/src/VHACDUtilApp.cpp diff --git a/tools/vhacd/src/VHACDUtilApp.h b/tools/vhacd-util/src/VHACDUtilApp.h similarity index 100% rename from tools/vhacd/src/VHACDUtilApp.h rename to tools/vhacd-util/src/VHACDUtilApp.h diff --git a/tools/vhacd/src/main.cpp b/tools/vhacd-util/src/main.cpp similarity index 100% rename from tools/vhacd/src/main.cpp rename to tools/vhacd-util/src/main.cpp diff --git a/tools/vhacd/CMakeLists.txt b/tools/vhacd/CMakeLists.txt deleted file mode 100644 index f003b685e0..0000000000 --- a/tools/vhacd/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -set(TARGET_NAME vhacd-util) -setup_hifi_project(Core Widgets) -link_hifi_libraries(shared model fbx gpu networking octree) - -#find_package(VHACD REQUIRED) done in CMakeList.txt in parent directory -target_include_directories(${TARGET_NAME} PUBLIC ${VHACD_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${VHACD_LIBRARIES}) - -if(NOT WIN32) - find_package( Threads) - target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT}) - - include(FindOpenMP) - if(OPENMP_FOUND) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") - endif() -endif() - -add_dependency_external_projects(glm) -find_package(GLM REQUIRED) -target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS})