mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 08:49:05 +02:00
Merge remote-tracking branch 'upstream/master' into offscreen
Conflicts: interface/src/Menu.cpp
This commit is contained in:
commit
7a33474245
50 changed files with 1033 additions and 936 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -4,6 +4,7 @@ CMakeFiles/
|
||||||
CMakeScripts/
|
CMakeScripts/
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
build*/
|
build*/
|
||||||
|
ext/
|
||||||
Makefile
|
Makefile
|
||||||
*.user
|
*.user
|
||||||
|
|
||||||
|
@ -32,10 +33,6 @@ DerivedData
|
||||||
interface/external/*/*
|
interface/external/*/*
|
||||||
!interface/external/*/readme.txt
|
!interface/external/*/readme.txt
|
||||||
|
|
||||||
# ignore interface optional resources
|
|
||||||
interface/resources/visage/*
|
|
||||||
!interface/resources/visage/tracker.cfg
|
|
||||||
|
|
||||||
# Ignore interfaceCache for Linux users
|
# Ignore interfaceCache for Linux users
|
||||||
interface/interfaceCache/
|
interface/interfaceCache/
|
||||||
|
|
||||||
|
|
4
BUILD.md
4
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
|
* [SDL2](https://www.libsdl.org/download-2.0.php) ~> 2.0.3
|
||||||
* Enables game controller support in Interface
|
* 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.
|
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.
|
||||||
|
|
||||||
|
|
|
@ -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_TBB "Get Threading Building Blocks library automatically as external project" 1)
|
||||||
option(GET_LIBOVR "Get LibOVR 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(USE_NSIGHT "Attempt to find the nSight libraries" 1)
|
||||||
|
option(GET_VHACD "Get V-HACD library automatically as external project" 1)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
option(GET_GLEW "Get GLEW library automatically as external project" 1)
|
option(GET_GLEW "Get GLEW library automatically as external project" 1)
|
||||||
|
|
31
cmake/externals/vhacd/CMakeLists.txt
vendored
Normal file
31
cmake/externals/vhacd/CMakeLists.txt
vendored
Normal file
|
@ -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=<INSTALL_DIR>
|
||||||
|
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")
|
|
@ -22,7 +22,7 @@ macro(SETUP_EXTERNALS_BINARY_DIR)
|
||||||
endif ()
|
endif ()
|
||||||
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)
|
if (ANDROID)
|
||||||
set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/android/${CMAKE_GENERATOR_FOLDER_NAME}")
|
set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/android/${CMAKE_GENERATOR_FOLDER_NAME}")
|
||||||
else ()
|
else ()
|
||||||
|
|
|
@ -19,40 +19,16 @@
|
||||||
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||||
hifi_library_search_hints("vhacd")
|
hifi_library_search_hints("vhacd")
|
||||||
|
|
||||||
macro(_FIND_VHACD_LIBRARY _var)
|
find_path(VHACD_INCLUDE_DIRS VHACD.h PATH_SUFFIXES include HINTS ${VHACD_SEARCH_DIRS})
|
||||||
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
|
find_library(VHACD_LIBRARY_DEBUG NAMES VHACD VHACD_LIB PATH_SUFFIXES lib/Debug HINTS ${VHACD_SEARCH_DIRS})
|
||||||
NAMES ${_${_var}_NAMES}
|
find_library(VHACD_LIBRARY_RELEASE NAMES VHACD VHACD_LIB PATH_SUFFIXES lib/Release lib HINTS ${VHACD_SEARCH_DIRS})
|
||||||
HINTS
|
|
||||||
${VHACD_SEARCH_DIRS}
|
|
||||||
$ENV{VHACD_ROOT_DIR}
|
|
||||||
PATH_SUFFIXES lib lib/Debug
|
|
||||||
)
|
|
||||||
|
|
||||||
select_library_configurations(${_var})
|
include(SelectLibraryConfigurations)
|
||||||
|
select_library_configurations(VHACD)
|
||||||
|
|
||||||
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} $ENV{VHACD_ROOT_DIR})
|
|
||||||
if(NOT WIN32)
|
|
||||||
_FIND_VHACD_LIBRARY(VHACD libVHACD.a)
|
|
||||||
else()
|
|
||||||
_FIND_VHACD_LIBRARY(VHACD VHACD_LIB)
|
|
||||||
endif()
|
|
||||||
set(VHACD_LIBRARIES ${VHACD_LIBRARY})
|
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"
|
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)
|
VHACD_INCLUDE_DIRS VHACD_LIBRARIES)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
|
@ -302,6 +302,9 @@ bool DomainServer::didSetupAccountManagerWithAccessToken() {
|
||||||
<< "at keypath metaverse.access_token or in your ENV at key DOMAIN_SERVER_ACCESS_TOKEN";
|
<< "at keypath metaverse.access_token or in your ENV at key DOMAIN_SERVER_ACCESS_TOKEN";
|
||||||
return false;
|
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
|
// give this access token to the AccountManager
|
||||||
|
|
163
examples/acScripts/rain.js
Normal file
163
examples/acScripts/rain.js
Normal file
|
@ -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
|
||||||
|
});
|
|
@ -41,7 +41,8 @@ panel.newSlider("Year Time", 0, 364,
|
||||||
);
|
);
|
||||||
|
|
||||||
panel.newSlider("Day Time", 0, 24,
|
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() { return Scene.getStageDayTime(); },
|
||||||
function(value) {
|
function(value) {
|
||||||
var hour = Math.floor(value);
|
var hour = Math.floor(value);
|
||||||
|
@ -72,12 +73,36 @@ function runStageTime() {
|
||||||
}
|
}
|
||||||
Script.setInterval(runStageTime, tickTackPeriod);
|
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,
|
panel.newSlider("Light Intensity", 0.0, 5,
|
||||||
function(value) { Scene.setSunIntensity(value); },
|
function(value) { Scene.setKeyLightIntensity(value); },
|
||||||
function() { return Scene.getSunIntensity(); },
|
function() { return Scene.getKeyLightIntensity(); },
|
||||||
function(value) { return (value).toFixed(2); }
|
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.mouseMoveEvent.connect(function panelMouseMoveEvent(event) { return panel.mouseMoveEvent(event); });
|
||||||
Controller.mousePressEvent.connect( function panelMousePressEvent(event) { return panel.mousePressEvent(event); });
|
Controller.mousePressEvent.connect( function panelMousePressEvent(event) { return panel.mousePressEvent(event); });
|
||||||
Controller.mouseReleaseEvent.connect(function(event) { return panel.mouseReleaseEvent(event); });
|
Controller.mouseReleaseEvent.connect(function(event) { return panel.mouseReleaseEvent(event); });
|
||||||
|
|
|
@ -12,6 +12,129 @@
|
||||||
|
|
||||||
// The Slider class
|
// The Slider class
|
||||||
Slider = function(x,y,width,thumbSize) {
|
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", {
|
this.thumb = Overlays.addOverlay("text", {
|
||||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||||
|
@ -52,6 +175,10 @@ Slider = function(x,y,width,thumbSize) {
|
||||||
Overlays.editOverlay(this.thumb, { x: thumbTruePos } );
|
Overlays.editOverlay(this.thumb, { x: thumbTruePos } );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.isClickableOverlayItem = function(item) {
|
||||||
|
return item == this.background;
|
||||||
|
};
|
||||||
|
|
||||||
this.onMouseMoveEvent = function(event) {
|
this.onMouseMoveEvent = function(event) {
|
||||||
if (this.isMoving) {
|
if (this.isMoving) {
|
||||||
newThumbX = event.x - this.clickOffsetX;
|
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;
|
this.isMoving = true;
|
||||||
var clickOffset = event.x - this.thumbX;
|
var clickOffset = event.x - this.thumbX;
|
||||||
if ((clickOffset > -this.thumbHalfSize) && (clickOffset < this.thumbHalfSize)) {
|
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;
|
var textFontSize = 16;
|
||||||
|
|
||||||
|
@ -167,7 +459,12 @@ function PanelItem(name, setter, getter, displayer, x, y, textWidth, valueWidth,
|
||||||
};
|
};
|
||||||
this.setterFromWidget = function(value) {
|
this.setterFromWidget = function(value) {
|
||||||
setter(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) {
|
for (var i in this.items) {
|
||||||
var widget = this.items[i].widget;
|
var widget = this.items[i].widget;
|
||||||
|
|
||||||
if (clickedOverlay == widget.background) {
|
if (widget.isClickableOverlayItem(clickedOverlay)) {
|
||||||
this.activeWidget = widget;
|
this.activeWidget = widget;
|
||||||
this.activeWidget.onMousePressEvent(event);
|
this.activeWidget.onMousePressEvent(event, clickedOverlay);
|
||||||
// print("clicked... widget=" + i);
|
// print("clicked... widget=" + i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -237,21 +534,63 @@ Panel = function(x, y) {
|
||||||
|
|
||||||
this.newSlider = function(name, minValue, maxValue, setValue, getValue, displayValue) {
|
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);
|
var slider = new Slider(this.widgetX, this.nextY, widgetWidth, rawHeight);
|
||||||
slider.minValue = minValue;
|
slider.minValue = minValue;
|
||||||
slider.maxValue = maxValue;
|
slider.maxValue = maxValue;
|
||||||
slider.onValueChanged = function(value) { sliderItem.setterFromWidget(value); };
|
|
||||||
|
|
||||||
|
|
||||||
sliderItem.widget = slider;
|
item.widget = slider;
|
||||||
sliderItem.setter(getValue());
|
item.widget.onValueChanged = function(value) { item.setterFromWidget(value); };
|
||||||
this.items[name] = sliderItem;
|
item.setter(getValue());
|
||||||
|
this.items[name] = item;
|
||||||
this.nextY += rawYDelta;
|
this.nextY += rawYDelta;
|
||||||
// print("created Item... slider=" + name);
|
// 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() {
|
this.destroy = function() {
|
||||||
for (var i in this.items) {
|
for (var i in this.items) {
|
||||||
this.items[i].destroy();
|
this.items[i].destroy();
|
||||||
|
@ -273,6 +612,15 @@ Panel = function(x, y) {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.update = function(name) {
|
||||||
|
var item = this.items[name];
|
||||||
|
if (item != null) {
|
||||||
|
return item.setter(item.getter());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -170,15 +170,6 @@ foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
|
||||||
endif ()
|
endif ()
|
||||||
endforeach()
|
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
|
# special OS X modifications for RtMidi library
|
||||||
if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI AND APPLE)
|
if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI AND APPLE)
|
||||||
find_library(CoreMIDI CoreMIDI)
|
find_library(CoreMIDI CoreMIDI)
|
||||||
|
|
14
interface/external/visage/readme.txt
vendored
14
interface/external/visage/readme.txt
vendored
|
@ -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.
|
|
||||||
|
|
|
@ -108,7 +108,6 @@
|
||||||
#include "devices/MIDIManager.h"
|
#include "devices/MIDIManager.h"
|
||||||
#include "devices/OculusManager.h"
|
#include "devices/OculusManager.h"
|
||||||
#include "devices/TV3DManager.h"
|
#include "devices/TV3DManager.h"
|
||||||
#include "devices/Visage.h"
|
|
||||||
|
|
||||||
#include "gpu/Batch.h"
|
#include "gpu/Batch.h"
|
||||||
#include "gpu/GLBackend.h"
|
#include "gpu/GLBackend.h"
|
||||||
|
@ -247,7 +246,6 @@ bool setupEssentials(int& argc, char** argv) {
|
||||||
auto ambientOcclusionEffect = DependencyManager::set<AmbientOcclusionEffect>();
|
auto ambientOcclusionEffect = DependencyManager::set<AmbientOcclusionEffect>();
|
||||||
auto textureCache = DependencyManager::set<TextureCache>();
|
auto textureCache = DependencyManager::set<TextureCache>();
|
||||||
auto animationCache = DependencyManager::set<AnimationCache>();
|
auto animationCache = DependencyManager::set<AnimationCache>();
|
||||||
auto visage = DependencyManager::set<Visage>();
|
|
||||||
auto ddeFaceTracker = DependencyManager::set<DdeFaceTracker>();
|
auto ddeFaceTracker = DependencyManager::set<DdeFaceTracker>();
|
||||||
auto modelBlender = DependencyManager::set<ModelBlender>();
|
auto modelBlender = DependencyManager::set<ModelBlender>();
|
||||||
auto audioToolBox = DependencyManager::set<AudioToolBox>();
|
auto audioToolBox = DependencyManager::set<AudioToolBox>();
|
||||||
|
@ -1834,12 +1832,10 @@ int Application::getMouseDragStartedY() const {
|
||||||
|
|
||||||
FaceTracker* Application::getActiveFaceTracker() {
|
FaceTracker* Application::getActiveFaceTracker() {
|
||||||
auto faceshift = DependencyManager::get<Faceshift>();
|
auto faceshift = DependencyManager::get<Faceshift>();
|
||||||
auto visage = DependencyManager::get<Visage>();
|
|
||||||
auto dde = DependencyManager::get<DdeFaceTracker>();
|
auto dde = DependencyManager::get<DdeFaceTracker>();
|
||||||
|
|
||||||
return (dde->isActive() ? static_cast<FaceTracker*>(dde.data()) :
|
return (dde->isActive() ? static_cast<FaceTracker*>(dde.data()) :
|
||||||
(faceshift->isActive() ? static_cast<FaceTracker*>(faceshift.data()) :
|
(faceshift->isActive() ? static_cast<FaceTracker*>(faceshift.data()) : NULL));
|
||||||
(visage->isActive() ? static_cast<FaceTracker*>(visage.data()) : NULL)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setActiveFaceTracker() {
|
void Application::setActiveFaceTracker() {
|
||||||
|
@ -1847,10 +1843,11 @@ void Application::setActiveFaceTracker() {
|
||||||
DependencyManager::get<Faceshift>()->setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift));
|
DependencyManager::get<Faceshift>()->setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift));
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_DDE
|
#ifdef HAVE_DDE
|
||||||
DependencyManager::get<DdeFaceTracker>()->setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression));
|
bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression);
|
||||||
#endif
|
Menu::getInstance()->getActionForOption(MenuOption::UseAudioForMouth)->setVisible(isUsingDDE);
|
||||||
#ifdef HAVE_VISAGE
|
Menu::getInstance()->getActionForOption(MenuOption::DDEFiltering)->setVisible(isUsingDDE);
|
||||||
DependencyManager::get<Visage>()->updateEnabled();
|
Menu::getInstance()->getActionForOption(MenuOption::ResetDDETracking)->setVisible(isUsingDDE);
|
||||||
|
DependencyManager::get<DdeFaceTracker>()->setEnabled(isUsingDDE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2025,7 +2022,6 @@ void Application::init() {
|
||||||
// initialize our face trackers after loading the menu settings
|
// initialize our face trackers after loading the menu settings
|
||||||
DependencyManager::get<Faceshift>()->init();
|
DependencyManager::get<Faceshift>()->init();
|
||||||
DependencyManager::get<DdeFaceTracker>()->init();
|
DependencyManager::get<DdeFaceTracker>()->init();
|
||||||
DependencyManager::get<Visage>()->init();
|
|
||||||
|
|
||||||
Leapmotion::init();
|
Leapmotion::init();
|
||||||
RealSense::init();
|
RealSense::init();
|
||||||
|
@ -3144,7 +3140,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
||||||
{
|
{
|
||||||
DependencyManager::get<DeferredLightingEffect>()->setAmbientLightMode(getRenderAmbientLight());
|
DependencyManager::get<DeferredLightingEffect>()->setAmbientLightMode(getRenderAmbientLight());
|
||||||
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||||
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity());
|
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity());
|
||||||
DependencyManager::get<DeferredLightingEffect>()->setGlobalAtmosphere(skyStage->getAtmosphere());
|
DependencyManager::get<DeferredLightingEffect>()->setGlobalAtmosphere(skyStage->getAtmosphere());
|
||||||
|
|
||||||
PROFILE_RANGE("DeferredLighting");
|
PROFILE_RANGE("DeferredLighting");
|
||||||
|
@ -3359,7 +3355,6 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
|
||||||
|
|
||||||
void Application::resetSensors() {
|
void Application::resetSensors() {
|
||||||
DependencyManager::get<Faceshift>()->reset();
|
DependencyManager::get<Faceshift>()->reset();
|
||||||
DependencyManager::get<Visage>()->reset();
|
|
||||||
DependencyManager::get<DdeFaceTracker>()->reset();
|
DependencyManager::get<DdeFaceTracker>()->reset();
|
||||||
|
|
||||||
OculusManager::reset();
|
OculusManager::reset();
|
||||||
|
@ -3966,6 +3961,9 @@ void Application::stopAllScripts(bool restart) {
|
||||||
// stops all current running scripts
|
// stops all current running scripts
|
||||||
for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
|
for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
|
||||||
it != _scriptEnginesHash.constEnd(); it++) {
|
it != _scriptEnginesHash.constEnd(); it++) {
|
||||||
|
if (it.value()->isFinished()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (restart && it.value()->isUserLoaded()) {
|
if (restart && it.value()->isUserLoaded()) {
|
||||||
connect(it.value(), SIGNAL(finished(const QString&)), SLOT(loadScript(const QString&)));
|
connect(it.value(), SIGNAL(finished(const QString&)), SLOT(loadScript(const QString&)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,7 +213,6 @@ public:
|
||||||
bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; }
|
bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; }
|
||||||
|
|
||||||
FaceTracker* getActiveFaceTracker();
|
FaceTracker* getActiveFaceTracker();
|
||||||
void setActiveFaceTracker();
|
|
||||||
|
|
||||||
QSystemTrayIcon* getTrayIcon() { return _trayIcon; }
|
QSystemTrayIcon* getTrayIcon() { return _trayIcon; }
|
||||||
ApplicationOverlay& getApplicationOverlay() { return _applicationOverlay; }
|
ApplicationOverlay& getApplicationOverlay() { return _applicationOverlay; }
|
||||||
|
@ -388,6 +387,8 @@ public slots:
|
||||||
void setVSyncEnabled();
|
void setVSyncEnabled();
|
||||||
|
|
||||||
void resetSensors();
|
void resetSensors();
|
||||||
|
void setActiveFaceTracker();
|
||||||
|
|
||||||
void aboutApp();
|
void aboutApp();
|
||||||
void showEditEntitiesHelp();
|
void showEditEntitiesHelp();
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <UUID.h>
|
#include <UUID.h>
|
||||||
|
|
||||||
#include "DiscoverabilityManager.h"
|
#include "DiscoverabilityManager.h"
|
||||||
|
#include "Menu.h"
|
||||||
|
|
||||||
const Discoverability::Mode DEFAULT_DISCOVERABILITY_MODE = Discoverability::All;
|
const Discoverability::Mode DEFAULT_DISCOVERABILITY_MODE = Discoverability::All;
|
||||||
|
|
||||||
|
@ -97,3 +98,31 @@ void DiscoverabilityManager::setDiscoverabilityMode(Discoverability::Mode discov
|
||||||
emit discoverabilityModeChanged(discoverabilityMode);
|
emit discoverabilityModeChanged(discoverabilityMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,9 @@ public slots:
|
||||||
Discoverability::Mode getDiscoverabilityMode() { return static_cast<Discoverability::Mode>(_mode.get()); }
|
Discoverability::Mode getDiscoverabilityMode() { return static_cast<Discoverability::Mode>(_mode.get()); }
|
||||||
void setDiscoverabilityMode(Discoverability::Mode discoverabilityMode);
|
void setDiscoverabilityMode(Discoverability::Mode discoverabilityMode);
|
||||||
|
|
||||||
|
void setVisibility();
|
||||||
|
void visibilityChanged(Discoverability::Mode discoverabilityMode);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void discoverabilityModeChanged(Discoverability::Mode discoverabilityMode);
|
void discoverabilityModeChanged(Discoverability::Mode discoverabilityMode);
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include "devices/Faceshift.h"
|
#include "devices/Faceshift.h"
|
||||||
#include "devices/RealSense.h"
|
#include "devices/RealSense.h"
|
||||||
#include "devices/SixenseManager.h"
|
#include "devices/SixenseManager.h"
|
||||||
#include "devices/Visage.h"
|
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "scripting/MenuScriptingInterface.h"
|
#include "scripting/MenuScriptingInterface.h"
|
||||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||||
|
@ -164,21 +163,21 @@ Menu::Menu() {
|
||||||
|
|
||||||
QAction* visibleToEveryone = addCheckableActionToQMenuAndActionHash(visibilityMenu, MenuOption::VisibleToEveryone,
|
QAction* visibleToEveryone = addCheckableActionToQMenuAndActionHash(visibilityMenu, MenuOption::VisibleToEveryone,
|
||||||
0, discoverabilityManager->getDiscoverabilityMode() == Discoverability::All,
|
0, discoverabilityManager->getDiscoverabilityMode() == Discoverability::All,
|
||||||
this, SLOT(setVisibility()));
|
discoverabilityManager.data(), SLOT(setVisibility()));
|
||||||
visibilityGroup->addAction(visibleToEveryone);
|
visibilityGroup->addAction(visibleToEveryone);
|
||||||
|
|
||||||
QAction* visibleToFriends = addCheckableActionToQMenuAndActionHash(visibilityMenu, MenuOption::VisibleToFriends,
|
QAction* visibleToFriends = addCheckableActionToQMenuAndActionHash(visibilityMenu, MenuOption::VisibleToFriends,
|
||||||
0, discoverabilityManager->getDiscoverabilityMode() == Discoverability::Friends,
|
0, discoverabilityManager->getDiscoverabilityMode() == Discoverability::Friends,
|
||||||
this, SLOT(setVisibility()));
|
discoverabilityManager.data(), SLOT(setVisibility()));
|
||||||
visibilityGroup->addAction(visibleToFriends);
|
visibilityGroup->addAction(visibleToFriends);
|
||||||
|
|
||||||
QAction* visibleToNoOne = addCheckableActionToQMenuAndActionHash(visibilityMenu, MenuOption::VisibleToNoOne,
|
QAction* visibleToNoOne = addCheckableActionToQMenuAndActionHash(visibilityMenu, MenuOption::VisibleToNoOne,
|
||||||
0, discoverabilityManager->getDiscoverabilityMode() == Discoverability::None,
|
0, discoverabilityManager->getDiscoverabilityMode() == Discoverability::None,
|
||||||
this, SLOT(setVisibility()));
|
discoverabilityManager.data(), SLOT(setVisibility()));
|
||||||
visibilityGroup->addAction(visibleToNoOne);
|
visibilityGroup->addAction(visibleToNoOne);
|
||||||
|
|
||||||
connect(discoverabilityManager.data(), &DiscoverabilityManager::discoverabilityModeChanged,
|
connect(discoverabilityManager.data(), &DiscoverabilityManager::discoverabilityModeChanged,
|
||||||
this, &Menu::visibilityChanged);
|
discoverabilityManager.data(), &DiscoverabilityManager::visibilityChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
addActionToQMenuAndActionHash(toolsMenu,
|
addActionToQMenuAndActionHash(toolsMenu,
|
||||||
|
@ -236,17 +235,13 @@ Menu::Menu() {
|
||||||
|
|
||||||
QMenu* viewMenu = addMenu("View");
|
QMenu* viewMenu = addMenu("View");
|
||||||
|
|
||||||
|
addCheckableActionToQMenuAndActionHash(viewMenu,
|
||||||
|
MenuOption::Fullscreen,
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu,
|
|
||||||
MenuOption::Fullscreen,
|
|
||||||
Qt::CTRL | Qt::META | Qt::Key_F,
|
Qt::CTRL | Qt::META | Qt::Key_F,
|
||||||
false,
|
|
||||||
qApp,
|
|
||||||
SLOT(setFullscreen(bool)));
|
|
||||||
#else
|
#else
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu,
|
|
||||||
MenuOption::Fullscreen,
|
|
||||||
Qt::CTRL | Qt::Key_F,
|
Qt::CTRL | Qt::Key_F,
|
||||||
|
#endif
|
||||||
false,
|
false,
|
||||||
qApp,
|
qApp,
|
||||||
SLOT(setFullscreen(bool)));
|
SLOT(setFullscreen(bool)));
|
||||||
|
@ -261,12 +256,16 @@ Menu::Menu() {
|
||||||
0, // QML Qt::Key_H,
|
0, // QML Qt::Key_H,
|
||||||
false, qApp, SLOT(cameraMenuChanged()));
|
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,
|
false,
|
||||||
dialogsManager.data(),
|
dialogsManager.data(),
|
||||||
SLOT(hmdTools(bool)));
|
SLOT(hmdTools(bool)));
|
||||||
|
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0,
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0,
|
||||||
false,
|
false,
|
||||||
qApp,
|
qApp,
|
||||||
|
@ -376,30 +375,28 @@ Menu::Menu() {
|
||||||
|
|
||||||
QAction* noFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::NoFaceTracking,
|
QAction* noFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::NoFaceTracking,
|
||||||
0, true,
|
0, true,
|
||||||
this, SLOT(setActiveFaceTracker()));
|
qApp, SLOT(setActiveFaceTracker()));
|
||||||
faceTrackerGroup->addAction(noFaceTracker);
|
faceTrackerGroup->addAction(noFaceTracker);
|
||||||
|
|
||||||
#ifdef HAVE_FACESHIFT
|
#ifdef HAVE_FACESHIFT
|
||||||
QAction* faceshiftFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Faceshift,
|
QAction* faceshiftFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Faceshift,
|
||||||
0, false,
|
0, false,
|
||||||
this, SLOT(setActiveFaceTracker()));
|
qApp, SLOT(setActiveFaceTracker()));
|
||||||
faceTrackerGroup->addAction(faceshiftFaceTracker);
|
faceTrackerGroup->addAction(faceshiftFaceTracker);
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_DDE
|
#ifdef HAVE_DDE
|
||||||
QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFaceRegression,
|
QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFaceRegression,
|
||||||
0, false,
|
0, false,
|
||||||
this, SLOT(setActiveFaceTracker()));
|
qApp, SLOT(setActiveFaceTracker()));
|
||||||
faceTrackerGroup->addAction(ddeFaceTracker);
|
faceTrackerGroup->addAction(ddeFaceTracker);
|
||||||
#endif
|
|
||||||
#ifdef HAVE_VISAGE
|
|
||||||
QAction* visageFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Visage,
|
|
||||||
0, false,
|
|
||||||
this, SLOT(setActiveFaceTracker()));
|
|
||||||
faceTrackerGroup->addAction(visageFaceTracker);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DDE
|
#ifdef HAVE_DDE
|
||||||
faceTrackingMenu->addSeparator();
|
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,
|
QAction* ddeFaceTrackerReset = addActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::ResetDDETracking,
|
||||||
Qt::CTRL | Qt::Key_Apostrophe,
|
Qt::CTRL | Qt::Key_Apostrophe,
|
||||||
DependencyManager::get<DdeFaceTracker>().data(), SLOT(resetTracking()));
|
DependencyManager::get<DdeFaceTracker>().data(), SLOT(resetTracking()));
|
||||||
|
@ -975,37 +972,3 @@ bool Menu::menuItemExists(const QString& menu, const QString& menuitem) {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Menu::setVisibility() {
|
|
||||||
auto discoverabilityManager = DependencyManager::get<DiscoverabilityManager>();
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
|
@ -66,10 +66,6 @@ public slots:
|
||||||
bool isOptionChecked(const QString& menuOption) const;
|
bool isOptionChecked(const QString& menuOption) const;
|
||||||
void setIsOptionChecked(const QString& menuOption, bool isChecked);
|
void setIsOptionChecked(const QString& menuOption, bool isChecked);
|
||||||
|
|
||||||
private slots:
|
|
||||||
void setVisibility();
|
|
||||||
void setActiveFaceTracker();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Menu* _instance;
|
static Menu* _instance;
|
||||||
Menu();
|
Menu();
|
||||||
|
@ -100,8 +96,6 @@ private:
|
||||||
int findPositionOfMenuItem(QMenu* menu, const QString& searchMenuItem);
|
int findPositionOfMenuItem(QMenu* menu, const QString& searchMenuItem);
|
||||||
int positionBeforeSeparatorIfNeeded(QMenu* menu, int requestedPosition);
|
int positionBeforeSeparatorIfNeeded(QMenu* menu, int requestedPosition);
|
||||||
|
|
||||||
void visibilityChanged(Discoverability::Mode discoverabilityMode);
|
|
||||||
|
|
||||||
QHash<QString, QAction*> _actionHash;
|
QHash<QString, QAction*> _actionHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -137,6 +131,7 @@ namespace MenuOption {
|
||||||
const QString CopyAddress = "Copy Address to Clipboard";
|
const QString CopyAddress = "Copy Address to Clipboard";
|
||||||
const QString CopyPath = "Copy Path to Clipboard";
|
const QString CopyPath = "Copy Path to Clipboard";
|
||||||
const QString DDEFaceRegression = "DDE Face Regression";
|
const QString DDEFaceRegression = "DDE Face Regression";
|
||||||
|
const QString DDEFiltering = "DDE Filtering";
|
||||||
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
||||||
const QString DeleteBookmark = "Delete Bookmark...";
|
const QString DeleteBookmark = "Delete Bookmark...";
|
||||||
const QString DisableActivityLogger = "Disable Activity Logger";
|
const QString DisableActivityLogger = "Disable Activity Logger";
|
||||||
|
@ -192,6 +187,7 @@ namespace MenuOption {
|
||||||
const QString OctreeStats = "Entity Statistics";
|
const QString OctreeStats = "Entity Statistics";
|
||||||
const QString OffAxisProjection = "Off-Axis Projection";
|
const QString OffAxisProjection = "Off-Axis Projection";
|
||||||
const QString OnlyDisplayTopTen = "Only Display Top Ten";
|
const QString OnlyDisplayTopTen = "Only Display Top Ten";
|
||||||
|
const QString PackageModel = "Package Model...";
|
||||||
const QString Pair = "Pair";
|
const QString Pair = "Pair";
|
||||||
const QString PipelineWarnings = "Log Render Pipeline Warnings";
|
const QString PipelineWarnings = "Log Render Pipeline Warnings";
|
||||||
const QString Preferences = "Preferences...";
|
const QString Preferences = "Preferences...";
|
||||||
|
@ -250,8 +246,7 @@ namespace MenuOption {
|
||||||
const QString ToolWindow = "Tool Window";
|
const QString ToolWindow = "Tool Window";
|
||||||
const QString TransmitterDrive = "Transmitter Drive";
|
const QString TransmitterDrive = "Transmitter Drive";
|
||||||
const QString TurnWithHead = "Turn using Head";
|
const QString TurnWithHead = "Turn using Head";
|
||||||
const QString PackageModel = "Package Model...";
|
const QString UseAudioForMouth = "Use Audio for Mouth";
|
||||||
const QString Visage = "Visage";
|
|
||||||
const QString VisibleToEveryone = "Everyone";
|
const QString VisibleToEveryone = "Everyone";
|
||||||
const QString VisibleToFriends = "Friends";
|
const QString VisibleToFriends = "Friends";
|
||||||
const QString VisibleToNoOne = "No one";
|
const QString VisibleToNoOne = "No one";
|
||||||
|
|
|
@ -76,12 +76,41 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
||||||
if (isMine) {
|
if (isMine) {
|
||||||
MyAvatar* myAvatar = static_cast<MyAvatar*>(_owningAvatar);
|
MyAvatar* myAvatar = static_cast<MyAvatar*>(_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.
|
// Only use face trackers when not playing back a recording.
|
||||||
if (!myAvatar->isPlaying()) {
|
if (!myAvatar->isPlaying()) {
|
||||||
FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker();
|
FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker();
|
||||||
_isFaceTrackerConnected = faceTracker != NULL;
|
_isFaceTrackerConnected = faceTracker != NULL;
|
||||||
if (_isFaceTrackerConnected) {
|
if (_isFaceTrackerConnected) {
|
||||||
_blendshapeCoefficients = faceTracker->getBlendshapeCoefficients();
|
_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,
|
// 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);
|
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)) {
|
if (!(_isFaceTrackerConnected || billboard)) {
|
||||||
// Update eye saccades
|
// Update eye saccades
|
||||||
const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f;
|
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
|
// use data to update fake Faceshift blendshape coefficients
|
||||||
|
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);
|
|
||||||
|
|
||||||
DependencyManager::get<Faceshift>()->updateFakeCoefficients(_leftEyeBlink,
|
DependencyManager::get<Faceshift>()->updateFakeCoefficients(_leftEyeBlink,
|
||||||
_rightEyeBlink,
|
_rightEyeBlink,
|
||||||
_browAudioLift,
|
_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) {
|
void Head::relaxLean(float deltaTime) {
|
||||||
// restore rotation, lean to neutral positions
|
// restore rotation, lean to neutral positions
|
||||||
const float LEAN_RELAXATION_PERIOD = 0.25f; // seconds
|
const float LEAN_RELAXATION_PERIOD = 0.25f; // seconds
|
||||||
|
|
|
@ -154,6 +154,7 @@ private:
|
||||||
|
|
||||||
// private methods
|
// private methods
|
||||||
void renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition);
|
void renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition);
|
||||||
|
void calculateMouthShapes();
|
||||||
|
|
||||||
friend class FaceModel;
|
friend class FaceModel;
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
|
|
||||||
|
#include <GLMHelpers.h>
|
||||||
|
|
||||||
#include "DdeFaceTracker.h"
|
#include "DdeFaceTracker.h"
|
||||||
#include "FaceshiftConstants.h"
|
#include "FaceshiftConstants.h"
|
||||||
#include "InterfaceLogging.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_SERVER_PORT = 64204;
|
||||||
static const quint16 DDE_CONTROL_PORT = 64205;
|
static const quint16 DDE_CONTROL_PORT = 64205;
|
||||||
#if defined(Q_OS_WIN)
|
#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)
|
#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
|
#endif
|
||||||
static const QStringList DDE_ARGUMENTS = QStringList()
|
static const QStringList DDE_ARGUMENTS = QStringList()
|
||||||
<< "--udp=" + DDE_SERVER_ADDR.toString() + ":" + QString::number(DDE_SERVER_PORT)
|
<< "--udp=" + DDE_SERVER_ADDR.toString() + ":" + QString::number(DDE_SERVER_PORT)
|
||||||
|
@ -132,6 +134,8 @@ struct Packet {
|
||||||
char name[MAX_NAME_SIZE + 1];
|
char name[MAX_NAME_SIZE + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const float STARTING_DDE_MESSAGE_TIME = 0.033f;
|
||||||
|
|
||||||
DdeFaceTracker::DdeFaceTracker() :
|
DdeFaceTracker::DdeFaceTracker() :
|
||||||
DdeFaceTracker(QHostAddress::Any, DDE_SERVER_PORT, DDE_CONTROL_PORT)
|
DdeFaceTracker(QHostAddress::Any, DDE_SERVER_PORT, DDE_CONTROL_PORT)
|
||||||
{
|
{
|
||||||
|
@ -157,11 +161,16 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui
|
||||||
_mouthSmileLeftIndex(28),
|
_mouthSmileLeftIndex(28),
|
||||||
_mouthSmileRightIndex(29),
|
_mouthSmileRightIndex(29),
|
||||||
_jawOpenIndex(21),
|
_jawOpenIndex(21),
|
||||||
_previousTranslation(glm::vec3()),
|
_lastMessageReceived(0),
|
||||||
_previousRotation(glm::quat())
|
_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);
|
_coefficients.resize(NUM_FACESHIFT_BLENDSHAPES);
|
||||||
_previousCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES);
|
|
||||||
|
|
||||||
_blendshapeCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES);
|
_blendshapeCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES);
|
||||||
|
|
||||||
|
@ -182,9 +191,10 @@ void DdeFaceTracker::setEnabled(bool enabled) {
|
||||||
_udpSocket.bind(_host, _serverPort);
|
_udpSocket.bind(_host, _serverPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* DDE_EXIT_COMMAND = "exit";
|
||||||
|
|
||||||
if (enabled && !_ddeProcess) {
|
if (enabled && !_ddeProcess) {
|
||||||
// Terminate any existing DDE process, perhaps left running after an Interface crash
|
// 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);
|
_udpSocket.writeDatagram(DDE_EXIT_COMMAND, DDE_SERVER_ADDR, _controlPort);
|
||||||
|
|
||||||
qDebug() << "[Info] DDE Face Tracker Starting";
|
qDebug() << "[Info] DDE Face Tracker Starting";
|
||||||
|
@ -194,7 +204,8 @@ void DdeFaceTracker::setEnabled(bool enabled) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enabled && _ddeProcess) {
|
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;
|
_ddeProcess = NULL;
|
||||||
qDebug() << "[Info] DDE Face Tracker Stopped";
|
qDebug() << "[Info] DDE Face Tracker Stopped";
|
||||||
}
|
}
|
||||||
|
@ -270,6 +281,8 @@ float DdeFaceTracker::getBlendshapeCoefficient(int index) const {
|
||||||
|
|
||||||
void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
|
void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
|
||||||
if(buffer.size() > MIN_PACKET_SIZE) {
|
if(buffer.size() > MIN_PACKET_SIZE) {
|
||||||
|
bool isFiltering = Menu::getInstance()->isOptionChecked(MenuOption::DDEFiltering);
|
||||||
|
|
||||||
Packet packet;
|
Packet packet;
|
||||||
int bytesToCopy = glm::min((int)sizeof(packet), buffer.size());
|
int bytesToCopy = glm::min((int)sizeof(packet), buffer.size());
|
||||||
memset(&packet.name, '\n', MAX_NAME_SIZE + 1);
|
memset(&packet.name, '\n', MAX_NAME_SIZE + 1);
|
||||||
|
@ -290,13 +303,36 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
|
||||||
translation -= _referenceTranslation;
|
translation -= _referenceTranslation;
|
||||||
translation /= LEAN_DAMPING_FACTOR;
|
translation /= LEAN_DAMPING_FACTOR;
|
||||||
translation.x *= -1;
|
translation.x *= -1;
|
||||||
_headTranslation = (translation + _previousTranslation) / 2.0f;
|
if (isFiltering) {
|
||||||
_previousTranslation = translation;
|
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
|
// Compute relative rotation
|
||||||
rotation = glm::inverse(_referenceRotation) * rotation;
|
rotation = glm::inverse(_referenceRotation) * rotation;
|
||||||
_headRotation = (rotation + _previousRotation) / 2.0f;
|
if (isFiltering) {
|
||||||
_previousRotation = rotation;
|
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
|
// Translate DDE coefficients to Faceshift compatible coefficients
|
||||||
for (int i = 0; i < NUM_EXPRESSIONS; i += 1) {
|
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
|
// Use EyeBlink values to control both EyeBlink and EyeOpen
|
||||||
static const float RELAXED_EYE_VALUE = 0.1f;
|
static const float RELAXED_EYE_VALUE = 0.1f;
|
||||||
float leftEye = (_coefficients[_leftBlinkIndex] + _previousCoefficients[_leftBlinkIndex]) / 2.0f;
|
float leftEye = _coefficients[_leftBlinkIndex];
|
||||||
float rightEye = (_coefficients[_rightBlinkIndex] + _previousCoefficients[_rightBlinkIndex]) / 2.0f;
|
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) {
|
if (leftEye > RELAXED_EYE_VALUE) {
|
||||||
_coefficients[_leftBlinkIndex] = leftEye - RELAXED_EYE_VALUE;
|
_coefficients[_leftBlinkIndex] = leftEye - RELAXED_EYE_VALUE;
|
||||||
_coefficients[_leftEyeOpenIndex] = 0.0f;
|
_coefficients[_leftEyeOpenIndex] = 0.0f;
|
||||||
|
@ -341,10 +392,18 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
|
||||||
// Scale all coefficients
|
// Scale all coefficients
|
||||||
for (int i = 0; i < NUM_EXPRESSIONS; i += 1) {
|
for (int i = 0; i < NUM_EXPRESSIONS; i += 1) {
|
||||||
_blendshapeCoefficients[i]
|
_blendshapeCoefficients[i]
|
||||||
= glm::clamp(DDE_COEFFICIENT_SCALES[i] * (_coefficients[i] + _previousCoefficients[i]) / 2.0f, 0.0f, 1.0f);
|
= glm::clamp(DDE_COEFFICIENT_SCALES[i] * _coefficients[i], 0.0f, 1.0f);
|
||||||
_previousCoefficients[i] = _coefficients[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
} else {
|
||||||
qCDebug(interfaceapp) << "[Error] DDE Face Tracker Decode Error";
|
qCDebug(interfaceapp) << "[Error] DDE Face Tracker Decode Error";
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,10 +101,14 @@ private:
|
||||||
|
|
||||||
QVector<float> _coefficients;
|
QVector<float> _coefficients;
|
||||||
|
|
||||||
// Previous values for simple smoothing
|
quint64 _lastMessageReceived;
|
||||||
glm::vec3 _previousTranslation;
|
float _averageMessageTime;
|
||||||
glm::quat _previousRotation;
|
glm::vec3 _lastHeadTranslation;
|
||||||
QVector<float> _previousCoefficients;
|
glm::vec3 _filteredHeadTranslation;
|
||||||
|
float _lastLeftEyeBlink;
|
||||||
|
float _filteredLeftEyeBlink;
|
||||||
|
float _lastRightEyeBlink;
|
||||||
|
float _filteredRightEyeBlink;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_DdeFaceTracker_h
|
#endif // hifi_DdeFaceTracker_h
|
|
@ -18,7 +18,7 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
/// Base class for face trackers (Faceshift, Visage, DDE).
|
/// Base class for face trackers (Faceshift, DDE).
|
||||||
class FaceTracker : public QObject {
|
class FaceTracker : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
|
@ -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 <QHash>
|
|
||||||
|
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
|
||||||
#include <FBXReader.h>
|
|
||||||
#include <PathUtils.h>
|
|
||||||
#include <PerfStat.h>
|
|
||||||
#include <SharedUtil.h>
|
|
||||||
|
|
||||||
#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 <VisageTracker2.h>
|
|
||||||
#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<QByteArray, QPair<int, float> > createActionUnitNameMap() {
|
|
||||||
QMultiHash<QByteArray, QPair<QByteArray, float> > blendshapeMap;
|
|
||||||
blendshapeMap.insert("JawFwd", QPair<QByteArray, float>("au_jaw_z_push", 1.0f));
|
|
||||||
blendshapeMap.insert("JawLeft", QPair<QByteArray, float>("au_jaw_x_push", 1.0f));
|
|
||||||
blendshapeMap.insert("JawOpen", QPair<QByteArray, float>("au_jaw_drop", 1.0f));
|
|
||||||
blendshapeMap.insert("LipsLowerDown", QPair<QByteArray, float>("au_lower_lip_drop", 1.0f));
|
|
||||||
blendshapeMap.insert("LipsUpperOpen", QPair<QByteArray, float>("au_upper_lip_raiser", 1.0f));
|
|
||||||
blendshapeMap.insert("LipsStretch_R", QPair<QByteArray, float>("au_lip_stretcher_left", 0.5f));
|
|
||||||
blendshapeMap.insert("MouthSmile_L", QPair<QByteArray, float>("au_lip_corner_depressor", -1.0f));
|
|
||||||
blendshapeMap.insert("MouthSmile_R", QPair<QByteArray, float>("au_lip_corner_depressor", -1.0f));
|
|
||||||
blendshapeMap.insert("BrowsU_R", QPair<QByteArray, float>("au_left_outer_brow_raiser", 1.0f));
|
|
||||||
blendshapeMap.insert("BrowsU_C", QPair<QByteArray, float>("au_left_inner_brow_raiser", 1.0f));
|
|
||||||
blendshapeMap.insert("BrowsD_R", QPair<QByteArray, float>("au_left_brow_lowerer", 1.0f));
|
|
||||||
blendshapeMap.insert("EyeBlink_L", QPair<QByteArray, float>("au_leye_closed", 1.0f));
|
|
||||||
blendshapeMap.insert("EyeBlink_R", QPair<QByteArray, float>("au_reye_closed", 1.0f));
|
|
||||||
blendshapeMap.insert("EyeOpen_L", QPair<QByteArray, float>("au_upper_lid_raiser", 1.0f));
|
|
||||||
blendshapeMap.insert("EyeOpen_R", QPair<QByteArray, float>("au_upper_lid_raiser", 1.0f));
|
|
||||||
blendshapeMap.insert("LipLowerOpen", QPair<QByteArray, float>("au_lower_lip_x_push", 1.0f));
|
|
||||||
blendshapeMap.insert("LipsStretch_L", QPair<QByteArray, float>("au_lip_stretcher_right", 0.5f));
|
|
||||||
blendshapeMap.insert("BrowsU_L", QPair<QByteArray, float>("au_right_outer_brow_raiser", 1.0f));
|
|
||||||
blendshapeMap.insert("BrowsU_C", QPair<QByteArray, float>("au_right_inner_brow_raiser", 1.0f));
|
|
||||||
blendshapeMap.insert("BrowsD_L", QPair<QByteArray, float>("au_right_brow_lowerer", 1.0f));
|
|
||||||
|
|
||||||
QMultiHash<QByteArray, QPair<int, float> > 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<QByteArray, QPair<QByteArray, float> >::const_iterator it = blendshapeMap.constFind(blendshape);
|
|
||||||
it != blendshapeMap.constEnd() && it.key() == blendshape; it++) {
|
|
||||||
actionUnitNameMap.insert(it.value().first, QPair<int, float>(i, it.value().second));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return actionUnitNameMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const QMultiHash<QByteArray, QPair<int, float> >& getActionUnitNameMap() {
|
|
||||||
static QMultiHash<QByteArray, QPair<int, float> > actionUnitNameMap = createActionUnitNameMap();
|
|
||||||
return actionUnitNameMap;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_VISAGE
|
|
||||||
const float TRANSLATION_SCALE = 20.0f;
|
|
||||||
void Visage::init() {
|
|
||||||
connect(DependencyManager::get<Faceshift>().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<QByteArray, QPair<int, float> >::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<int, QPair<int, float> >::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<Faceshift>()->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
|
|
||||||
}
|
|
|
@ -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 <QMultiHash>
|
|
||||||
#include <QPair>
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
|
||||||
|
|
||||||
#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<int, QPair<int, float> > _actionUnitIndexMap;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void setEnabled(bool enabled);
|
|
||||||
|
|
||||||
bool _enabled;
|
|
||||||
|
|
||||||
glm::vec3 _headOrigin;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_Visage_h
|
|
|
@ -1705,7 +1705,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
||||||
material._material->setDiffuse(material.diffuse);
|
material._material->setDiffuse(material.diffuse);
|
||||||
material._material->setSpecular(material.specular);
|
material._material->setSpecular(material.specular);
|
||||||
material._material->setShininess(material.shininess);
|
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);
|
materials.insert(material.id, material);
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,10 @@ void Light::setIntensity(float intensity) {
|
||||||
editSchema()._intensity = intensity;
|
editSchema()._intensity = intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Light::setAmbientIntensity(float intensity) {
|
||||||
|
editSchema()._ambientIntensity = intensity;
|
||||||
|
}
|
||||||
|
|
||||||
void Light::setMaximumRadius(float radius) {
|
void Light::setMaximumRadius(float radius) {
|
||||||
if (radius <= 0.f) {
|
if (radius <= 0.f) {
|
||||||
radius = 1.0f;
|
radius = 1.0f;
|
||||||
|
|
|
@ -244,6 +244,10 @@ public:
|
||||||
void setShowContour(float show);
|
void setShowContour(float show);
|
||||||
float getShowContour() const { return getSchema()._control.w; }
|
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
|
// Spherical Harmonics storing the Ambien lighting approximation used for the Sun typed light
|
||||||
void setAmbientSphere(const SphericalHarmonics& sphere) { _ambientSphere = sphere; }
|
void setAmbientSphere(const SphericalHarmonics& sphere) { _ambientSphere = sphere; }
|
||||||
const SphericalHarmonics& getAmbientSphere() const { return _ambientSphere; }
|
const SphericalHarmonics& getAmbientSphere() const { return _ambientSphere; }
|
||||||
|
@ -254,14 +258,14 @@ public:
|
||||||
public:
|
public:
|
||||||
Vec4 _position{0.0f, 0.0f, 0.0f, 1.0f};
|
Vec4 _position{0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
Vec3 _direction{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};
|
Color _color{1.0f};
|
||||||
float _intensity{1.0f};
|
float _intensity{1.0f};
|
||||||
Vec4 _attenuation{1.0f};
|
Vec4 _attenuation{1.0f};
|
||||||
Vec4 _spot{0.0f, 0.0f, 0.0f, 3.0f};
|
Vec4 _spot{0.0f, 0.0f, 0.0f, 3.0f};
|
||||||
Vec4 _shadow{0.0f};
|
Vec4 _shadow{0.0f};
|
||||||
|
|
||||||
Vec4 _control{0.0f};
|
Vec4 _control{0.0f, 0.0f, 0.0f, 0.0f};
|
||||||
|
|
||||||
Schema() {}
|
Schema() {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,7 @@ vec3 getLightDirection(Light l) { return l._direction.xyz; } // direction is -Z
|
||||||
|
|
||||||
vec3 getLightColor(Light l) { return l._color.rgb; }
|
vec3 getLightColor(Light l) { return l._color.rgb; }
|
||||||
float getLightIntensity(Light l) { return l._color.w; }
|
float getLightIntensity(Light l) { return l._color.w; }
|
||||||
|
float getLightAmbientIntensity(Light l) { return l._direction.w; }
|
||||||
|
|
||||||
float evalLightAttenuation(Light l, float r) {
|
float evalLightAttenuation(Light l, float r) {
|
||||||
float d = max(r - l._attenuation.x, 0.0);
|
float d = max(r - l._attenuation.x, 0.0);
|
||||||
|
|
|
@ -203,6 +203,7 @@ SunSkyStage::SunSkyStage() :
|
||||||
_sunLight->setType(Light::SUN);
|
_sunLight->setType(Light::SUN);
|
||||||
|
|
||||||
setSunIntensity(1.0f);
|
setSunIntensity(1.0f);
|
||||||
|
setSunAmbientIntensity(0.5f);
|
||||||
setSunColor(Vec3(1.0f, 1.0f, 1.0f));
|
setSunColor(Vec3(1.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
// Default origin location is a special place in the world...
|
// Default origin location is a special place in the world...
|
||||||
|
@ -249,12 +250,26 @@ void SunSkyStage::setOriginLocation(float longitude, float latitude, float altit
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SunSkyStage::setSunModelEnable(bool isEnabled) {
|
||||||
|
_sunModelEnable = isEnabled;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
void SunSkyStage::setSunColor(const Vec3& color) {
|
void SunSkyStage::setSunColor(const Vec3& color) {
|
||||||
_sunLight->setColor(color);
|
_sunLight->setColor(color);
|
||||||
}
|
}
|
||||||
void SunSkyStage::setSunIntensity(float intensity) {
|
void SunSkyStage::setSunIntensity(float intensity) {
|
||||||
_sunLight->setIntensity(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
|
// THe sun declinaison calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun
|
||||||
double evalSunDeclinaison(double dayNumber) {
|
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
|
// And update the sunLAtitude as the declinaison depending of the time of the year
|
||||||
_earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime));
|
_earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime));
|
||||||
|
|
||||||
Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir();
|
if (isSunModelEnabled()) {
|
||||||
_sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z));
|
Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir();
|
||||||
|
_sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z));
|
||||||
|
|
||||||
double originAlt = _earthSunModel.getAltitude();
|
double originAlt = _earthSunModel.getAltitude();
|
||||||
_sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f));
|
_sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
static int firstTime = 0;
|
static int firstTime = 0;
|
||||||
if (firstTime == 0) {
|
if (firstTime == 0) {
|
||||||
firstTime++;
|
firstTime++;
|
||||||
gpu::Shader::makeProgram(*(_skyPipeline->getProgram()));
|
gpu::Shader::makeProgram(*(_skyPipeline->getProgram()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SunSkyStage::setSkybox(const SkyboxPointer& skybox) {
|
void SunSkyStage::setSkybox(const SkyboxPointer& skybox) {
|
||||||
|
|
|
@ -203,11 +203,21 @@ public:
|
||||||
float getOriginLongitude() const { return _earthSunModel.getLongitude(); }
|
float getOriginLongitude() const { return _earthSunModel.getLongitude(); }
|
||||||
float getOriginSurfaceAltitude() const { return _earthSunModel.getAltitude(); }
|
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
|
// Sun properties
|
||||||
void setSunColor(const Vec3& color);
|
void setSunColor(const Vec3& color);
|
||||||
const Vec3& getSunColor() const { return getSunLight()->getColor(); }
|
const Vec3& getSunColor() const { return getSunLight()->getColor(); }
|
||||||
void setSunIntensity(float intensity);
|
void setSunIntensity(float intensity);
|
||||||
float getSunIntensity() const { return getSunLight()->getIntensity(); }
|
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; }
|
LightPointer getSunLight() const { valid(); return _sunLight; }
|
||||||
AtmospherePointer getAtmosphere() const { valid(); return _atmosphere; }
|
AtmospherePointer getAtmosphere() const { valid(); return _atmosphere; }
|
||||||
|
@ -223,10 +233,10 @@ protected:
|
||||||
|
|
||||||
gpu::PipelinePointer _skyPipeline;
|
gpu::PipelinePointer _skyPipeline;
|
||||||
|
|
||||||
float _dayTime;
|
float _dayTime = 12.0f;
|
||||||
int _yearTime;
|
int _yearTime = 0;
|
||||||
|
|
||||||
mutable EarthSunModel _earthSunModel;
|
mutable EarthSunModel _earthSunModel;
|
||||||
|
bool _sunModelEnable = true;
|
||||||
|
|
||||||
mutable bool _invalid = true;
|
mutable bool _invalid = true;
|
||||||
void invalidate() const { _invalid = true; }
|
void invalidate() const { _invalid = true; }
|
||||||
|
|
|
@ -366,7 +366,7 @@ void AccountManager::setAccessTokenForCurrentAuthURL(const QString& accessToken)
|
||||||
OAuthAccessToken newOAuthToken;
|
OAuthAccessToken newOAuthToken;
|
||||||
newOAuthToken.token = accessToken;
|
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);
|
_accountInfo.setAccessToken(newOAuthToken);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,4 +12,16 @@ add_dependency_external_projects(glm)
|
||||||
find_package(GLM REQUIRED)
|
find_package(GLM REQUIRED)
|
||||||
target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS})
|
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)
|
link_hifi_libraries(animation fbx shared gpu)
|
|
@ -66,7 +66,7 @@ vec3 evalAmbienGlobalColor(float shadowAttenuation, vec3 position, vec3 normal,
|
||||||
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
|
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
|
||||||
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
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);
|
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 fragEyeDir = normalize(fragEyeVector.xyz);
|
||||||
|
|
||||||
vec3 ambientNormal = fragNormal.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);
|
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;
|
vec3 diffuseLight = lightAttenuation * lightmap;
|
||||||
|
|
||||||
// ambient is a tiny percentage of the lightmap and only when in the shadow
|
// 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);
|
return diffuse * (ambientLight + diffuseLight);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
auto light = _allocatedLights.front();
|
||||||
light->setDirection(direction);
|
light->setDirection(direction);
|
||||||
light->setColor(diffuse);
|
light->setColor(diffuse);
|
||||||
light->setIntensity(intensity);
|
light->setIntensity(intensity);
|
||||||
|
light->setAmbientIntensity(ambientIntensity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeferredLightingEffect::setGlobalSkybox(const model::SkyboxPointer& skybox) {
|
void DeferredLightingEffect::setGlobalSkybox(const model::SkyboxPointer& skybox) {
|
||||||
|
|
|
@ -73,7 +73,7 @@ public:
|
||||||
|
|
||||||
// update global lighting
|
// update global lighting
|
||||||
void setAmbientLightMode(int preset);
|
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 setGlobalAtmosphere(const model::AtmospherePointer& atmosphere) { _atmosphere = atmosphere; }
|
||||||
|
|
||||||
void setGlobalSkybox(const model::SkyboxPointer& skybox);
|
void setGlobalSkybox(const model::SkyboxPointer& skybox);
|
||||||
|
|
|
@ -244,13 +244,6 @@ void Model::initJointTransforms() {
|
||||||
|
|
||||||
void Model::init() {
|
void Model::init() {
|
||||||
if (_renderPipelineLib.empty()) {
|
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
|
// Vertex shaders
|
||||||
auto modelVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_vert)));
|
auto modelVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_vert)));
|
||||||
auto modelNormalMapVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_normal_map_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),
|
RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR),
|
||||||
modelNormalMapVertex, modelNormalSpecularMapPixel);
|
modelNormalMapVertex, modelNormalSpecularMapPixel);
|
||||||
|
|
||||||
|
|
||||||
_renderPipelineLib.addRenderPipeline(
|
_renderPipelineLib.addRenderPipeline(
|
||||||
RenderKey(RenderKey::IS_TRANSLUCENT),
|
RenderKey(RenderKey::IS_TRANSLUCENT),
|
||||||
modelVertex, modelTranslucentPixel);
|
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(
|
_renderPipelineLib.addRenderPipeline(
|
||||||
RenderKey(RenderKey::HAS_LIGHTMAP),
|
RenderKey(RenderKey::HAS_LIGHTMAP),
|
||||||
modelLightmapVertex, modelLightmapPixel);
|
modelLightmapVertex, modelLightmapPixel);
|
||||||
|
@ -310,6 +317,7 @@ void Model::init() {
|
||||||
RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR),
|
RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR),
|
||||||
modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel);
|
modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel);
|
||||||
|
|
||||||
|
|
||||||
_renderPipelineLib.addRenderPipeline(
|
_renderPipelineLib.addRenderPipeline(
|
||||||
RenderKey(RenderKey::IS_SKINNED),
|
RenderKey(RenderKey::IS_SKINNED),
|
||||||
skinModelVertex, modelPixel);
|
skinModelVertex, modelPixel);
|
||||||
|
@ -326,15 +334,29 @@ void Model::init() {
|
||||||
RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR),
|
RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR),
|
||||||
skinModelNormalMapVertex, modelNormalSpecularMapPixel);
|
skinModelNormalMapVertex, modelNormalSpecularMapPixel);
|
||||||
|
|
||||||
|
|
||||||
_renderPipelineLib.addRenderPipeline(
|
_renderPipelineLib.addRenderPipeline(
|
||||||
RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_TRANSLUCENT),
|
RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_TRANSLUCENT),
|
||||||
skinModelVertex, modelTranslucentPixel);
|
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(
|
_renderPipelineLib.addRenderPipeline(
|
||||||
RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW),
|
RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW),
|
||||||
modelShadowVertex, modelShadowPixel);
|
modelShadowVertex, modelShadowPixel);
|
||||||
|
|
||||||
|
|
||||||
_renderPipelineLib.addRenderPipeline(
|
_renderPipelineLib.addRenderPipeline(
|
||||||
RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW),
|
RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW),
|
||||||
skinModelShadowVertex, modelShadowPixel);
|
skinModelShadowVertex, modelShadowPixel);
|
||||||
|
@ -1732,6 +1754,12 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) {
|
||||||
void Model::endScene(RenderMode mode, RenderArgs* args) {
|
void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
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;
|
RenderArgs::RenderSide renderSide = RenderArgs::MONO;
|
||||||
if (args) {
|
if (args) {
|
||||||
renderSide = args->_renderSide;
|
renderSide = args->_renderSide;
|
||||||
|
@ -1899,6 +1927,12 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
backend.render(_sceneRenderBatch);
|
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
|
// restore all the default material settings
|
||||||
_viewState->setupWorldLight();
|
_viewState->setupWorldLight();
|
||||||
|
|
||||||
|
@ -1935,55 +1969,7 @@ bool Model::renderInScene(float alpha, RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::segregateMeshGroups() {
|
void Model::segregateMeshGroups() {
|
||||||
_meshesTranslucentTangents.clear();
|
_renderBuckets.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();
|
|
||||||
|
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
|
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
|
||||||
|
@ -2017,201 +2003,19 @@ void Model::segregateMeshGroups() {
|
||||||
qCDebug(renderutils) << "materialID:" << materialID << "parts:" << mesh.parts.size();
|
qCDebug(renderutils) << "materialID:" << materialID << "parts:" << mesh.parts.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasLightmap) {
|
RenderKey key(translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned);
|
||||||
if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) {
|
|
||||||
|
|
||||||
_unsortedMeshesTranslucent.insertMulti(materialID, i);
|
// reuse or create the bucket corresponding to that key and insert the mesh as unsorted
|
||||||
|
_renderBuckets[key.getRaw()]._unsortedMeshes.insertMulti(materialID, i);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (translucentMesh && hasTangents && !hasSpecular && !isSkinned) {
|
for(auto& b : _renderBuckets) {
|
||||||
|
foreach(auto i, b.second._unsortedMeshes) {
|
||||||
_unsortedMeshesTranslucentTangents.insertMulti(materialID, i);
|
b.second._meshes.append(i);
|
||||||
|
b.second._unsortedMeshes.clear();
|
||||||
} 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???";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(int i, _unsortedMeshesTranslucent) {
|
|
||||||
_meshesTranslucent.append(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
_meshGroupsKnown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2220,52 +2024,14 @@ QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool h
|
||||||
|
|
||||||
// depending on which parameters we were called with, pick the correct mesh group to render
|
// depending on which parameters we were called with, pick the correct mesh group to render
|
||||||
QVector<int>* whichList = NULL;
|
QVector<int>* 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) {
|
RenderKey key(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;
|
|
||||||
|
|
||||||
} else if (!translucent && hasLightmap && !hasTangents && !hasSpecular && !isSkinned) {
|
auto bucket = _renderBuckets.find(key.getRaw());
|
||||||
whichList = &_meshesOpaqueLightmap;
|
if (bucket != _renderBuckets.end()) {
|
||||||
} else if (!translucent && hasLightmap && hasTangents && !hasSpecular && !isSkinned) {
|
whichList = &(*bucket).second._meshes;
|
||||||
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???";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return whichList;
|
return whichList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2277,6 +2043,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
|
||||||
auto pipeline = _renderPipelineLib.find(key.getRaw());
|
auto pipeline = _renderPipelineLib.find(key.getRaw());
|
||||||
if (pipeline == _renderPipelineLib.end()) {
|
if (pipeline == _renderPipelineLib.end()) {
|
||||||
qDebug() << "No good, couldn't find a pipeline from the key ?" << key.getRaw();
|
qDebug() << "No good, couldn't find a pipeline from the key ?" << key.getRaw();
|
||||||
|
locations = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2303,7 +2070,7 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool
|
||||||
int meshPartsRendered = 0;
|
int meshPartsRendered = 0;
|
||||||
|
|
||||||
bool pickProgramsNeeded = true;
|
bool pickProgramsNeeded = true;
|
||||||
Locations* locations;
|
Locations* locations = nullptr;
|
||||||
|
|
||||||
foreach(Model* model, _modelsInScene) {
|
foreach(Model* model, _modelsInScene) {
|
||||||
QVector<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
|
QVector<int>* 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__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
int meshPartsRendered = 0;
|
int meshPartsRendered = 0;
|
||||||
|
|
||||||
|
//Pick the mesh list with the requested render flags
|
||||||
QVector<int>* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
|
QVector<int>* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
|
||||||
|
|
||||||
if (!whichList) {
|
if (!whichList) {
|
||||||
qCDebug(renderutils) << "unexpected!!! we don't know which list of meshes to render...";
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
QVector<int>& list = *whichList;
|
QVector<int>& list = *whichList;
|
||||||
|
|
||||||
// If this list has nothing to render, then don't bother proceeding. This saves us on binding to programs
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Locations* locations;
|
Locations* locations = nullptr;
|
||||||
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned,
|
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned,
|
||||||
args, locations);
|
args, locations);
|
||||||
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold,
|
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold,
|
||||||
|
|
|
@ -350,58 +350,6 @@ private:
|
||||||
|
|
||||||
bool _meshGroupsKnown;
|
bool _meshGroupsKnown;
|
||||||
|
|
||||||
QMap<QString, int> _unsortedMeshesTranslucent;
|
|
||||||
QMap<QString, int> _unsortedMeshesTranslucentTangents;
|
|
||||||
QMap<QString, int> _unsortedMeshesTranslucentTangentsSpecular;
|
|
||||||
QMap<QString, int> _unsortedMeshesTranslucentSpecular;
|
|
||||||
|
|
||||||
QMap<QString, int> _unsortedMeshesTranslucentSkinned;
|
|
||||||
QMap<QString, int> _unsortedMeshesTranslucentTangentsSkinned;
|
|
||||||
QMap<QString, int> _unsortedMeshesTranslucentTangentsSpecularSkinned;
|
|
||||||
QMap<QString, int> _unsortedMeshesTranslucentSpecularSkinned;
|
|
||||||
|
|
||||||
QMap<QString, int> _unsortedMeshesOpaque;
|
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueTangents;
|
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueTangentsSpecular;
|
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueSpecular;
|
|
||||||
|
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueSkinned;
|
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueTangentsSkinned;
|
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueTangentsSpecularSkinned;
|
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueSpecularSkinned;
|
|
||||||
|
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueLightmap;
|
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueLightmapTangents;
|
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueLightmapTangentsSpecular;
|
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueLightmapSpecular;
|
|
||||||
|
|
||||||
typedef std::unordered_map<int, QVector<int>> MeshListMap;
|
|
||||||
MeshListMap _sortedMeshes;
|
|
||||||
|
|
||||||
QVector<int> _meshesTranslucent;
|
|
||||||
QVector<int> _meshesTranslucentTangents;
|
|
||||||
QVector<int> _meshesTranslucentTangentsSpecular;
|
|
||||||
QVector<int> _meshesTranslucentSpecular;
|
|
||||||
|
|
||||||
QVector<int> _meshesTranslucentSkinned;
|
|
||||||
QVector<int> _meshesTranslucentTangentsSkinned;
|
|
||||||
QVector<int> _meshesTranslucentTangentsSpecularSkinned;
|
|
||||||
QVector<int> _meshesTranslucentSpecularSkinned;
|
|
||||||
|
|
||||||
QVector<int> _meshesOpaque;
|
|
||||||
QVector<int> _meshesOpaqueTangents;
|
|
||||||
QVector<int> _meshesOpaqueTangentsSpecular;
|
|
||||||
QVector<int> _meshesOpaqueSpecular;
|
|
||||||
|
|
||||||
QVector<int> _meshesOpaqueSkinned;
|
|
||||||
QVector<int> _meshesOpaqueTangentsSkinned;
|
|
||||||
QVector<int> _meshesOpaqueTangentsSpecularSkinned;
|
|
||||||
QVector<int> _meshesOpaqueSpecularSkinned;
|
|
||||||
|
|
||||||
QVector<int> _meshesOpaqueLightmap;
|
|
||||||
QVector<int> _meshesOpaqueLightmapTangents;
|
|
||||||
QVector<int> _meshesOpaqueLightmapTangentsSpecular;
|
|
||||||
QVector<int> _meshesOpaqueLightmapSpecular;
|
|
||||||
|
|
||||||
// debug rendering support
|
// debug rendering support
|
||||||
void renderDebugMeshBoxes();
|
void renderDebugMeshBoxes();
|
||||||
|
@ -490,6 +438,17 @@ private:
|
||||||
|
|
||||||
int getRaw() { return *reinterpret_cast<int*>(this); }
|
int getRaw() { return *reinterpret_cast<int*>(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,
|
RenderKey(RenderArgs::RenderMode mode,
|
||||||
bool translucent, float alphaThreshold, bool hasLightmap,
|
bool translucent, float alphaThreshold, bool hasLightmap,
|
||||||
bool hasTangents, bool hasSpecular, bool isSkinned) :
|
bool hasTangents, bool hasSpecular, bool isSkinned) :
|
||||||
|
@ -527,6 +486,19 @@ private:
|
||||||
};
|
};
|
||||||
static RenderPipelineLib _renderPipelineLib;
|
static RenderPipelineLib _renderPipelineLib;
|
||||||
|
|
||||||
|
|
||||||
|
class RenderBucket {
|
||||||
|
public:
|
||||||
|
QVector<int> _meshes;
|
||||||
|
QMap<QString, int> _unsortedMeshes;
|
||||||
|
};
|
||||||
|
typedef std::unordered_map<int, RenderBucket> BaseRenderBucketMap;
|
||||||
|
class RenderBucketMap : public BaseRenderBucketMap {
|
||||||
|
public:
|
||||||
|
typedef RenderKey Key;
|
||||||
|
};
|
||||||
|
RenderBucketMap _renderBuckets;
|
||||||
|
|
||||||
bool _renderCollisionHull;
|
bool _renderCollisionHull;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,22 +46,46 @@ int SceneScriptingInterface::getStageYearTime() const {
|
||||||
return _skyStage->getYearTime();
|
return _skyStage->getYearTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneScriptingInterface::setSunColor(const glm::vec3& color) {
|
void SceneScriptingInterface::setKeyLightColor(const glm::vec3& color) {
|
||||||
_skyStage->setSunColor(color);
|
_skyStage->setSunColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
const glm::vec3& SceneScriptingInterface::getSunColor() const {
|
glm::vec3 SceneScriptingInterface::getKeyLightColor() const {
|
||||||
return _skyStage->getSunColor();
|
return _skyStage->getSunColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneScriptingInterface::setSunIntensity(float intensity) {
|
void SceneScriptingInterface::setKeyLightIntensity(float intensity) {
|
||||||
_skyStage->setSunIntensity(intensity);
|
_skyStage->setSunIntensity(intensity);
|
||||||
}
|
}
|
||||||
|
|
||||||
float SceneScriptingInterface::getSunIntensity() const {
|
float SceneScriptingInterface::getKeyLightIntensity() const {
|
||||||
return _skyStage->getSunIntensity();
|
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 {
|
model::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const {
|
||||||
return _skyStage;
|
return _skyStage;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,10 +38,26 @@ public:
|
||||||
Q_INVOKABLE void setStageYearTime(int day);
|
Q_INVOKABLE void setStageYearTime(int day);
|
||||||
Q_INVOKABLE int getStageYearTime() const;
|
Q_INVOKABLE int getStageYearTime() const;
|
||||||
|
|
||||||
Q_INVOKABLE void setSunColor(const glm::vec3& color);
|
// Enable/disable the stage sun model which uses the key light to simulate
|
||||||
Q_INVOKABLE const glm::vec3& getSunColor() const;
|
// the sun light based on the location of the stage trelative to earth and the current time
|
||||||
Q_INVOKABLE void setSunIntensity(float intensity);
|
Q_INVOKABLE void setStageSunModelEnable(bool isEnabled);
|
||||||
Q_INVOKABLE float getSunIntensity() const;
|
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;
|
model::SunSkyStagePointer getSkyStage() const;
|
||||||
|
|
||||||
|
|
|
@ -647,8 +647,10 @@ void ScriptEngine::stopAllTimers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEngine::stop() {
|
void ScriptEngine::stop() {
|
||||||
_isFinished = true;
|
if (!_isFinished) {
|
||||||
emit runningStateChanged();
|
_isFinished = true;
|
||||||
|
emit runningStateChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEngine::timerFired() {
|
void ScriptEngine::timerFired() {
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
# add the tool directories
|
# add the tool directories
|
||||||
add_subdirectory(mtc)
|
add_subdirectory(mtc)
|
||||||
set_target_properties(mtc PROPERTIES FOLDER "Tools")
|
set_target_properties(mtc PROPERTIES FOLDER "Tools")
|
||||||
|
|
||||||
add_subdirectory(scribe)
|
add_subdirectory(scribe)
|
||||||
set_target_properties(scribe PROPERTIES FOLDER "Tools")
|
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()
|
|
||||||
|
|
18
tools/vhacd-util/CMakeLists.txt
Normal file
18
tools/vhacd-util/CMakeLists.txt
Normal file
|
@ -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 ()
|
|
@ -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})
|
|
Loading…
Reference in a new issue