From 98011da1efd15a7dca395b611a3d4df4ad43133e Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 8 Apr 2014 17:07:45 -0700 Subject: [PATCH 01/10] Starting on Faceplus integration. --- cmake/modules/FindFaceplus.cmake | 42 ++++++++++++++++++++++++++ interface/CMakeLists.txt | 9 ++++++ interface/external/faceplus/readme.txt | 9 ++++++ 3 files changed, 60 insertions(+) create mode 100644 cmake/modules/FindFaceplus.cmake create mode 100644 interface/external/faceplus/readme.txt diff --git a/cmake/modules/FindFaceplus.cmake b/cmake/modules/FindFaceplus.cmake new file mode 100644 index 0000000000..2a2083d6e4 --- /dev/null +++ b/cmake/modules/FindFaceplus.cmake @@ -0,0 +1,42 @@ +# Try to find the Faceplus library +# +# You must provide a FACEPLUS_ROOT_DIR which contains lib and include directories +# +# Once done this will define +# +# FACEPLUS_FOUND - system found Faceplus +# FACEPLUS_INCLUDE_DIRS - the Faceplus include directory +# FACEPLUS_LIBRARIES - Link this to use Faceplus +# +# Created on 4/8/2014 by Andrzej Kapolka +# Copyright (c) 2014 High Fidelity +# + +if (FACEPLUS_LIBRARIES AND FACEPLUS_INCLUDE_DIRS) + # in cache already + set(FACEPLUS_FOUND TRUE) +else (FACEPLUS_LIBRARIES AND FACEPLUS_INCLUDE_DIRS) + find_path(FACEPLUS_INCLUDE_DIRS faceplus.h ${FACEPLUS_ROOT_DIR}/include) + + if (WIN32) + find_library(FACEPLUS_LIBRARIES faceplus.lib ${FACEPLUS_ROOT_DIR}/win32/) + endif (WIN32) + + if (FACEPLUS_INCLUDE_DIRS AND FACEPLUS_LIBRARIES) + set(FACEPLUS_FOUND TRUE) + endif (FACEPLUS_INCLUDE_DIRS AND FACEPLUS_LIBRARIES) + + if (FACEPLUS_FOUND) + if (NOT FACEPLUS_FIND_QUIETLY) + message(STATUS "Found Faceplus... ${FACEPLUS_LIBRARIES}") + endif (NOT FACEPLUS_FIND_QUIETLY) + else () + if (FACEPLUS_FIND_REQUIRED) + message(FATAL_ERROR "Could not find Faceplus") + endif (FACEPLUS_FIND_REQUIRED) + endif () + + # show the FACEPLUS_INCLUDE_DIRS and FACEPLUS_LIBRARIES variables only in the advanced view + mark_as_advanced(FACEPLUS_INCLUDE_DIRS FACEPLUS_LIBRARIES) + +endif (FACEPLUS_LIBRARIES AND FACEPLUS_INCLUDE_DIRS) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 55d0a86d87..29943eb4cb 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -12,6 +12,7 @@ project(${TARGET_NAME}) # setup for find modules set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/") +set(FACEPLUS_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/faceplus") set(FACESHIFT_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/faceshift") set(LIBOVR_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/oculus") set(SIXENSE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/Sixense") @@ -130,6 +131,7 @@ link_hifi_library(audio ${TARGET_NAME} "${ROOT_DIR}") link_hifi_library(script-engine ${TARGET_NAME} "${ROOT_DIR}") # find any optional libraries +find_package(Faceplus) find_package(Faceshift) find_package(LibOVR) find_package(Sixense) @@ -163,6 +165,13 @@ if (VISAGE_FOUND AND NOT DISABLE_VISAGE) target_link_libraries(${TARGET_NAME} "${VISAGE_LIBRARIES}") endif (VISAGE_FOUND AND NOT DISABLE_VISAGE) +# and with Faceplus library, also for webcam feature tracking +if (FACEPLUS_FOUND AND NOT DISABLE_FACEPLUS) + add_definitions(-DHAVE_FACEPLUS) + include_directories(SYSTEM "${FACEPLUS_INCLUDE_DIRS}") + target_link_libraries(${TARGET_NAME} "${FACEPLUS_LIBRARIES}") +endif (FACEPLUS_FOUND AND NOT DISABLE_FACEPLUS) + # and with LibOVR for Oculus Rift if (LIBOVR_FOUND AND NOT DISABLE_LIBOVR) add_definitions(-DHAVE_LIBOVR) diff --git a/interface/external/faceplus/readme.txt b/interface/external/faceplus/readme.txt new file mode 100644 index 0000000000..322ea846bb --- /dev/null +++ b/interface/external/faceplus/readme.txt @@ -0,0 +1,9 @@ + +Instructions for adding the Faceplus driver to Interface +Andrzej Kapolka, April 8, 2014 + +1. Copy the Faceplus sdk folders (include, win32) into the interface/external/faceplus folder. + This readme.txt should be there as well. + +2. Delete your build directory, run cmake and build, and you should be all set. + From 5b0e7f818d623c064e21acc0566563a2a4326ad8 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 8 Apr 2014 18:03:49 -0700 Subject: [PATCH 02/10] More work on Faceplus integration/cleaning up support for multiple face trackers. --- interface/src/Application.cpp | 56 ++++++++++++++++----------- interface/src/Application.h | 7 +++- interface/src/avatar/MyAvatar.cpp | 24 ++++-------- interface/src/devices/FaceTracker.cpp | 14 +++++++ interface/src/devices/FaceTracker.h | 43 ++++++++++++++++++++ interface/src/devices/Faceplus.cpp | 32 +++++++++++++++ interface/src/devices/Faceplus.h | 34 ++++++++++++++++ interface/src/devices/Faceshift.cpp | 4 +- interface/src/devices/Faceshift.h | 19 ++------- interface/src/devices/Visage.cpp | 4 +- interface/src/devices/Visage.h | 21 ++-------- 11 files changed, 178 insertions(+), 80 deletions(-) create mode 100644 interface/src/devices/FaceTracker.cpp create mode 100644 interface/src/devices/FaceTracker.h create mode 100644 interface/src/devices/Faceplus.cpp create mode 100644 interface/src/devices/Faceplus.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 45ae36a23b..5c50f76767 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1342,6 +1342,12 @@ glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVox (mouseVoxel.z + mouseVoxel.s / 2.f) * TREE_SCALE); } +FaceTracker* Application::getActiveFaceTracker() { + return _faceshift.isActive() ? static_cast(&_faceshift) : + (_faceplus.isActive() ? static_cast(&_faceplus) : + (_visage.isActive() ? static_cast(&_visage) : NULL)); +} + struct SendVoxelsOperationArgs { const unsigned char* newBaseOctCode; }; @@ -1561,7 +1567,8 @@ void Application::init() { } qDebug("Loaded settings"); - // initialize Visage and Faceshift after loading the menu settings + // initialize our face trackers after loading the menu settings + _faceplus.init(); _faceshift.init(); _visage.init(); @@ -1682,6 +1689,15 @@ void Application::updateMouseRay() { _myAvatar->setMouseRay(_mouseRayOrigin, _mouseRayDirection); } +void Application::updateFaceplus() { + + bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); + PerformanceWarning warn(showWarnings, "Application::updateFaceplus()"); + + // Update faceplus + _faceplus.update(); +} + void Application::updateFaceshift() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); @@ -1726,19 +1742,11 @@ void Application::updateMyAvatarLookAtPosition() { glm::distance(_mouseRayOrigin, _myAvatar->getHead()->calculateAverageEyePosition())); lookAtSpot = _mouseRayOrigin + _mouseRayDirection * qMax(minEyeDistance, distance); } - bool trackerActive = false; - float eyePitch, eyeYaw; - if (_faceshift.isActive()) { - eyePitch = _faceshift.getEstimatedEyePitch(); - eyeYaw = _faceshift.getEstimatedEyeYaw(); - trackerActive = true; - - } else if (_visage.isActive()) { - eyePitch = _visage.getEstimatedEyePitch(); - eyeYaw = _visage.getEstimatedEyeYaw(); - trackerActive = true; - } - if (trackerActive) { + FaceTracker* tracker = getActiveFaceTracker(); + if (tracker) { + float eyePitch = tracker->getEstimatedEyePitch(); + float eyeYaw = tracker->getEstimatedEyeYaw(); + // deflect using Faceshift gaze data glm::vec3 origin = _myAvatar->getHead()->calculateAverageEyePosition(); float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f; @@ -1824,15 +1832,15 @@ void Application::updateCamera(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateCamera()"); - if (!OculusManager::isConnected() && !TV3DManager::isConnected()) { - if (Menu::getInstance()->isOptionChecked(MenuOption::OffAxisProjection)) { - float xSign = _myCamera.getMode() == CAMERA_MODE_MIRROR ? 1.0f : -1.0f; - if (_faceshift.isActive()) { - const float EYE_OFFSET_SCALE = 0.025f; - glm::vec3 position = _faceshift.getHeadTranslation() * EYE_OFFSET_SCALE; - _myCamera.setEyeOffsetPosition(glm::vec3(position.x * xSign, position.y, -position.z)); - updateProjectionMatrix(); - } + if (!OculusManager::isConnected() && !TV3DManager::isConnected() && + Menu::getInstance()->isOptionChecked(MenuOption::OffAxisProjection)) { + FaceTracker* tracker = getActiveFaceTracker(); + if (tracker) { + const float EYE_OFFSET_SCALE = 0.025f; + glm::vec3 position = tracker->getHeadTranslation() * EYE_OFFSET_SCALE; + float xSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? 1.0f : -1.0f; + _myCamera.setEyeOffsetPosition(glm::vec3(position.x * xSign, position.y, -position.z)); + updateProjectionMatrix(); } } } @@ -1886,6 +1894,7 @@ void Application::update(float deltaTime) { // check what's under the mouse and update the mouse voxel updateMouseRay(); + updateFaceplus(); updateFaceshift(); updateVisage(); _myAvatar->updateLookAtTargetAvatar(); @@ -2936,6 +2945,7 @@ void Application::resetSensors() { _mouseX = _glWidget->width() / 2; _mouseY = _glWidget->height() / 2; + _faceplus.reset(); _faceshift.reset(); _visage.reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 7c1cb9cab1..c6b38b1644 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -49,6 +49,7 @@ #include "avatar/Avatar.h" #include "avatar/AvatarManager.h" #include "avatar/MyAvatar.h" +#include "devices/Faceplus.h" #include "devices/Faceshift.h" #include "devices/SixenseManager.h" #include "devices/Visage.h" @@ -173,8 +174,10 @@ public: bool isMouseHidden() const { return _mouseHidden; } const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } + Faceplus* getFaceplus() { return &_faceplus; } Faceshift* getFaceshift() { return &_faceshift; } Visage* getVisage() { return &_visage; } + FaceTracker* getActiveFaceTracker(); SixenseManager* getSixenseManager() { return &_sixenseManager; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } QUndoStack* getUndoStack() { return &_undoStack; } @@ -313,6 +316,7 @@ private: // Various helper functions called during update() void updateLOD(); void updateMouseRay(); + void updateFaceplus(); void updateFaceshift(); void updateVisage(); void updateMyAvatarLookAtPosition(); @@ -412,9 +416,10 @@ private: AvatarManager _avatarManager; MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) + Faceplus _faceplus; Faceshift _faceshift; Visage _visage; - + SixenseManager _sixenseManager; Camera _myCamera; // My view onto the world diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 73d2a84eb7..6c7ac5b82c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -309,24 +309,13 @@ void MyAvatar::simulate(float deltaTime) { // Update avatar head rotation with sensor data void MyAvatar::updateFromGyros(float deltaTime) { - Faceshift* faceshift = Application::getInstance()->getFaceshift(); - Visage* visage = Application::getInstance()->getVisage(); glm::vec3 estimatedPosition, estimatedRotation; - bool trackerActive = false; - if (faceshift->isActive()) { - estimatedPosition = faceshift->getHeadTranslation(); - estimatedRotation = glm::degrees(safeEulerAngles(faceshift->getHeadRotation())); - trackerActive = true; - - } else if (visage->isActive()) { - estimatedPosition = visage->getHeadTranslation(); - estimatedRotation = glm::degrees(safeEulerAngles(visage->getHeadRotation())); - trackerActive = true; - } - - Head* head = getHead(); - if (trackerActive) { + FaceTracker* tracker = Application::getInstance()->getActiveFaceTracker(); + if (tracker) { + estimatedPosition = tracker->getHeadTranslation(); + estimatedRotation = glm::degrees(safeEulerAngles(tracker->getHeadRotation())); + // Rotate the body if the head is turned beyond the screen if (Menu::getInstance()->isOptionChecked(MenuOption::TurnWithHead)) { const float TRACKER_YAW_TURN_SENSITIVITY = 0.5f; @@ -341,13 +330,14 @@ void MyAvatar::updateFromGyros(float deltaTime) { } } } - } + } // Set the rotation of the avatar's head (as seen by others, not affecting view frustum) // to be scaled. Pitch is greater to emphasize nodding behavior / synchrony. const float AVATAR_HEAD_PITCH_MAGNIFY = 1.0f; const float AVATAR_HEAD_YAW_MAGNIFY = 1.0f; const float AVATAR_HEAD_ROLL_MAGNIFY = 1.0f; + Head* head = getHead(); head->setDeltaPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY); head->setDeltaYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY); head->setDeltaRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY); diff --git a/interface/src/devices/FaceTracker.cpp b/interface/src/devices/FaceTracker.cpp new file mode 100644 index 0000000000..45f789fbfe --- /dev/null +++ b/interface/src/devices/FaceTracker.cpp @@ -0,0 +1,14 @@ +// +// FaceTracker.cpp +// interface +// +// Created by Andrzej Kapolka on 4/8/14. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#include "FaceTracker.h" + +FaceTracker::FaceTracker() : + _estimatedEyePitch(0.0f), + _estimatedEyeYaw(0.0f) { +} diff --git a/interface/src/devices/FaceTracker.h b/interface/src/devices/FaceTracker.h new file mode 100644 index 0000000000..659defe591 --- /dev/null +++ b/interface/src/devices/FaceTracker.h @@ -0,0 +1,43 @@ +// +// FaceTracker.h +// interface +// +// Created by Andrzej Kapolka on 4/8/14. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__FaceTracker__ +#define __interface__FaceTracker__ + +#include +#include + +#include +#include + +/// Base class for face trackers (Faceshift, Visage, Faceplus). +class FaceTracker : public QObject { + Q_OBJECT + +public: + + FaceTracker(); + + const glm::vec3& getHeadTranslation() const { return _headTranslation; } + const glm::quat& getHeadRotation() const { return _headRotation; } + + float getEstimatedEyePitch() const { return _estimatedEyePitch; } + float getEstimatedEyeYaw() const { return _estimatedEyeYaw; } + + const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } + +protected: + + glm::vec3 _headTranslation; + glm::quat _headRotation; + float _estimatedEyePitch; + float _estimatedEyeYaw; + QVector _blendshapeCoefficients; +}; + +#endif /* defined(__interface__FaceTracker__) */ diff --git a/interface/src/devices/Faceplus.cpp b/interface/src/devices/Faceplus.cpp new file mode 100644 index 0000000000..64dd4bf52d --- /dev/null +++ b/interface/src/devices/Faceplus.cpp @@ -0,0 +1,32 @@ +// +// Faceplus.cpp +// interface +// +// Created by Andrzej Kapolka on 4/8/14. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifdef HAVE_FACEPLUS +#include +#endif + +#include "Faceplus.h" + +Faceplus::Faceplus() : + _active(false) { +} + +void Faceplus::init() { +#ifdef HAVE_FACEPLUS + // these are ignored--any values will do + faceplus_log_in("username", "password"); +#endif +} + +void Faceplus::update() { +} + +void Faceplus::reset() { +} + + diff --git a/interface/src/devices/Faceplus.h b/interface/src/devices/Faceplus.h new file mode 100644 index 0000000000..cf7a6583a1 --- /dev/null +++ b/interface/src/devices/Faceplus.h @@ -0,0 +1,34 @@ +// +// Faceplus.h +// interface +// +// Created by Andrzej Kapolka on 4/8/14. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__Faceplus__ +#define __interface__Faceplus__ + +#include "FaceTracker.h" + +/// Interface for Mixamo FacePlus. +class Faceplus : public FaceTracker { + Q_OBJECT + +public: + + Faceplus(); + + void init(); + + bool isActive() const { return _active; } + + void update(); + void reset(); + +private: + + bool _active; +}; + +#endif /* defined(__interface__Faceplus__) */ diff --git a/interface/src/devices/Faceshift.cpp b/interface/src/devices/Faceshift.cpp index 9f1734c7e5..05abcfd0d7 100644 --- a/interface/src/devices/Faceshift.cpp +++ b/interface/src/devices/Faceshift.cpp @@ -42,9 +42,7 @@ Faceshift::Faceshift() : _jawOpenIndex(21), _longTermAverageEyePitch(0.0f), _longTermAverageEyeYaw(0.0f), - _longTermAverageInitialized(false), - _estimatedEyePitch(0.0f), - _estimatedEyeYaw(0.0f) + _longTermAverageInitialized(false) { connect(&_tcpSocket, SIGNAL(connected()), SLOT(noteConnected())); connect(&_tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(noteError(QAbstractSocket::SocketError))); diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index f878056b57..c49c6661e7 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -17,8 +17,10 @@ #include +#include "FaceTracker.h" + /// Handles interaction with the Faceshift software, which provides head position/orientation and facial features. -class Faceshift : public QObject { +class Faceshift : public FaceTracker { Q_OBJECT public: @@ -31,9 +33,7 @@ public: bool isActive() const; - const glm::quat& getHeadRotation() const { return _headRotation; } const glm::vec3& getHeadAngularVelocity() const { return _headAngularVelocity; } - const glm::vec3& getHeadTranslation() const { return _headTranslation; } // these pitch/yaw angles are in degrees float getEyeGazeLeftPitch() const { return _eyeGazeLeftPitch; } @@ -42,11 +42,6 @@ public: float getEyeGazeRightPitch() const { return _eyeGazeRightPitch; } float getEyeGazeRightYaw() const { return _eyeGazeRightYaw; } - float getEstimatedEyePitch() const { return _estimatedEyePitch; } - float getEstimatedEyeYaw() const { return _estimatedEyeYaw; } - - const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } - float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); } float getRightBlink() const { return getBlendshapeCoefficient(_rightBlinkIndex); } float getLeftEyeOpen() const { return getBlendshapeCoefficient(_leftEyeOpenIndex); } @@ -99,9 +94,7 @@ private: bool _tracking; quint64 _lastTrackingStateReceived; - glm::quat _headRotation; glm::vec3 _headAngularVelocity; - glm::vec3 _headTranslation; // degrees float _eyeGazeLeftPitch; @@ -109,8 +102,6 @@ private: float _eyeGazeRightPitch; float _eyeGazeRightYaw; - QVector _blendshapeCoefficients; - int _leftBlinkIndex; int _rightBlinkIndex; int _leftEyeOpenIndex; @@ -132,10 +123,6 @@ private: float _longTermAverageEyePitch; float _longTermAverageEyeYaw; bool _longTermAverageInitialized; - - // degrees - float _estimatedEyePitch; - float _estimatedEyeYaw; }; #endif /* defined(__interface__Faceshift__) */ diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index b96ef1ee72..0cb534f8c3 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -34,9 +34,7 @@ const glm::vec3 DEFAULT_HEAD_ORIGIN(0.0f, 0.0f, 0.7f); Visage::Visage() : _enabled(false), _active(false), - _headOrigin(DEFAULT_HEAD_ORIGIN), - _estimatedEyePitch(0.0f), - _estimatedEyeYaw(0.0f) { + _headOrigin(DEFAULT_HEAD_ORIGIN) { #ifdef HAVE_VISAGE QByteArray licensePath = Application::resourcesPath().toLatin1() + "visage/license.vlc"; diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 6e98abbb61..0da87fb332 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -16,13 +16,15 @@ #include #include +#include "FaceTracker.h" + namespace VisageSDK { class VisageTracker2; struct FaceData; } /// Handles input from the Visage webcam feature tracking software. -class Visage : public QObject { +class Visage : public FaceTracker { Q_OBJECT public: @@ -34,14 +36,6 @@ public: bool isActive() const { return _active; } - const glm::quat& getHeadRotation() const { return _headRotation; } - const glm::vec3& getHeadTranslation() const { return _headTranslation; } - - float getEstimatedEyePitch() const { return _estimatedEyePitch; } - float getEstimatedEyeYaw() const { return _estimatedEyeYaw; } - - const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } - void update(); void reset(); @@ -61,15 +55,8 @@ private: bool _enabled; bool _active; - glm::quat _headRotation; - glm::vec3 _headTranslation; - + glm::vec3 _headOrigin; - - float _estimatedEyePitch; - float _estimatedEyeYaw; - - QVector _blendshapeCoefficients; }; #endif /* defined(__interface__Visage__) */ From 55e0035fc890b0e618e0c6439cc4a8a9c316a990 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 9 Apr 2014 11:14:47 -0700 Subject: [PATCH 03/10] More progress on Faceplus integration. --- interface/src/Menu.cpp | 5 ++ interface/src/Menu.h | 1 + interface/src/devices/Faceplus.cpp | 113 ++++++++++++++++++++++++++++- interface/src/devices/Faceplus.h | 17 +++++ interface/src/devices/Faceshift.h | 3 - interface/src/devices/Visage.cpp | 1 + interface/src/devices/Visage.h | 3 - 7 files changed, 135 insertions(+), 8 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8a97c98f02..b85f83ab05 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -301,6 +301,11 @@ Menu::Menu() : true, appInstance->getFaceshift(), SLOT(setTCPEnabled(bool))); +#ifdef HAVE_FACEPLUS + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Faceplus, 0, true, + appInstance->getFaceplus(), SLOT(updateEnabled())); +#endif + #ifdef HAVE_VISAGE addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Visage, 0, true, appInstance->getVisage(), SLOT(updateEnabled())); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 7bb0b75675..b7a82b0b0e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -250,6 +250,7 @@ namespace MenuOption { const QString EchoLocalAudio = "Echo Local Audio"; const QString EchoServerAudio = "Echo Server Audio"; const QString Enable3DTVMode = "Enable 3DTV Mode"; + const QString Faceplus = "Faceplus"; const QString Faceshift = "Faceshift"; const QString FilterSixense = "Smooth Sixense Movement"; const QString FirstPerson = "First Person"; diff --git a/interface/src/devices/Faceplus.cpp b/interface/src/devices/Faceplus.cpp index 64dd4bf52d..2e02126240 100644 --- a/interface/src/devices/Faceplus.cpp +++ b/interface/src/devices/Faceplus.cpp @@ -10,23 +10,132 @@ #include #endif +#include "Application.h" #include "Faceplus.h" +#include "renderer/FBXReader.h" Faceplus::Faceplus() : + _enabled(false), _active(false) { -} -void Faceplus::init() { #ifdef HAVE_FACEPLUS // these are ignored--any values will do faceplus_log_in("username", "password"); #endif } +Faceplus::~Faceplus() { + setEnabled(false); +} + +void Faceplus::init() { + connect(Application::getInstance()->getFaceshift(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled())); + updateEnabled(); +} + +#ifdef HAVE_FACEPLUS +static QMultiHash > createChannelNameMap() { + QMultiHash > blendshapeMap; + blendshapeMap.insert("JawFwd", QPair("au_jaw_z_push", 1.0f)); + blendshapeMap.insert("JawLeft", QPair("au_jaw_x_push", 1.0f)); + blendshapeMap.insert("JawOpen", QPair("au_jaw_drop", 1.0f)); + blendshapeMap.insert("LipsLowerDown", QPair("au_lower_lip_drop", 1.0f)); + blendshapeMap.insert("LipsUpperOpen", QPair("au_upper_lip_raiser", 1.0f)); + blendshapeMap.insert("LipsStretch_R", QPair("au_lip_stretcher_left", 0.5f)); + blendshapeMap.insert("MouthSmile_L", QPair("au_lip_corner_depressor", -1.0f)); + blendshapeMap.insert("MouthSmile_R", QPair("au_lip_corner_depressor", -1.0f)); + blendshapeMap.insert("BrowsU_R", QPair("au_left_outer_brow_raiser", 1.0f)); + blendshapeMap.insert("BrowsU_C", QPair("au_left_inner_brow_raiser", 1.0f)); + blendshapeMap.insert("BrowsD_R", QPair("au_left_brow_lowerer", 1.0f)); + blendshapeMap.insert("EyeBlink_L", QPair("au_leye_closed", 1.0f)); + blendshapeMap.insert("EyeBlink_R", QPair("au_reye_closed", 1.0f)); + blendshapeMap.insert("EyeOpen_L", QPair("au_upper_lid_raiser", 1.0f)); + blendshapeMap.insert("EyeOpen_R", QPair("au_upper_lid_raiser", 1.0f)); + blendshapeMap.insert("LipLowerOpen", QPair("au_lower_lip_x_push", 1.0f)); + blendshapeMap.insert("LipsStretch_L", QPair("au_lip_stretcher_right", 0.5f)); + blendshapeMap.insert("BrowsU_L", QPair("au_right_outer_brow_raiser", 1.0f)); + blendshapeMap.insert("BrowsU_C", QPair("au_right_inner_brow_raiser", 1.0f)); + blendshapeMap.insert("BrowsD_L", QPair("au_right_brow_lowerer", 1.0f)); + + QMultiHash > channelNameMap; + for (int i = 0;; i++) { + QByteArray blendshape = FACESHIFT_BLENDSHAPES[i]; + if (blendshape.isEmpty()) { + break; + } + for (QMultiHash >::const_iterator it = blendshapeMap.constFind(blendshape); + it != blendshapeMap.constEnd() && it.key() == blendshape; it++) { + channelNameMap.insert(it.value().first, QPair(i, it.value().second)); + } + } + + return channelNameMap; +} + +static const QMultiHash >& getChannelNameMap() { + static QMultiHash > channelNameMap = createChannelNameMap(); + return channelNameMap; +} +#endif + void Faceplus::update() { +#ifdef HAVE_FACEPLUS + if (!_active) { + return; + } + if (!(_active = faceplus_current_output_vector(_outputVector.data()))) { + return; + } + qFill(_blendshapeCoefficients.begin(), _blendshapeCoefficients.end(), 0.0f); + for (int i = 0; i < _outputVector.size(); i++) { + for (QMultiHash >::const_iterator it = _channelIndexMap.constFind(i); + it != _channelIndexMap.constEnd() && it.key() == i; it++) { + _blendshapeCoefficients[it.value().first] += _outputVector.at(i) * it.value().second; + } + } +#endif } void Faceplus::reset() { } +void Faceplus::updateEnabled() { + setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceplus) && + !(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && + Application::getInstance()->getFaceshift()->isConnectedOrConnecting())); +} +void Faceplus::setEnabled(bool enabled) { +#ifdef HAVE_FACEPLUS + if (_enabled == enabled) { + return; + } + if ((_enabled = enabled)) { + if (faceplus_init("VGA")) { + qDebug() << "Faceplus initialized."; + _active = true; + + int channelCount = faceplus_output_channels_count(); + _outputVector.resize(channelCount); + + int maxIndex = -1; + _channelIndexMap.clear(); + for (int i = 0; i < channelCount; i++) { + QByteArray channelName = faceplus_output_channel_name(i); + + qDebug() << channelName; + + for (QMultiHash >::const_iterator it = getChannelNameMap().constFind(name); + it != getChannelNameMap().constEnd() && it.key() == name; it++) { + _channelIndexMap.insert(i, it.value()); + maxIndex = qMax(maxIndex, it.value().first); + } + } + _blendshapeCoefficients.resize(maxIndex + 1); + } + } else if (faceplus_teardown()) { + qDebug() << "Faceplus torn down."; + _active = false; + } +#endif +} diff --git a/interface/src/devices/Faceplus.h b/interface/src/devices/Faceplus.h index cf7a6583a1..a511313d0c 100644 --- a/interface/src/devices/Faceplus.h +++ b/interface/src/devices/Faceplus.h @@ -9,6 +9,10 @@ #ifndef __interface__Faceplus__ #define __interface__Faceplus__ +#include +#include +#include + #include "FaceTracker.h" /// Interface for Mixamo FacePlus. @@ -18,6 +22,7 @@ class Faceplus : public FaceTracker { public: Faceplus(); + virtual ~Faceplus(); void init(); @@ -26,9 +31,21 @@ public: void update(); void reset(); +public slots: + + void updateEnabled(); + private: + void setEnabled(bool enabled); + + bool _enabled; bool _active; + +#ifdef HAVE_VISAGE + QMultiHash > _channelIndexMap; + QVector _outputVector; +#endif }; #endif /* defined(__interface__Faceplus__) */ diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index c49c6661e7..c245d648b8 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -12,9 +12,6 @@ #include #include -#include -#include - #include #include "FaceTracker.h" diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 0cb534f8c3..3792cc913d 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -159,6 +159,7 @@ void Visage::reset() { void Visage::updateEnabled() { setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) && + !Menu::getInstance()->isOptionChecked(MenuOption::Faceplus) && !(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && Application::getInstance()->getFaceshift()->isConnectedOrConnecting())); } diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 0da87fb332..1a02f5d7c3 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -13,9 +13,6 @@ #include #include -#include -#include - #include "FaceTracker.h" namespace VisageSDK { From 4deb052d5dde2f36d1c0771a015d81b57d487655 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 9 Apr 2014 11:54:55 -0700 Subject: [PATCH 04/10] More work on Faceplus integration. --- .gitignore | 4 ++ interface/external/faceplus/readme.txt | 4 +- interface/src/devices/Faceplus.cpp | 53 +++++++++++++++++++++++++- interface/src/devices/Faceplus.h | 2 +- 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index eb2f3ec303..c296a918af 100644 --- a/.gitignore +++ b/.gitignore @@ -42,5 +42,9 @@ interface/external/visage/* interface/resources/visage/* !interface/resources/visage/tracker.cfg +# Ignore Faceplus +interface/external/faceplus/* +!interface/external/faceplus/readme.txt + # Ignore interfaceCache for Linux users interface/interfaceCache/ diff --git a/interface/external/faceplus/readme.txt b/interface/external/faceplus/readme.txt index 322ea846bb..e98f8becdc 100644 --- a/interface/external/faceplus/readme.txt +++ b/interface/external/faceplus/readme.txt @@ -5,5 +5,7 @@ Andrzej Kapolka, April 8, 2014 1. Copy the Faceplus sdk folders (include, win32) into the interface/external/faceplus folder. This readme.txt should be there as well. -2. Delete your build directory, run cmake and build, and you should be all set. +2. Copy the Faceplus DLLs from the win32 folder into your path. + +3. Delete your build directory, run cmake and build, and you should be all set. diff --git a/interface/src/devices/Faceplus.cpp b/interface/src/devices/Faceplus.cpp index 2e02126240..89197a5acf 100644 --- a/interface/src/devices/Faceplus.cpp +++ b/interface/src/devices/Faceplus.cpp @@ -33,6 +33,55 @@ void Faceplus::init() { updateEnabled(); } +/* +[2014-04-09T11:42:11] "Mix::Blink_Left" +[2014-04-09T11:42:11] "Mix::Blink_Right" +[2014-04-09T11:42:11] "Mix::BrowsDown_Left" +[2014-04-09T11:42:11] "Mix::BrowsDown_Right" +[2014-04-09T11:42:11] "Mix::BrowsIn_Left" +[2014-04-09T11:42:11] "Mix::BrowsIn_Right" +[2014-04-09T11:42:11] "Mix::BrowsOuterLower_Left" +[2014-04-09T11:42:11] "Mix::BrowsOuterLower_Right" +[2014-04-09T11:42:11] "Mix::BrowsUp_Left" +[2014-04-09T11:42:11] "Mix::BrowsUp_Right" +[2014-04-09T11:42:11] "Mix::EyesWide_Left" +[2014-04-09T11:42:11] "Mix::EyesWide_Right" +[2014-04-09T11:42:11] "Mix::Frown_Left" +[2014-04-09T11:42:11] "Mix::Frown_Right" +[2014-04-09T11:42:11] "Mix::Jaw_RotateY_Left" +[2014-04-09T11:42:11] "Mix::Jaw_RotateY_Right" +[2014-04-09T11:42:11] "Mix::LowerLipDown_Left" +[2014-04-09T11:42:11] "Mix::LowerLipDown_Right" +[2014-04-09T11:42:11] "Mix::LowerLipIn" +[2014-04-09T11:42:11] "Mix::LowerLipOut" +[2014-04-09T11:42:11] "Mix::Midmouth_Left" +[2014-04-09T11:42:11] "Mix::Midmouth_Right" +[2014-04-09T11:42:11] "Mix::MouthDown" +[2014-04-09T11:42:11] "Mix::MouthNarrow_Left" +[2014-04-09T11:42:11] "Mix::MouthNarrow_Right" +[2014-04-09T11:42:11] "Mix::MouthOpen" +[2014-04-09T11:42:11] "Mix::MouthUp" +[2014-04-09T11:42:11] "Mix::MouthWhistle_NarrowAdjust_Left" +[2014-04-09T11:42:11] "Mix::MouthWhistle_NarrowAdjust_Right" +[2014-04-09T11:42:11] "Mix::NoseScrunch_Left" +[2014-04-09T11:42:11] "Mix::NoseScrunch_Right" +[2014-04-09T11:42:11] "Mix::Smile_Left" +[2014-04-09T11:42:11] "Mix::Smile_Right" +[2014-04-09T11:42:11] "Mix::Squint_Left" +[2014-04-09T11:42:11] "Mix::Squint_Right" +[2014-04-09T11:42:11] "Mix::UpperLipIn" +[2014-04-09T11:42:11] "Mix::UpperLipOut" +[2014-04-09T11:42:11] "Mix::UpperLipUp_Left" +[2014-04-09T11:42:11] "Mix::UpperLipUp_Right" +[2014-04-09T11:42:11] "Head_Joint::Rotation_X" +[2014-04-09T11:42:11] "Head_Joint::Rotation_Y" +[2014-04-09T11:42:11] "Head_Joint::Rotation_Z" +[2014-04-09T11:42:11] "Left_Eye_Joint::Rotation_X" +[2014-04-09T11:42:11] "Left_Eye_Joint::Rotation_Y" +[2014-04-09T11:42:11] "Right_Eye_Joint::Rotation_X" +[2014-04-09T11:42:11] "Right_Eye_Joint::Rotation_Y" +*/ + #ifdef HAVE_FACEPLUS static QMultiHash > createChannelNameMap() { QMultiHash > blendshapeMap; @@ -121,9 +170,9 @@ void Faceplus::setEnabled(bool enabled) { int maxIndex = -1; _channelIndexMap.clear(); for (int i = 0; i < channelCount; i++) { - QByteArray channelName = faceplus_output_channel_name(i); + QByteArray name = faceplus_output_channel_name(i); - qDebug() << channelName; + qDebug() << name; for (QMultiHash >::const_iterator it = getChannelNameMap().constFind(name); it != getChannelNameMap().constEnd() && it.key() == name; it++) { diff --git a/interface/src/devices/Faceplus.h b/interface/src/devices/Faceplus.h index a511313d0c..1e3272906c 100644 --- a/interface/src/devices/Faceplus.h +++ b/interface/src/devices/Faceplus.h @@ -42,7 +42,7 @@ private: bool _enabled; bool _active; -#ifdef HAVE_VISAGE +#ifdef HAVE_FACEPLUS QMultiHash > _channelIndexMap; QVector _outputVector; #endif From 4d9f3a4aee436af3295455201df83923560d2b52 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 9 Apr 2014 12:36:02 -0700 Subject: [PATCH 05/10] Added basic mappings to start off with. --- interface/src/devices/Faceplus.cpp | 133 ++++++++++++++--------------- interface/src/devices/Faceplus.h | 3 + 2 files changed, 66 insertions(+), 70 deletions(-) diff --git a/interface/src/devices/Faceplus.cpp b/interface/src/devices/Faceplus.cpp index 89197a5acf..ccbc494fe3 100644 --- a/interface/src/devices/Faceplus.cpp +++ b/interface/src/devices/Faceplus.cpp @@ -33,78 +33,48 @@ void Faceplus::init() { updateEnabled(); } -/* -[2014-04-09T11:42:11] "Mix::Blink_Left" -[2014-04-09T11:42:11] "Mix::Blink_Right" -[2014-04-09T11:42:11] "Mix::BrowsDown_Left" -[2014-04-09T11:42:11] "Mix::BrowsDown_Right" -[2014-04-09T11:42:11] "Mix::BrowsIn_Left" -[2014-04-09T11:42:11] "Mix::BrowsIn_Right" -[2014-04-09T11:42:11] "Mix::BrowsOuterLower_Left" -[2014-04-09T11:42:11] "Mix::BrowsOuterLower_Right" -[2014-04-09T11:42:11] "Mix::BrowsUp_Left" -[2014-04-09T11:42:11] "Mix::BrowsUp_Right" -[2014-04-09T11:42:11] "Mix::EyesWide_Left" -[2014-04-09T11:42:11] "Mix::EyesWide_Right" -[2014-04-09T11:42:11] "Mix::Frown_Left" -[2014-04-09T11:42:11] "Mix::Frown_Right" -[2014-04-09T11:42:11] "Mix::Jaw_RotateY_Left" -[2014-04-09T11:42:11] "Mix::Jaw_RotateY_Right" -[2014-04-09T11:42:11] "Mix::LowerLipDown_Left" -[2014-04-09T11:42:11] "Mix::LowerLipDown_Right" -[2014-04-09T11:42:11] "Mix::LowerLipIn" -[2014-04-09T11:42:11] "Mix::LowerLipOut" -[2014-04-09T11:42:11] "Mix::Midmouth_Left" -[2014-04-09T11:42:11] "Mix::Midmouth_Right" -[2014-04-09T11:42:11] "Mix::MouthDown" -[2014-04-09T11:42:11] "Mix::MouthNarrow_Left" -[2014-04-09T11:42:11] "Mix::MouthNarrow_Right" -[2014-04-09T11:42:11] "Mix::MouthOpen" -[2014-04-09T11:42:11] "Mix::MouthUp" -[2014-04-09T11:42:11] "Mix::MouthWhistle_NarrowAdjust_Left" -[2014-04-09T11:42:11] "Mix::MouthWhistle_NarrowAdjust_Right" -[2014-04-09T11:42:11] "Mix::NoseScrunch_Left" -[2014-04-09T11:42:11] "Mix::NoseScrunch_Right" -[2014-04-09T11:42:11] "Mix::Smile_Left" -[2014-04-09T11:42:11] "Mix::Smile_Right" -[2014-04-09T11:42:11] "Mix::Squint_Left" -[2014-04-09T11:42:11] "Mix::Squint_Right" -[2014-04-09T11:42:11] "Mix::UpperLipIn" -[2014-04-09T11:42:11] "Mix::UpperLipOut" -[2014-04-09T11:42:11] "Mix::UpperLipUp_Left" -[2014-04-09T11:42:11] "Mix::UpperLipUp_Right" -[2014-04-09T11:42:11] "Head_Joint::Rotation_X" -[2014-04-09T11:42:11] "Head_Joint::Rotation_Y" -[2014-04-09T11:42:11] "Head_Joint::Rotation_Z" -[2014-04-09T11:42:11] "Left_Eye_Joint::Rotation_X" -[2014-04-09T11:42:11] "Left_Eye_Joint::Rotation_Y" -[2014-04-09T11:42:11] "Right_Eye_Joint::Rotation_X" -[2014-04-09T11:42:11] "Right_Eye_Joint::Rotation_Y" -*/ - #ifdef HAVE_FACEPLUS static QMultiHash > createChannelNameMap() { QMultiHash > blendshapeMap; - blendshapeMap.insert("JawFwd", QPair("au_jaw_z_push", 1.0f)); - blendshapeMap.insert("JawLeft", QPair("au_jaw_x_push", 1.0f)); - blendshapeMap.insert("JawOpen", QPair("au_jaw_drop", 1.0f)); - blendshapeMap.insert("LipsLowerDown", QPair("au_lower_lip_drop", 1.0f)); - blendshapeMap.insert("LipsUpperOpen", QPair("au_upper_lip_raiser", 1.0f)); - blendshapeMap.insert("LipsStretch_R", QPair("au_lip_stretcher_left", 0.5f)); - blendshapeMap.insert("MouthSmile_L", QPair("au_lip_corner_depressor", -1.0f)); - blendshapeMap.insert("MouthSmile_R", QPair("au_lip_corner_depressor", -1.0f)); - blendshapeMap.insert("BrowsU_R", QPair("au_left_outer_brow_raiser", 1.0f)); - blendshapeMap.insert("BrowsU_C", QPair("au_left_inner_brow_raiser", 1.0f)); - blendshapeMap.insert("BrowsD_R", QPair("au_left_brow_lowerer", 1.0f)); - blendshapeMap.insert("EyeBlink_L", QPair("au_leye_closed", 1.0f)); - blendshapeMap.insert("EyeBlink_R", QPair("au_reye_closed", 1.0f)); - blendshapeMap.insert("EyeOpen_L", QPair("au_upper_lid_raiser", 1.0f)); - blendshapeMap.insert("EyeOpen_R", QPair("au_upper_lid_raiser", 1.0f)); - blendshapeMap.insert("LipLowerOpen", QPair("au_lower_lip_x_push", 1.0f)); - blendshapeMap.insert("LipsStretch_L", QPair("au_lip_stretcher_right", 0.5f)); - blendshapeMap.insert("BrowsU_L", QPair("au_right_outer_brow_raiser", 1.0f)); - blendshapeMap.insert("BrowsU_C", QPair("au_right_inner_brow_raiser", 1.0f)); - blendshapeMap.insert("BrowsD_L", QPair("au_right_brow_lowerer", 1.0f)); + blendshapeMap.insert("EyeBlink_L", QPair("Mix::Blink_Left", 1.0f)); + blendshapeMap.insert("EyeBlink_R", QPair("Mix::Blink_Right", 1.0f)); + blendshapeMap.insert("BrowsD_L", QPair("Mix::BrowsDown_Left", 1.0f)); + blendshapeMap.insert("BrowsD_R", QPair("Mix::BrowsDown_Right", 1.0f)); + blendshapeMap.insert("...", QPair("Mix::BrowsIn_Left", 1.0f)); + blendshapeMap.insert("...", QPair("Mix::BrowsIn_Right", 1.0f)); + blendshapeMap.insert("...", QPair("Mix::BrowsOuterLower_Left", 1.0f)); + blendshapeMap.insert("...", QPair("Mix::BrowsOuterLower_Right", 1.0f)); + blendshapeMap.insert("BrowsU_L", QPair("Mix::BrowsUp_Left", 1.0f)); + blendshapeMap.insert("BrowsU_R", QPair("Mix::BrowsUp_Right", 1.0f)); + blendshapeMap.insert("EyeOpen_L", QPair("Mix::EyesWide_Left", 1.0f)); + blendshapeMap.insert("EyeOpen_R", QPair("Mix::EyesWide_Right", 1.0f)); + blendshapeMap.insert("MouthFrown_L", QPair("Mix::Frown_Left", 1.0f)); + blendshapeMap.insert("MouthFrown_R", QPair("Mix::Frown_Right", 1.0f)); + blendshapeMap.insert("JawLeft", QPair("Mix::Jaw_RotateY_Left", 1.0f)); + blendshapeMap.insert("JawRight", QPair("Mix::Jaw_RotateY_Right", 1.0f)); + blendshapeMap.insert("LipsLowerDown", QPair("Mix::LowerLipDown_Left", 0.5f)); + blendshapeMap.insert("LipsLowerDown", QPair("Mix::LowerLipDown_Right", 0.5f)); + blendshapeMap.insert("...", QPair("Mix::LowerLipIn", 1.0f)); + blendshapeMap.insert("...", QPair("Mix::LowerLipOut", 1.0f)); + blendshapeMap.insert("MouthLeft", QPair("Mix::Midmouth_Left", 1.0f)); + blendshapeMap.insert("MouthRight", QPair("Mix::Midmouth_Right", 1.0f)); + blendshapeMap.insert("...", QPair("Mix::MouthDown", 1.0f)); + blendshapeMap.insert("...", QPair("Mix::MouthNarrow_Left", 1.0f)); + blendshapeMap.insert("...", QPair("Mix::MouthNarrow_Right", 1.0f)); + blendshapeMap.insert("JawOpen", QPair("Mix::MouthOpen", 1.0f)); + blendshapeMap.insert("...", QPair("Mix::MouthUp", 1.0f)); + blendshapeMap.insert("LipsPucker", QPair("Mix::MouthWhistle_NarrowAdjust_Left", 0.5f)); + blendshapeMap.insert("LipsPucker", QPair("Mix::MouthWhistle_NarrowAdjust_Right", 0.5f)); + blendshapeMap.insert("Sneer", QPair("Mix::NoseScrunch_Left", 0.5f)); + blendshapeMap.insert("Sneer", QPair("Mix::NoseScrunch_Right", 0.5f)); + blendshapeMap.insert("MouthSmile_L", QPair("Mix::Smile_Left", 1.0f)); + blendshapeMap.insert("MouthSmile_R", QPair("Mix::Smile_Right", 1.0f)); + blendshapeMap.insert("EyeSquint_L", QPair("Mix::Squint_Left", 1.0f)); + blendshapeMap.insert("EyeSquint_R", QPair("Mix::Squint_Right", 1.0f)); + blendshapeMap.insert("...", QPair("Mix::UpperLipIn", 1.0f)); + blendshapeMap.insert("...", QPair("Mix::UpperLipOut", 1.0f)); + blendshapeMap.insert("LipsUpperUp", QPair("Mix::UpperLipUp_Left", 0.5f)); + blendshapeMap.insert("LipsUpperUp", QPair("Mix::UpperLipUp_Right", 0.5f)); QMultiHash > channelNameMap; for (int i = 0;; i++) { @@ -135,6 +105,11 @@ void Faceplus::update() { if (!(_active = faceplus_current_output_vector(_outputVector.data()))) { return; } + _headRotation = glm::quat(glm::radians(_outputVector.at(_headRotationIndices[0]), + _outputVector.at(_headRotationIndices[1]), _outputVector.at(_headRotationIndices[2]))); + _estimatedEyePitch = (_outputVector.at(_leftEyeRotationIndices[0]) + _outputVector.at(_rightEyeRotationIndices[0])) * 0.5f; + _estimatedEyeYaw = (_outputVector.at(_leftEyeRotationIndices[1]) + _outputVector.at(_rightEyeRotationIndices[1])) * 0.5f; + qFill(_blendshapeCoefficients.begin(), _blendshapeCoefficients.end(), 0.0f); for (int i = 0; i < _outputVector.size(); i++) { for (QMultiHash >::const_iterator it = _channelIndexMap.constFind(i); @@ -171,9 +146,27 @@ void Faceplus::setEnabled(bool enabled) { _channelIndexMap.clear(); for (int i = 0; i < channelCount; i++) { QByteArray name = faceplus_output_channel_name(i); + if (name == "Head_Joint::Rotation_X") { + _headRotationIndices[0] = i; - qDebug() << name; + } else if (name == "Head_Joint::Rotation_Y") { + _headRotationIndices[1] = i; + } else if (name == "Head_Joint::Rotation_Z") { + _headRotationIndices[2] = i; + + } else if (name == "Left_Eye_Joint::Rotation_X") { + _leftEyeRotationIndices[0] = i; + + } else if (name == "Left_Eye_Joint::Rotation_Y") { + _leftEyeRotationIndices[1] = i; + + } else if (name == "Right_Eye_Joint::Rotation_X") { + _rightEyeRotationIndices[0] = i; + + } else if (name == "Right_Eye_Joint::Rotation_Y") { + _rightEyeRotationIndices[1] = i; + } for (QMultiHash >::const_iterator it = getChannelNameMap().constFind(name); it != getChannelNameMap().constEnd() && it.key() == name; it++) { _channelIndexMap.insert(i, it.value()); diff --git a/interface/src/devices/Faceplus.h b/interface/src/devices/Faceplus.h index 1e3272906c..164cf4d031 100644 --- a/interface/src/devices/Faceplus.h +++ b/interface/src/devices/Faceplus.h @@ -45,6 +45,9 @@ private: #ifdef HAVE_FACEPLUS QMultiHash > _channelIndexMap; QVector _outputVector; + int _headRotationIndices[3]; + int _leftEyeRotationIndices[2]; + int _rightEyeRotationIndices[2]; #endif }; From 79455d5850936f1483dc7e2532be76311c46ae7b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 9 Apr 2014 13:07:02 -0700 Subject: [PATCH 06/10] More Faceplus work. Starting to get results. --- interface/src/Application.cpp | 4 ++-- interface/src/avatar/Head.cpp | 19 +++++++------------ interface/src/devices/Faceplus.cpp | 12 ++++++------ 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5c50f76767..dedbbced30 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1568,9 +1568,9 @@ void Application::init() { qDebug("Loaded settings"); // initialize our face trackers after loading the menu settings - _faceplus.init(); _faceshift.init(); - _visage.init(); + _faceplus.init(); + _visage.init(); // fire off an immediate domain-server check in now that settings are loaded NodeList::getInstance()->sendDomainServerCheckIn(); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index f42220c0f4..c3cff15c70 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -60,17 +60,11 @@ void Head::reset() { void Head::simulate(float deltaTime, bool isMine, bool billboard) { // Update audio trailing average for rendering facial animations - Faceshift* faceshift = Application::getInstance()->getFaceshift(); - Visage* visage = Application::getInstance()->getVisage(); if (isMine) { - _isFaceshiftConnected = false; - if (faceshift->isActive()) { - _blendshapeCoefficients = faceshift->getBlendshapeCoefficients(); - _isFaceshiftConnected = true; - - } else if (visage->isActive()) { - _blendshapeCoefficients = visage->getBlendshapeCoefficients(); - _isFaceshiftConnected = true; + FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); + if ((_isFaceshiftConnected = faceTracker)) { + _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); + _isFaceshiftConnected = true; } } @@ -152,8 +146,9 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { const float BROW_LIFT_SCALE = 500.0f; const float JAW_OPEN_SCALE = 0.01f; const float JAW_OPEN_DEAD_ZONE = 0.75f; - faceshift->updateFakeCoefficients(_leftEyeBlink, _rightEyeBlink, min(1.0f, _browAudioLift * BROW_LIFT_SCALE), - glm::clamp(sqrt(_averageLoudness * JAW_OPEN_SCALE) - JAW_OPEN_DEAD_ZONE, 0.0f, 1.0f), _blendshapeCoefficients); + Application::getInstance()->getFaceshift()->updateFakeCoefficients(_leftEyeBlink, _rightEyeBlink, + min(1.0f, _browAudioLift * BROW_LIFT_SCALE), glm::clamp(sqrt(_averageLoudness * JAW_OPEN_SCALE) - + JAW_OPEN_DEAD_ZONE, 0.0f, 1.0f), _blendshapeCoefficients); } if (!isMine) { diff --git a/interface/src/devices/Faceplus.cpp b/interface/src/devices/Faceplus.cpp index ccbc494fe3..9a3067e48f 100644 --- a/interface/src/devices/Faceplus.cpp +++ b/interface/src/devices/Faceplus.cpp @@ -44,8 +44,8 @@ static QMultiHash > createChannelNameMap() { blendshapeMap.insert("...", QPair("Mix::BrowsIn_Right", 1.0f)); blendshapeMap.insert("...", QPair("Mix::BrowsOuterLower_Left", 1.0f)); blendshapeMap.insert("...", QPair("Mix::BrowsOuterLower_Right", 1.0f)); - blendshapeMap.insert("BrowsU_L", QPair("Mix::BrowsUp_Left", 1.0f)); - blendshapeMap.insert("BrowsU_R", QPair("Mix::BrowsUp_Right", 1.0f)); + blendshapeMap.insert("BrowsU_L", QPair("Mix::BrowsUp_Left", 5.0f)); + blendshapeMap.insert("BrowsU_R", QPair("Mix::BrowsUp_Right", 5.0f)); blendshapeMap.insert("EyeOpen_L", QPair("Mix::EyesWide_Left", 1.0f)); blendshapeMap.insert("EyeOpen_R", QPair("Mix::EyesWide_Right", 1.0f)); blendshapeMap.insert("MouthFrown_L", QPair("Mix::Frown_Left", 1.0f)); @@ -102,12 +102,12 @@ void Faceplus::update() { if (!_active) { return; } - if (!(_active = faceplus_current_output_vector(_outputVector.data()))) { + if (!(_active = faceplus_synchronous_track() && faceplus_current_output_vector(_outputVector.data()))) { return; } - _headRotation = glm::quat(glm::radians(_outputVector.at(_headRotationIndices[0]), - _outputVector.at(_headRotationIndices[1]), _outputVector.at(_headRotationIndices[2]))); - _estimatedEyePitch = (_outputVector.at(_leftEyeRotationIndices[0]) + _outputVector.at(_rightEyeRotationIndices[0])) * 0.5f; + _headRotation = glm::quat(glm::radians(glm::vec3(-_outputVector.at(_headRotationIndices[0]), + _outputVector.at(_headRotationIndices[1]), -_outputVector.at(_headRotationIndices[2])))); + _estimatedEyePitch = (_outputVector.at(_leftEyeRotationIndices[0]) + _outputVector.at(_rightEyeRotationIndices[0])) * -0.5f; _estimatedEyeYaw = (_outputVector.at(_leftEyeRotationIndices[1]) + _outputVector.at(_rightEyeRotationIndices[1])) * 0.5f; qFill(_blendshapeCoefficients.begin(), _blendshapeCoefficients.end(), 0.0f); From 28d3eae12b08eed5655a3419d3eace5036d068da Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 9 Apr 2014 14:52:27 -0700 Subject: [PATCH 07/10] Move Faceplus reading to its own thread to avoid blocking the main one. --- interface/src/Application.cpp | 11 -- interface/src/Application.h | 1 - interface/src/devices/Faceplus.cpp | 173 ++++++++++++++++++----------- interface/src/devices/Faceplus.h | 24 +++- 4 files changed, 127 insertions(+), 82 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dedbbced30..6e05167d6f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1689,15 +1689,6 @@ void Application::updateMouseRay() { _myAvatar->setMouseRay(_mouseRayOrigin, _mouseRayDirection); } -void Application::updateFaceplus() { - - bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showWarnings, "Application::updateFaceplus()"); - - // Update faceplus - _faceplus.update(); -} - void Application::updateFaceshift() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); @@ -1894,7 +1885,6 @@ void Application::update(float deltaTime) { // check what's under the mouse and update the mouse voxel updateMouseRay(); - updateFaceplus(); updateFaceshift(); updateVisage(); _myAvatar->updateLookAtTargetAvatar(); @@ -2945,7 +2935,6 @@ void Application::resetSensors() { _mouseX = _glWidget->width() / 2; _mouseY = _glWidget->height() / 2; - _faceplus.reset(); _faceshift.reset(); _visage.reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index c6b38b1644..7182010050 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -174,7 +174,6 @@ public: bool isMouseHidden() const { return _mouseHidden; } const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } - Faceplus* getFaceplus() { return &_faceplus; } Faceshift* getFaceshift() { return &_faceshift; } Visage* getVisage() { return &_visage; } FaceTracker* getActiveFaceTracker(); diff --git a/interface/src/devices/Faceplus.cpp b/interface/src/devices/Faceplus.cpp index 9a3067e48f..34547c2a6a 100644 --- a/interface/src/devices/Faceplus.cpp +++ b/interface/src/devices/Faceplus.cpp @@ -6,6 +6,8 @@ // Copyright (c) 2014 High Fidelity, Inc. All rights reserved. // +#include + #ifdef HAVE_FACEPLUS #include #endif @@ -33,6 +35,41 @@ void Faceplus::init() { updateEnabled(); } +void Faceplus::setState(const glm::quat& headRotation, float estimatedEyePitch, float estimatedEyeYaw, + const QVector& blendshapeCoefficients) { + _headRotation = headRotation; + _estimatedEyePitch = estimatedEyePitch; + _estimatedEyeYaw = estimatedEyeYaw; + _blendshapeCoefficients = blendshapeCoefficients; + _active = true; +} + +void Faceplus::updateEnabled() { + setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceplus) && + !(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && + Application::getInstance()->getFaceshift()->isConnectedOrConnecting())); +} + +void Faceplus::setEnabled(bool enabled) { + if (_enabled == enabled) { + return; + } + if ((_enabled = enabled)) { + _reader = new FaceplusReader(); + QThread* readerThread = new QThread(this); + _reader->moveToThread(readerThread); + readerThread->start(); + QMetaObject::invokeMethod(_reader, "init"); + + } else { + QThread* readerThread = _reader->thread(); + QMetaObject::invokeMethod(_reader, "shutdown"); + readerThread->wait(); + delete readerThread; + _active = false; + } +} + #ifdef HAVE_FACEPLUS static QMultiHash > createChannelNameMap() { QMultiHash > blendshapeMap; @@ -97,18 +134,76 @@ static const QMultiHash >& getChannelNameMap() { } #endif -void Faceplus::update() { +void FaceplusReader::init() { #ifdef HAVE_FACEPLUS - if (!_active) { + if (!faceplus_init("VGA")) { + qDebug() << "Failed to initialized Faceplus."; return; } - if (!(_active = faceplus_synchronous_track() && faceplus_current_output_vector(_outputVector.data()))) { + qDebug() << "Faceplus initialized."; + + int channelCount = faceplus_output_channels_count(); + _outputVector.resize(channelCount); + + int maxIndex = -1; + _channelIndexMap.clear(); + for (int i = 0; i < channelCount; i++) { + QByteArray name = faceplus_output_channel_name(i); + if (name == "Head_Joint::Rotation_X") { + _headRotationIndices[0] = i; + + } else if (name == "Head_Joint::Rotation_Y") { + _headRotationIndices[1] = i; + + } else if (name == "Head_Joint::Rotation_Z") { + _headRotationIndices[2] = i; + + } else if (name == "Left_Eye_Joint::Rotation_X") { + _leftEyeRotationIndices[0] = i; + + } else if (name == "Left_Eye_Joint::Rotation_Y") { + _leftEyeRotationIndices[1] = i; + + } else if (name == "Right_Eye_Joint::Rotation_X") { + _rightEyeRotationIndices[0] = i; + + } else if (name == "Right_Eye_Joint::Rotation_Y") { + _rightEyeRotationIndices[1] = i; + } + for (QMultiHash >::const_iterator it = getChannelNameMap().constFind(name); + it != getChannelNameMap().constEnd() && it.key() == name; it++) { + _channelIndexMap.insert(i, it.value()); + maxIndex = qMax(maxIndex, it.value().first); + } + } + _blendshapeCoefficients.resize(maxIndex + 1); + + QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); +#endif +} + +void FaceplusReader::shutdown() { +#ifdef HAVE_FACEPLUS + if (faceplus_teardown()) { + qDebug() << "Faceplus torn down."; + } +#endif + deleteLater(); + thread()->quit(); +} + +void FaceplusReader::update() { +#ifdef HAVE_FACEPLUS + if (!(faceplus_synchronous_track() && faceplus_current_output_vector(_outputVector.data()))) { + QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); return; } - _headRotation = glm::quat(glm::radians(glm::vec3(-_outputVector.at(_headRotationIndices[0]), + glm::quat headRotation(glm::radians(glm::vec3(-_outputVector.at(_headRotationIndices[0]), _outputVector.at(_headRotationIndices[1]), -_outputVector.at(_headRotationIndices[2])))); - _estimatedEyePitch = (_outputVector.at(_leftEyeRotationIndices[0]) + _outputVector.at(_rightEyeRotationIndices[0])) * -0.5f; - _estimatedEyeYaw = (_outputVector.at(_leftEyeRotationIndices[1]) + _outputVector.at(_rightEyeRotationIndices[1])) * 0.5f; + float estimatedEyePitch = (_outputVector.at(_leftEyeRotationIndices[0]) + + _outputVector.at(_rightEyeRotationIndices[0])) * -0.5f; + float estimatedEyeYaw = (_outputVector.at(_leftEyeRotationIndices[1]) + + _outputVector.at(_rightEyeRotationIndices[1])) * 0.5f; qFill(_blendshapeCoefficients.begin(), _blendshapeCoefficients.end(), 0.0f); for (int i = 0; i < _outputVector.size(); i++) { @@ -117,67 +212,11 @@ void Faceplus::update() { _blendshapeCoefficients[it.value().first] += _outputVector.at(i) * it.value().second; } } + + QMetaObject::invokeMethod(Application::getInstance()->getFaceplus(), "setState", Q_ARG(const glm::quat&, headRotation), + Q_ARG(float, estimatedEyePitch), Q_ARG(float, estimatedEyeYaw), Q_ARG(const QVector&, _blendshapeCoefficients)); + + QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); #endif } -void Faceplus::reset() { -} - -void Faceplus::updateEnabled() { - setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceplus) && - !(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && - Application::getInstance()->getFaceshift()->isConnectedOrConnecting())); -} - -void Faceplus::setEnabled(bool enabled) { -#ifdef HAVE_FACEPLUS - if (_enabled == enabled) { - return; - } - if ((_enabled = enabled)) { - if (faceplus_init("VGA")) { - qDebug() << "Faceplus initialized."; - _active = true; - - int channelCount = faceplus_output_channels_count(); - _outputVector.resize(channelCount); - - int maxIndex = -1; - _channelIndexMap.clear(); - for (int i = 0; i < channelCount; i++) { - QByteArray name = faceplus_output_channel_name(i); - if (name == "Head_Joint::Rotation_X") { - _headRotationIndices[0] = i; - - } else if (name == "Head_Joint::Rotation_Y") { - _headRotationIndices[1] = i; - - } else if (name == "Head_Joint::Rotation_Z") { - _headRotationIndices[2] = i; - - } else if (name == "Left_Eye_Joint::Rotation_X") { - _leftEyeRotationIndices[0] = i; - - } else if (name == "Left_Eye_Joint::Rotation_Y") { - _leftEyeRotationIndices[1] = i; - - } else if (name == "Right_Eye_Joint::Rotation_X") { - _rightEyeRotationIndices[0] = i; - - } else if (name == "Right_Eye_Joint::Rotation_Y") { - _rightEyeRotationIndices[1] = i; - } - for (QMultiHash >::const_iterator it = getChannelNameMap().constFind(name); - it != getChannelNameMap().constEnd() && it.key() == name; it++) { - _channelIndexMap.insert(i, it.value()); - maxIndex = qMax(maxIndex, it.value().first); - } - } - _blendshapeCoefficients.resize(maxIndex + 1); - } - } else if (faceplus_teardown()) { - qDebug() << "Faceplus torn down."; - _active = false; - } -#endif -} diff --git a/interface/src/devices/Faceplus.h b/interface/src/devices/Faceplus.h index 164cf4d031..5c5f26e64d 100644 --- a/interface/src/devices/Faceplus.h +++ b/interface/src/devices/Faceplus.h @@ -15,6 +15,8 @@ #include "FaceTracker.h" +class FaceplusReader; + /// Interface for Mixamo FacePlus. class Faceplus : public FaceTracker { Q_OBJECT @@ -28,9 +30,9 @@ public: bool isActive() const { return _active; } - void update(); - void reset(); - + Q_INVOKABLE void setState(const glm::quat& headRotation, float estimatedEyePitch, float estimatedEyeYaw, + const QVector& blendshapeCoefficients); + public slots: void updateEnabled(); @@ -42,12 +44,28 @@ private: bool _enabled; bool _active; + FaceplusReader* _reader; +}; + +/// The reader object that lives in its own thread. +class FaceplusReader : public QObject { + Q_OBJECT + +public: + + Q_INVOKABLE void init(); + Q_INVOKABLE void shutdown(); + Q_INVOKABLE void update(); + +private: + #ifdef HAVE_FACEPLUS QMultiHash > _channelIndexMap; QVector _outputVector; int _headRotationIndices[3]; int _leftEyeRotationIndices[2]; int _rightEyeRotationIndices[2]; + QVector _blendshapeIndices; #endif }; From cbfaf9709efc948f591611e5e14112f0dc6448ce Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 9 Apr 2014 15:18:22 -0700 Subject: [PATCH 08/10] Faceplus fixes. --- interface/src/Application.h | 1 + interface/src/devices/Faceplus.cpp | 19 ++++++++++++------- interface/src/devices/Faceplus.h | 6 +++++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index 7182010050..d76bd38c5f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -174,6 +174,7 @@ public: bool isMouseHidden() const { return _mouseHidden; } const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } + Faceplus* getFaceplus() { return &_faceplus; } Faceshift* getFaceshift() { return &_faceshift; } Visage* getVisage() { return &_visage; } FaceTracker* getActiveFaceTracker(); diff --git a/interface/src/devices/Faceplus.cpp b/interface/src/devices/Faceplus.cpp index 34547c2a6a..62f39d3b91 100644 --- a/interface/src/devices/Faceplus.cpp +++ b/interface/src/devices/Faceplus.cpp @@ -16,6 +16,8 @@ #include "Faceplus.h" #include "renderer/FBXReader.h" +static int floatVectorMetaTypeId = qRegisterMetaType >(); + Faceplus::Faceplus() : _enabled(false), _active(false) { @@ -81,8 +83,8 @@ static QMultiHash > createChannelNameMap() { blendshapeMap.insert("...", QPair("Mix::BrowsIn_Right", 1.0f)); blendshapeMap.insert("...", QPair("Mix::BrowsOuterLower_Left", 1.0f)); blendshapeMap.insert("...", QPair("Mix::BrowsOuterLower_Right", 1.0f)); - blendshapeMap.insert("BrowsU_L", QPair("Mix::BrowsUp_Left", 5.0f)); - blendshapeMap.insert("BrowsU_R", QPair("Mix::BrowsUp_Right", 5.0f)); + blendshapeMap.insert("BrowsU_L", QPair("Mix::BrowsUp_Left", 10.0f)); + blendshapeMap.insert("BrowsU_R", QPair("Mix::BrowsUp_Right", 10.0f)); blendshapeMap.insert("EyeOpen_L", QPair("Mix::EyesWide_Left", 1.0f)); blendshapeMap.insert("EyeOpen_R", QPair("Mix::EyesWide_Right", 1.0f)); blendshapeMap.insert("MouthFrown_L", QPair("Mix::Frown_Left", 1.0f)); @@ -134,6 +136,14 @@ static const QMultiHash >& getChannelNameMap() { } #endif +FaceplusReader::~FaceplusReader() { +#ifdef HAVE_FACEPLUS + if (faceplus_teardown()) { + qDebug() << "Faceplus torn down."; + } +#endif +} + void FaceplusReader::init() { #ifdef HAVE_FACEPLUS if (!faceplus_init("VGA")) { @@ -183,11 +193,6 @@ void FaceplusReader::init() { } void FaceplusReader::shutdown() { -#ifdef HAVE_FACEPLUS - if (faceplus_teardown()) { - qDebug() << "Faceplus torn down."; - } -#endif deleteLater(); thread()->quit(); } diff --git a/interface/src/devices/Faceplus.h b/interface/src/devices/Faceplus.h index 5c5f26e64d..f90c3449bf 100644 --- a/interface/src/devices/Faceplus.h +++ b/interface/src/devices/Faceplus.h @@ -47,12 +47,16 @@ private: FaceplusReader* _reader; }; +Q_DECLARE_METATYPE(QVector) + /// The reader object that lives in its own thread. class FaceplusReader : public QObject { Q_OBJECT public: + virtual ~FaceplusReader(); + Q_INVOKABLE void init(); Q_INVOKABLE void shutdown(); Q_INVOKABLE void update(); @@ -65,7 +69,7 @@ private: int _headRotationIndices[3]; int _leftEyeRotationIndices[2]; int _rightEyeRotationIndices[2]; - QVector _blendshapeIndices; + QVector _blendshapeCoefficients; #endif }; From ead05c4d992481693daa49957bc83abd8eab214e Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 9 Apr 2014 15:22:53 -0700 Subject: [PATCH 09/10] Tab fixes. --- interface/src/Application.cpp | 2 +- interface/src/Application.h | 2 +- interface/src/devices/Faceplus.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6e05167d6f..0d0ec96ce5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1570,7 +1570,7 @@ void Application::init() { // initialize our face trackers after loading the menu settings _faceshift.init(); _faceplus.init(); - _visage.init(); + _visage.init(); // fire off an immediate domain-server check in now that settings are loaded NodeList::getInstance()->sendDomainServerCheckIn(); diff --git a/interface/src/Application.h b/interface/src/Application.h index d76bd38c5f..c6b38b1644 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -174,7 +174,7 @@ public: bool isMouseHidden() const { return _mouseHidden; } const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } - Faceplus* getFaceplus() { return &_faceplus; } + Faceplus* getFaceplus() { return &_faceplus; } Faceshift* getFaceshift() { return &_faceshift; } Visage* getVisage() { return &_visage; } FaceTracker* getActiveFaceTracker(); diff --git a/interface/src/devices/Faceplus.h b/interface/src/devices/Faceplus.h index f90c3449bf..6cfdac2640 100644 --- a/interface/src/devices/Faceplus.h +++ b/interface/src/devices/Faceplus.h @@ -55,7 +55,7 @@ class FaceplusReader : public QObject { public: - virtual ~FaceplusReader(); + virtual ~FaceplusReader(); Q_INVOKABLE void init(); Q_INVOKABLE void shutdown(); From f0dfb7fc38cc05cc1d6e32f702353cd1ea309c5c Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 9 Apr 2014 15:38:54 -0700 Subject: [PATCH 10/10] Updated headers to match the new standard. --- interface/src/devices/FaceTracker.cpp | 9 ++++++--- interface/src/devices/FaceTracker.h | 15 +++++++++------ interface/src/devices/Faceplus.cpp | 9 ++++++--- interface/src/devices/Faceplus.h | 15 +++++++++------ 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/interface/src/devices/FaceTracker.cpp b/interface/src/devices/FaceTracker.cpp index 45f789fbfe..52fe04de77 100644 --- a/interface/src/devices/FaceTracker.cpp +++ b/interface/src/devices/FaceTracker.cpp @@ -1,9 +1,12 @@ // // FaceTracker.cpp -// interface +// interface/src/devices // -// Created by Andrzej Kapolka on 4/8/14. -// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// Created by Andrzej Kapolka on 4/9/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 "FaceTracker.h" diff --git a/interface/src/devices/FaceTracker.h b/interface/src/devices/FaceTracker.h index 659defe591..459f38cafc 100644 --- a/interface/src/devices/FaceTracker.h +++ b/interface/src/devices/FaceTracker.h @@ -1,13 +1,16 @@ // // FaceTracker.h -// interface +// interface/src/devices // -// Created by Andrzej Kapolka on 4/8/14. -// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// Created by Andrzej Kapolka on 4/9/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 __interface__FaceTracker__ -#define __interface__FaceTracker__ +#ifndef hifi_FaceTracker_h +#define hifi_FaceTracker_h #include #include @@ -40,4 +43,4 @@ protected: QVector _blendshapeCoefficients; }; -#endif /* defined(__interface__FaceTracker__) */ +#endif // hifi_FaceTracker_h diff --git a/interface/src/devices/Faceplus.cpp b/interface/src/devices/Faceplus.cpp index 62f39d3b91..f7f2f1f1bd 100644 --- a/interface/src/devices/Faceplus.cpp +++ b/interface/src/devices/Faceplus.cpp @@ -1,9 +1,12 @@ // // Faceplus.cpp -// interface +// interface/src/devices // -// Created by Andrzej Kapolka on 4/8/14. -// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// Created by Andrzej Kapolka on 4/9/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 diff --git a/interface/src/devices/Faceplus.h b/interface/src/devices/Faceplus.h index 6cfdac2640..2b9219f3fd 100644 --- a/interface/src/devices/Faceplus.h +++ b/interface/src/devices/Faceplus.h @@ -1,13 +1,16 @@ // // Faceplus.h -// interface +// interface/src/devices // -// Created by Andrzej Kapolka on 4/8/14. -// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// Created by Andrzej Kapolka on 4/9/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 __interface__Faceplus__ -#define __interface__Faceplus__ +#ifndef hifi_Faceplus_h +#define hifi_Faceplus_h #include #include @@ -73,4 +76,4 @@ private: #endif }; -#endif /* defined(__interface__Faceplus__) */ +#endif // hifi_Faceplus_h