From 38741aed7358b2b592e18bdb50ff364ba40e6692 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 4 Aug 2014 10:27:19 -0700 Subject: [PATCH 01/16] Fixed wrong header guard --- interface/src/devices/CaraFaceTracker.h | 6 +++--- interface/src/devices/DdeFaceTracker.cpp | 12 ++++++++++++ interface/src/devices/DdeFaceTracker.h | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 interface/src/devices/DdeFaceTracker.cpp create mode 100644 interface/src/devices/DdeFaceTracker.h diff --git a/interface/src/devices/CaraFaceTracker.h b/interface/src/devices/CaraFaceTracker.h index f51fed0f1b..8fdba1f606 100644 --- a/interface/src/devices/CaraFaceTracker.h +++ b/interface/src/devices/CaraFaceTracker.h @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hi_fi_CaraFaceTracker_h -#define hi_fi_CaraFaceTracker_h +#ifndef hifi_CaraFaceTracker_h +#define hifi_CaraFaceTracker_h #include @@ -120,4 +120,4 @@ private: int _jawOpenIndex; }; -#endif //endif hi_fi_CaraFaceTracker_h \ No newline at end of file +#endif //endif hifi_CaraFaceTracker_h \ No newline at end of file diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp new file mode 100644 index 0000000000..de1576da4b --- /dev/null +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -0,0 +1,12 @@ +// +// DdeFaceTracker.cpp +// +// +// Created by Clement on 8/2/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 "DdeFaceTracker.h" diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h new file mode 100644 index 0000000000..a57711a10d --- /dev/null +++ b/interface/src/devices/DdeFaceTracker.h @@ -0,0 +1,15 @@ +// +// DdeFaceTracker.h +// +// +// Created by Clement on 8/2/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_DdeFaceTracker_h +#define hifi_DdeFaceTracker_h + +#endif // hifi_DdeFaceTracker_h \ No newline at end of file From bbb52fc4aae9b31bc8bbb844d5a6f9e8288a9414 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 4 Aug 2014 10:28:29 -0700 Subject: [PATCH 02/16] Added dde face tracker class --- interface/src/devices/DdeFaceTracker.cpp | 169 +++++++++++++++++++++++ interface/src/devices/DdeFaceTracker.h | 41 ++++++ 2 files changed, 210 insertions(+) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index de1576da4b..7be5e90a31 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -9,4 +9,173 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + +#include +#include +#include +#include + #include "DdeFaceTracker.h" + +static const QHostAddress DDE_FEATURE_POINT_SERVER_ADDR("127.0.0.1"); +static const quint16 DDE_FEATURE_POINT_SERVER_PORT = 5555; + +static const int NUM_EXPRESSION = 46; +static const int MIN_PACKET_SIZE = (8 + NUM_EXPRESSION) * sizeof(float) + sizeof(int); +static const int MAX_NAME_SIZE = 31; + +struct Packet{ + //roughly in mm + float focal_length[1]; + float translation[3]; + + //quaternion + float rotation[4]; + + //blendshape coefficients ranging between -0.2 and 1.5 + float expressions[NUM_EXPRESSION]; + + //avatar id selected on the UI + int avatar_id; + + //client name, arbitrary length + char name[MAX_NAME_SIZE + 1]; +}; + +DdeFaceTracker::DdeFaceTracker() : +_lastReceiveTimestamp(0), +_reset(false) +{ + connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); + connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); + connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState))); + + bindTo(DDE_FEATURE_POINT_SERVER_PORT); +} + +DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) : +_lastReceiveTimestamp(0), +_reset(false) +{ + connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); + connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); + connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SIGNAL(socketStateChanged(QAbstractSocket::SocketState))); + + bindTo(host, port); +} + +DdeFaceTracker::~DdeFaceTracker() { + if(_udpSocket.isOpen()) + _udpSocket.close(); +} + +void DdeFaceTracker::init() { + +} + +void DdeFaceTracker::reset() { + _reset = true; +} + +void DdeFaceTracker::update() { + +} + +void DdeFaceTracker::bindTo(quint16 port) { + bindTo(QHostAddress::Any, port); +} + +void DdeFaceTracker::bindTo(const QHostAddress& host, quint16 port) { + if(_udpSocket.isOpen()) { + _udpSocket.close(); + } + _udpSocket.bind(host, port); +} + +bool DdeFaceTracker::isActive() const { + static const int ACTIVE_TIMEOUT_USECS = 3000000; //3 secs + return (usecTimestampNow() - _lastReceiveTimestamp < ACTIVE_TIMEOUT_USECS); +} + +//private slots and methods +void DdeFaceTracker::socketErrorOccurred(QAbstractSocket::SocketError socketError) { + qDebug() << "[Error] DDE Face Tracker Socket Error: " << _udpSocket.errorString(); +} + +void DdeFaceTracker::socketStateChanged(QAbstractSocket::SocketState socketState) { + QString state; + switch(socketState) { + case QAbstractSocket::BoundState: + state = "Bounded"; + break; + case QAbstractSocket::ClosingState: + state = "Closing"; + break; + case QAbstractSocket::ConnectedState: + state = "Connected"; + break; + case QAbstractSocket::ConnectingState: + state = "Connecting"; + break; + case QAbstractSocket::HostLookupState: + state = "Host Lookup"; + break; + case QAbstractSocket::ListeningState: + state = "Listening"; + break; + case QAbstractSocket::UnconnectedState: + state = "Unconnected"; + break; + } + qDebug() << "[Info] DDE Face Tracker Socket: " << socketState; +} + +void DdeFaceTracker::readPendingDatagrams() { + QByteArray buffer; + while (_udpSocket.hasPendingDatagrams()) { + buffer.resize(_udpSocket.pendingDatagramSize()); + _udpSocket.readDatagram(buffer.data(), buffer.size()); + } + decodePacket(buffer); +} + +void DdeFaceTracker::decodePacket(const QByteArray& buffer) { + if(buffer.size() > MIN_PACKET_SIZE) { + Packet packet; + int bytesToCopy = glm::min((int)sizeof(packet), buffer.size()); + memset(&packet.name, '\n', MAX_NAME_SIZE + 1); + memcpy(&packet, buffer.data(), bytesToCopy); + + glm::vec3 translation; + memcpy(&translation, packet.translation, sizeof(packet.translation)); + glm::quat rotation; + memcpy(&rotation, &packet.rotation, sizeof(packet.rotation)); + if (_reset) { + memcpy(&_referenceTranslation, &translation, sizeof(glm::vec3)); + memcpy(&_referenceRotation, &rotation, sizeof(glm::quat)); + _reset = false; + } + + // Compute relative translation + float DAMPING_FACTOR = 40; + translation -= _referenceTranslation; + translation /= DAMPING_FACTOR; + translation.x *= -1; + + // Compute relative rotation + rotation = glm::inverse(_referenceRotation) * rotation; + + // copy values + _headTranslation = translation; + _headRotation = rotation; + + // Set blendshapes + + + + } else { + qDebug() << "[Error] DDE Face Tracker Decode Error"; + } + _lastReceiveTimestamp = usecTimestampNow(); +} diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index a57711a10d..310ce60212 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -12,4 +12,45 @@ #ifndef hifi_DdeFaceTracker_h #define hifi_DdeFaceTracker_h +#include + +#include "FaceTracker.h" + +class DdeFaceTracker : public FaceTracker { + Q_OBJECT + +public: + DdeFaceTracker(); + DdeFaceTracker(const QHostAddress& host, quint16 port); + ~DdeFaceTracker(); + + //initialization + void init(); + void reset(); + void update(); + + //sockets + void bindTo(quint16 port); + void bindTo(const QHostAddress& host, quint16 port); + bool isActive() const; + +private slots: + + //sockets + void socketErrorOccurred(QAbstractSocket::SocketError socketError); + void readPendingDatagrams(); + void socketStateChanged(QAbstractSocket::SocketState socketState); + +private: + void decodePacket(const QByteArray& buffer); + + // sockets + QUdpSocket _udpSocket; + quint64 _lastReceiveTimestamp; + + bool _reset; + glm::vec3 _referenceTranslation; + glm::quat _referenceRotation; +}; + #endif // hifi_DdeFaceTracker_h \ No newline at end of file From 8d1438a44c1700e39326e58f701cb37a095ef148 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 4 Aug 2014 10:28:52 -0700 Subject: [PATCH 03/16] Plugged in dde face tracker --- interface/src/Application.cpp | 22 ++++++++++++++++------ interface/src/Application.h | 4 ++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 28640dc092..05a4a08c48 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1502,10 +1502,11 @@ glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVox } FaceTracker* Application::getActiveFaceTracker() { - return _cara.isActive() ? static_cast(&_cara) : - (_faceshift.isActive() ? static_cast(&_faceshift) : - (_faceplus.isActive() ? static_cast(&_faceplus) : - (_visage.isActive() ? static_cast(&_visage) : NULL))); + return (_dde.isActive() ? static_cast(&_dde) : + (_cara.isActive() ? static_cast(&_cara) : + (_faceshift.isActive() ? static_cast(&_faceshift) : + (_faceplus.isActive() ? static_cast(&_faceplus) : + (_visage.isActive() ? static_cast(&_visage) : NULL))))); } struct SendVoxelsOperationArgs { @@ -1937,13 +1938,21 @@ void Application::updateVisage() { _visage.update(); } +void Application::updateDDE() { + bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); + PerformanceWarning warn(showWarnings, "Application::updateDDE()"); + + // Update Cara + _dde.update(); +} + void Application::updateCara() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateCara()"); - + // Update Cara _cara.update(); - + // Copy angular velocity if measured by cara, to the head if (_cara.isActive()) { _myAvatar->getHead()->setAngularVelocity(_cara.getHeadAngularVelocity()); @@ -3265,6 +3274,7 @@ void Application::resetSensors() { _faceplus.reset(); _faceshift.reset(); _visage.reset(); + _dde.reset(); OculusManager::reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 43a6083457..c898d10cbd 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -64,6 +64,7 @@ #include "devices/SixenseManager.h" #include "devices/Visage.h" #include "devices/CaraFaceTracker.h" +#include "devices/DdeFaceTracker.h" #include "models/ModelTreeRenderer.h" #include "particles/ParticleTreeRenderer.h" #include "renderer/AmbientOcclusionEffect.h" @@ -214,6 +215,7 @@ public: Faceplus* getFaceplus() { return &_faceplus; } Faceshift* getFaceshift() { return &_faceshift; } Visage* getVisage() { return &_visage; } + DdeFaceTracker* getDDE() { return &_dde; } CaraFaceTracker* getCara() { return &_cara; } FaceTracker* getActiveFaceTracker(); SixenseManager* getSixenseManager() { return &_sixenseManager; } @@ -393,6 +395,7 @@ private: void updateFaceplus(); void updateFaceshift(); void updateVisage(); + void updateDDE(); void updateCara(); void updateMyAvatarLookAtPosition(); void updateThreads(float deltaTime); @@ -493,6 +496,7 @@ private: Faceshift _faceshift; Visage _visage; CaraFaceTracker _cara; + DdeFaceTracker _dde; SixenseManager _sixenseManager; PrioVR _prioVR; From cac3983778060f45aadcc6b1d7697a2d63b0213d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 4 Aug 2014 11:03:58 -0700 Subject: [PATCH 04/16] Added a few blendshapes --- interface/src/devices/DdeFaceTracker.cpp | 44 ++++++++++++++++++++++-- interface/src/devices/DdeFaceTracker.h | 33 ++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 7be5e90a31..23dad928d3 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -45,8 +45,22 @@ struct Packet{ DdeFaceTracker::DdeFaceTracker() : _lastReceiveTimestamp(0), -_reset(false) +_reset(false), +_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes +_rightBlinkIndex(1), +_leftEyeOpenIndex(8), +_rightEyeOpenIndex(9), +_browDownLeftIndex(14), +_browDownRightIndex(15), +_browUpCenterIndex(16), +_browUpLeftIndex(17), +_browUpRightIndex(18), +_mouthSmileLeftIndex(28), +_mouthSmileRightIndex(29), +_jawOpenIndex(21) { + _blendshapeCoefficients.resize(NUM_EXPRESSION); + connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState))); @@ -56,8 +70,22 @@ _reset(false) DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) : _lastReceiveTimestamp(0), -_reset(false) +_reset(false), +_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes +_rightBlinkIndex(1), +_leftEyeOpenIndex(8), +_rightEyeOpenIndex(9), +_browDownLeftIndex(14), +_browDownRightIndex(15), +_browUpCenterIndex(16), +_browUpLeftIndex(17), +_browUpRightIndex(18), +_mouthSmileLeftIndex(28), +_mouthSmileRightIndex(29), +_jawOpenIndex(21) { + _blendshapeCoefficients.resize(NUM_EXPRESSION); + connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SIGNAL(socketStateChanged(QAbstractSocket::SocketState))); @@ -140,6 +168,10 @@ void DdeFaceTracker::readPendingDatagrams() { decodePacket(buffer); } +float DdeFaceTracker::getBlendshapeCoefficient(int index) const { + return (index >= 0 && index < (int)_blendshapeCoefficients.size()) ? _blendshapeCoefficients[index] : 0.0f; +} + void DdeFaceTracker::decodePacket(const QByteArray& buffer) { if(buffer.size() > MIN_PACKET_SIZE) { Packet packet; @@ -171,8 +203,16 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { _headRotation = rotation; // Set blendshapes + _blendshapeCoefficients[_leftBlinkIndex] = packet.expressions[1]; + _blendshapeCoefficients[_rightBlinkIndex] = packet.expressions[0]; + _blendshapeCoefficients[_browDownLeftIndex] = packet.expressions[14]; + _blendshapeCoefficients[_browDownRightIndex] = packet.expressions[15]; + _blendshapeCoefficients[_browUpCenterIndex] = (packet.expressions[14] + packet.expressions[14]) / 2.0f; + _blendshapeCoefficients[_browUpLeftIndex] = packet.expressions[14]; + _blendshapeCoefficients[_browUpRightIndex] = packet.expressions[15]; + _blendshapeCoefficients[_jawOpenIndex] = packet.expressions[21]; } else { qDebug() << "[Error] DDE Face Tracker Decode Error"; diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 310ce60212..96707ac94c 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -34,6 +34,21 @@ public: void bindTo(const QHostAddress& host, quint16 port); bool isActive() const; + float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); } + float getRightBlink() const { return getBlendshapeCoefficient(_rightBlinkIndex); } + float getLeftEyeOpen() const { return getBlendshapeCoefficient(_leftEyeOpenIndex); } + float getRightEyeOpen() const { return getBlendshapeCoefficient(_rightEyeOpenIndex); } + + float getBrowDownLeft() const { return getBlendshapeCoefficient(_browDownLeftIndex); } + float getBrowDownRight() const { return getBlendshapeCoefficient(_browDownRightIndex); } + float getBrowUpCenter() const { return getBlendshapeCoefficient(_browUpCenterIndex); } + float getBrowUpLeft() const { return getBlendshapeCoefficient(_browUpLeftIndex); } + float getBrowUpRight() const { return getBlendshapeCoefficient(_browUpRightIndex); } + + float getMouthSize() const { return getBlendshapeCoefficient(_jawOpenIndex); } + float getMouthSmileLeft() const { return getBlendshapeCoefficient(_mouthSmileLeftIndex); } + float getMouthSmileRight() const { return getBlendshapeCoefficient(_mouthSmileRightIndex); } + private slots: //sockets @@ -42,6 +57,7 @@ private slots: void socketStateChanged(QAbstractSocket::SocketState socketState); private: + float getBlendshapeCoefficient(int index) const; void decodePacket(const QByteArray& buffer); // sockets @@ -51,6 +67,23 @@ private: bool _reset; glm::vec3 _referenceTranslation; glm::quat _referenceRotation; + + int _leftBlinkIndex; + int _rightBlinkIndex; + int _leftEyeOpenIndex; + int _rightEyeOpenIndex; + + // Brows + int _browDownLeftIndex; + int _browDownRightIndex; + int _browUpCenterIndex; + int _browUpLeftIndex; + int _browUpRightIndex; + + int _mouthSmileLeftIndex; + int _mouthSmileRightIndex; + + int _jawOpenIndex; }; #endif // hifi_DdeFaceTracker_h \ No newline at end of file From c80cd0d71d964864d30aad97aec2a27d06ef56d6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 4 Aug 2014 11:04:14 -0700 Subject: [PATCH 05/16] connected blendshapes --- interface/src/avatar/Head.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index d3d1e74fc8..995f3f2390 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -68,6 +68,9 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { if ((_isFaceshiftConnected = faceTracker)) { _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); _isFaceshiftConnected = true; + } else if (Application::getInstance()->getDDE()->isActive()) { + faceTracker = Application::getInstance()->getDDE(); + _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); } } From 1d2cf3536b8baf4ef176547f5c87066f806a72dc Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 4 Aug 2014 11:20:18 -0700 Subject: [PATCH 06/16] Coefficients tweaks --- interface/src/devices/DdeFaceTracker.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 23dad928d3..acaa6d4faf 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -172,6 +172,12 @@ float DdeFaceTracker::getBlendshapeCoefficient(int index) const { return (index >= 0 && index < (int)_blendshapeCoefficients.size()) ? _blendshapeCoefficients[index] : 0.0f; } +static const float DDE_MIN_RANGE = -0.2; +static const float DDE_MAX_RANGE = 1.5; +float rescaleCoef(float ddeCoef) { + return (ddeCoef - DDE_MIN_RANGE) / (DDE_MAX_RANGE - DDE_MIN_RANGE); +} + void DdeFaceTracker::decodePacket(const QByteArray& buffer) { if(buffer.size() > MIN_PACKET_SIZE) { Packet packet; @@ -203,14 +209,11 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { _headRotation = rotation; // Set blendshapes - _blendshapeCoefficients[_leftBlinkIndex] = packet.expressions[1]; - _blendshapeCoefficients[_rightBlinkIndex] = packet.expressions[0]; + _blendshapeCoefficients[_leftBlinkIndex] = rescaleCoef(packet.expressions[1]); + _blendshapeCoefficients[_rightBlinkIndex] = rescaleCoef(packet.expressions[0]); - _blendshapeCoefficients[_browDownLeftIndex] = packet.expressions[14]; - _blendshapeCoefficients[_browDownRightIndex] = packet.expressions[15]; - _blendshapeCoefficients[_browUpCenterIndex] = (packet.expressions[14] + packet.expressions[14]) / 2.0f; - _blendshapeCoefficients[_browUpLeftIndex] = packet.expressions[14]; - _blendshapeCoefficients[_browUpRightIndex] = packet.expressions[15]; + _blendshapeCoefficients[_browDownLeftIndex] = rescaleCoef(packet.expressions[14]); + _blendshapeCoefficients[_browDownRightIndex] = rescaleCoef(packet.expressions[15]); _blendshapeCoefficients[_jawOpenIndex] = packet.expressions[21]; From 0a429681974b4f51fa0fed46baf2807088b0a8e4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 4 Aug 2014 12:40:12 -0700 Subject: [PATCH 07/16] DDE tweaks --- interface/src/devices/DdeFaceTracker.cpp | 29 ++++++++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index acaa6d4faf..c22720c0c0 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -209,13 +209,32 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { _headRotation = rotation; // Set blendshapes - _blendshapeCoefficients[_leftBlinkIndex] = rescaleCoef(packet.expressions[1]); - _blendshapeCoefficients[_rightBlinkIndex] = rescaleCoef(packet.expressions[0]); + _blendshapeCoefficients[_leftBlinkIndex] = rescaleCoef(packet.expressions[1]) * 2.0f; + _blendshapeCoefficients[_rightBlinkIndex] = rescaleCoef(packet.expressions[0]) * 2.0f; - _blendshapeCoefficients[_browDownLeftIndex] = rescaleCoef(packet.expressions[14]); - _blendshapeCoefficients[_browDownRightIndex] = rescaleCoef(packet.expressions[15]); + float leftBrow = 1.0f - rescaleCoef(packet.expressions[14]); + if (leftBrow < 0.5f) { + _blendshapeCoefficients[_browDownLeftIndex] = 1.0f - 2.0f * leftBrow; + _blendshapeCoefficients[_browUpLeftIndex] = 0.0f; + } else { + _blendshapeCoefficients[_browDownLeftIndex] = 0.0f; + _blendshapeCoefficients[_browUpLeftIndex] = 2.0f * (leftBrow - 0.5f); + } + float rightBrow = 1.0f - rescaleCoef(packet.expressions[15]); + if (rightBrow < 0.5f) { + _blendshapeCoefficients[_browDownRightIndex] = 1.0f - 2.0f * rightBrow; + _blendshapeCoefficients[_browUpRightIndex] = 0.0f; + } else { + _blendshapeCoefficients[_browDownRightIndex] = 0.0f; + _blendshapeCoefficients[_browUpRightIndex] = 2.0f * (rightBrow - 0.5f); + } + + _blendshapeCoefficients[_jawOpenIndex] = rescaleCoef(packet.expressions[21]) * 1.4f; + + + _blendshapeCoefficients[_mouthSmileLeftIndex] = rescaleCoef(packet.expressions[24]); + _blendshapeCoefficients[_mouthSmileRightIndex] = rescaleCoef(packet.expressions[23]); - _blendshapeCoefficients[_jawOpenIndex] = packet.expressions[21]; } else { qDebug() << "[Error] DDE Face Tracker Decode Error"; From d1a1311979c37a44e7a73a3e9cd5fa27a0af4609 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 4 Aug 2014 12:44:23 -0700 Subject: [PATCH 08/16] Mode DDE tweaks --- interface/src/devices/DdeFaceTracker.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index c22720c0c0..3dc5a818cc 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -196,9 +196,9 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { } // Compute relative translation - float DAMPING_FACTOR = 40; + float LEAN_DAMPING_FACTOR = 40; translation -= _referenceTranslation; - translation /= DAMPING_FACTOR; + translation /= LEAN_DAMPING_FACTOR; translation.x *= -1; // Compute relative rotation @@ -209,8 +209,9 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { _headRotation = rotation; // Set blendshapes - _blendshapeCoefficients[_leftBlinkIndex] = rescaleCoef(packet.expressions[1]) * 2.0f; - _blendshapeCoefficients[_rightBlinkIndex] = rescaleCoef(packet.expressions[0]) * 2.0f; + float BLINK_MAGNIFIER = 2.0f; + _blendshapeCoefficients[_leftBlinkIndex] = rescaleCoef(packet.expressions[1]) * BLINK_MAGNIFIER; + _blendshapeCoefficients[_rightBlinkIndex] = rescaleCoef(packet.expressions[0]) * BLINK_MAGNIFIER; float leftBrow = 1.0f - rescaleCoef(packet.expressions[14]); if (leftBrow < 0.5f) { @@ -229,7 +230,8 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { _blendshapeCoefficients[_browUpRightIndex] = 2.0f * (rightBrow - 0.5f); } - _blendshapeCoefficients[_jawOpenIndex] = rescaleCoef(packet.expressions[21]) * 1.4f; + float JAW_OPEN_MAGNIFIER = 1.4f; + _blendshapeCoefficients[_jawOpenIndex] = rescaleCoef(packet.expressions[21]) * JAW_OPEN_MAGNIFIER; _blendshapeCoefficients[_mouthSmileLeftIndex] = rescaleCoef(packet.expressions[24]); From 40375b8c81a37a7a53dab5f67b45177b6ab15420 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Aug 2014 14:46:33 -0700 Subject: [PATCH 09/16] add a navbar to domain-server web page --- domain-server/resources/web/header.html | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/domain-server/resources/web/header.html b/domain-server/resources/web/header.html index 2be603b00e..e1a9d1ea8a 100644 --- a/domain-server/resources/web/header.html +++ b/domain-server/resources/web/header.html @@ -8,4 +8,27 @@ +
\ No newline at end of file From 2c1277ef374db722ae7096ac695fefee0271b9fb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Aug 2014 14:47:17 -0700 Subject: [PATCH 10/16] remove voxel settings from domain-server settings until ready to go --- .../resources/web/settings/describe.json | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/domain-server/resources/web/settings/describe.json b/domain-server/resources/web/settings/describe.json index 2d90680e01..f4920a7b50 100644 --- a/domain-server/resources/web/settings/describe.json +++ b/domain-server/resources/web/settings/describe.json @@ -28,33 +28,5 @@ "default": "" } } - }, - "voxels": { - "label": "Voxels", - "assignment-types": [2,3], - "settings": { - "voxel-wallet": { - "label": "Destination Wallet ID", - "help": "Wallet to be paid for voxel changes", - "placeholder": "00000000-0000-0000-0000-000000000000", - "default": "" - }, - "per-voxel-credits": { - "type": "double", - "label": "Per Voxel Cost", - "help": "Credit cost to change each voxel", - "placeholder": "0.0", - "default": "0.0", - "input_addon": "₵" - }, - "per-meter-cubed-credits": { - "type": "double", - "label": "Per Meter Cubed Cost", - "help": "Credit cost to change each cubed meter of voxel space", - "placeholder": "0.0", - "default": "0.0", - "input_addon": "₵" - } - } } } \ No newline at end of file From 10c94023f199be7ee79a48b94a8fe3b3e1ea9615 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Aug 2014 15:25:14 -0700 Subject: [PATCH 11/16] handle basic authentication for domain-server admin --- domain-server/src/DomainServer.cpp | 64 +++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 2ecae73d0a..a76d3a916d 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1280,6 +1280,9 @@ bool DomainServer::isAuthenticatedRequest(HTTPConnection* connection, const QUrl const QByteArray HTTP_COOKIE_HEADER_KEY = "Cookie"; const QString ADMIN_USERS_CONFIG_KEY = "admin-users"; const QString ADMIN_ROLES_CONFIG_KEY = "admin-roles"; + const QString BASIC_AUTH_CONFIG_KEY = "basic-auth"; + + const QByteArray UNAUTHENTICATED_BODY = "You do not have permission to access this domain-server."; if (!_oauthProviderURL.isEmpty() && (_argumentVariantMap.contains(ADMIN_USERS_CONFIG_KEY) || _argumentVariantMap.contains(ADMIN_ROLES_CONFIG_KEY))) { @@ -1293,6 +1296,11 @@ bool DomainServer::isAuthenticatedRequest(HTTPConnection* connection, const QUrl cookieUUID = cookieUUIDRegex.cap(1); } + if (_argumentVariantMap.contains(BASIC_AUTH_CONFIG_KEY)) { + qDebug() << "Config file contains web admin settings for OAuth and basic HTTP authentication." + << "These cannot be combined - using OAuth for authentication."; + } + if (!cookieUUID.isNull() && _cookieSessionHash.contains(cookieUUID)) { // pull the QJSONObject for the user with this cookie UUID DomainServerWebSessionData sessionData = _cookieSessionHash.value(cookieUUID); @@ -1315,8 +1323,7 @@ bool DomainServer::isAuthenticatedRequest(HTTPConnection* connection, const QUrl } } - QString unauthenticatedRequest = "You do not have permission to access this domain-server."; - connection->respond(HTTPConnection::StatusCode401, unauthenticatedRequest.toUtf8()); + connection->respond(HTTPConnection::StatusCode401, UNAUTHENTICATED_BODY); // the user does not have allowed username or role, return 401 return false; @@ -1340,6 +1347,59 @@ bool DomainServer::isAuthenticatedRequest(HTTPConnection* connection, const QUrl // we don't know about this user yet, so they are not yet authenticated return false; } + } else if (_argumentVariantMap.contains(BASIC_AUTH_CONFIG_KEY)) { + // config file contains username and password combinations for basic auth + const QByteArray BASIC_AUTH_HEADER_KEY = "Authorization"; + + // check if a username and password have been provided with the request + QString basicAuthString = connection->requestHeaders().value(BASIC_AUTH_HEADER_KEY); + + if (!basicAuthString.isEmpty()) { + QStringList splitAuthString = basicAuthString.split(' '); + QString base64String = splitAuthString.size() == 2 ? splitAuthString[1] : ""; + QString credentialString = QByteArray::fromBase64(base64String.toLocal8Bit()); + + if (!credentialString.isEmpty()) { + QStringList credentialList = credentialString.split(':'); + if (credentialList.size() == 2) { + QString username = credentialList[0]; + QString password = credentialList[1]; + + // we've pulled a username and password - now check if there is a match in our basic auth hash + QJsonObject basicAuthObject = _argumentVariantMap.value(BASIC_AUTH_CONFIG_KEY).toJsonValue().toObject(); + + if (basicAuthObject.contains(username)) { + const QString BASIC_AUTH_USER_PASSWORD_KEY = "password"; + QJsonObject userObject = basicAuthObject.value(username).toObject(); + + if (userObject.contains(BASIC_AUTH_USER_PASSWORD_KEY) + && userObject.value(BASIC_AUTH_USER_PASSWORD_KEY).toString() == password) { + // this is username / password match - let this user in + return true; + } + } + } + } + } + + // basic HTTP auth being used but no username and password are present + // or the username and password are not correct + // send back a 401 and ask for basic auth + + const QByteArray HTTP_AUTH_REQUEST_HEADER_KEY = "WWW-Authenticate"; + static QString HTTP_AUTH_REALM_STRING = QString("Basic realm='%1 %2'") + .arg(_hostname.isEmpty() ? "localhost" : _hostname) + .arg("domain-server"); + + Headers basicAuthHeader; + basicAuthHeader.insert(HTTP_AUTH_REQUEST_HEADER_KEY, HTTP_AUTH_REALM_STRING.toUtf8()); + + connection->respond(HTTPConnection::StatusCode401, UNAUTHENTICATED_BODY, + HTTPConnection::DefaultContentType, basicAuthHeader); + + // not authenticated, bubble up false + return false; + } else { // we don't have an OAuth URL + admin roles/usernames, so all users are authenticated return true; From c786ee5c2698304f977b6895a3fae4187f01db16 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Aug 2014 15:27:34 -0700 Subject: [PATCH 12/16] dynamically change active link in domain-server navbar --- domain-server/resources/web/footer.html | 3 ++- domain-server/resources/web/header.html | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/domain-server/resources/web/footer.html b/domain-server/resources/web/footer.html index d1a3fc29e8..aa6821a3b9 100644 --- a/domain-server/resources/web/footer.html +++ b/domain-server/resources/web/footer.html @@ -1,3 +1,4 @@
- \ No newline at end of file + + \ No newline at end of file diff --git a/domain-server/resources/web/header.html b/domain-server/resources/web/header.html index e1a9d1ea8a..c007642724 100644 --- a/domain-server/resources/web/header.html +++ b/domain-server/resources/web/header.html @@ -25,7 +25,7 @@ From 6febca3533824d5a2639b7330c81a6721a140ce7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Aug 2014 15:37:06 -0700 Subject: [PATCH 13/16] add missing domain-server javascript file --- domain-server/resources/web/js/domain-server.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 domain-server/resources/web/js/domain-server.js diff --git a/domain-server/resources/web/js/domain-server.js b/domain-server/resources/web/js/domain-server.js new file mode 100644 index 0000000000..3f78d8f466 --- /dev/null +++ b/domain-server/resources/web/js/domain-server.js @@ -0,0 +1,10 @@ +$(document).ready(function(){ + var url = window.location; + // Will only work if string in href matches with location + $('ul.nav a[href="'+ url +'"]').parent().addClass('active'); + + // Will also work for relative and absolute hrefs + $('ul.nav a').filter(function() { + return this.href == url; + }).parent().addClass('active'); +}); \ No newline at end of file From 9fc545001cb563a9a1dfc015c23797b912a26715 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Aug 2014 15:40:45 -0700 Subject: [PATCH 14/16] look for a config.json file by default in resources --- libraries/shared/src/HifiConfigVariantMap.cpp | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/libraries/shared/src/HifiConfigVariantMap.cpp b/libraries/shared/src/HifiConfigVariantMap.cpp index 02cce80104..6fe39a8ccf 100644 --- a/libraries/shared/src/HifiConfigVariantMap.cpp +++ b/libraries/shared/src/HifiConfigVariantMap.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #include #include @@ -68,29 +69,35 @@ QVariantMap HifiConfigVariantMap::mergeCLParametersWithJSONConfig(const QStringL int configIndex = argumentList.indexOf(CONFIG_FILE_OPTION); + QString configFilePath; + if (configIndex != -1) { // we have a config file - try and read it - QString configFilePath = argumentList[configIndex + 1]; - QFile configFile(configFilePath); - - if (configFile.exists()) { - qDebug() << "Reading JSON config file at" << configFilePath; - configFile.open(QIODevice::ReadOnly); - - QJsonDocument configDocument = QJsonDocument::fromJson(configFile.readAll()); - QJsonObject rootObject = configDocument.object(); - - // enumerate the keys of the configDocument object - foreach(const QString& key, rootObject.keys()) { - - if (!mergedMap.contains(key)) { - // no match in existing list, add it - mergedMap.insert(key, QVariant(rootObject[key])); - } + configFilePath = argumentList[configIndex + 1]; + } else { + // no config file - try to read a file at resources/config.json + configFilePath = QCoreApplication::applicationDirPath() + "/resources/config.json"; + } + + QFile configFile(configFilePath); + + if (configFile.exists()) { + qDebug() << "Reading JSON config file at" << configFilePath; + configFile.open(QIODevice::ReadOnly); + + QJsonDocument configDocument = QJsonDocument::fromJson(configFile.readAll()); + QJsonObject rootObject = configDocument.object(); + + // enumerate the keys of the configDocument object + foreach(const QString& key, rootObject.keys()) { + + if (!mergedMap.contains(key)) { + // no match in existing list, add it + mergedMap.insert(key, QVariant(rootObject[key])); } - } else { - qDebug() << "Could not find JSON config file at" << configFilePath; } + } else { + qDebug() << "Could not find JSON config file at" << configFilePath; } return mergedMap; From 4407ea448070e5e960838e3175d2b3e4521c5e0d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Aug 2014 16:02:13 -0700 Subject: [PATCH 15/16] make assignment selector a dropdown --- domain-server/resources/web/header.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/domain-server/resources/web/header.html b/domain-server/resources/web/header.html index c007642724..f687590df2 100644 --- a/domain-server/resources/web/header.html +++ b/domain-server/resources/web/header.html @@ -26,7 +26,13 @@ From 4f0218090c564e7d61867c481f46146634eaa5a1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Aug 2014 16:23:26 -0700 Subject: [PATCH 16/16] have the domain-server brand in navbar link back to home --- domain-server/resources/web/header.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/resources/web/header.html b/domain-server/resources/web/header.html index f687590df2..a2aebc1189 100644 --- a/domain-server/resources/web/header.html +++ b/domain-server/resources/web/header.html @@ -18,7 +18,7 @@ - domain-server + domain-server