mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-10 02:04:57 +02:00
Update Facetrackers
This commit is contained in:
parent
8eb4abc49c
commit
b6968a6b15
6 changed files with 77 additions and 126 deletions
|
@ -50,6 +50,8 @@ DdeFaceTracker::DdeFaceTracker() :
|
||||||
}
|
}
|
||||||
|
|
||||||
DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) :
|
DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) :
|
||||||
|
_host(host),
|
||||||
|
_port(port),
|
||||||
_lastReceiveTimestamp(0),
|
_lastReceiveTimestamp(0),
|
||||||
_reset(false),
|
_reset(false),
|
||||||
_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
|
_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
|
||||||
|
@ -63,9 +65,7 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) :
|
||||||
_browUpRightIndex(18),
|
_browUpRightIndex(18),
|
||||||
_mouthSmileLeftIndex(28),
|
_mouthSmileLeftIndex(28),
|
||||||
_mouthSmileRightIndex(29),
|
_mouthSmileRightIndex(29),
|
||||||
_jawOpenIndex(21),
|
_jawOpenIndex(21)
|
||||||
_host(host),
|
|
||||||
_port(port)
|
|
||||||
{
|
{
|
||||||
_blendshapeCoefficients.resize(NUM_EXPRESSION);
|
_blendshapeCoefficients.resize(NUM_EXPRESSION);
|
||||||
|
|
||||||
|
@ -80,18 +80,6 @@ DdeFaceTracker::~DdeFaceTracker() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DdeFaceTracker::init() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void DdeFaceTracker::reset() {
|
|
||||||
_reset = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DdeFaceTracker::update() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void DdeFaceTracker::setEnabled(bool enabled) {
|
void DdeFaceTracker::setEnabled(bool enabled) {
|
||||||
// isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket.
|
// isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket.
|
||||||
_udpSocket.close();
|
_udpSocket.close();
|
||||||
|
|
|
@ -23,12 +23,10 @@ class DdeFaceTracker : public FaceTracker, public Dependency {
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//initialization
|
virtual void reset() { _reset = true; }
|
||||||
void init();
|
|
||||||
void reset();
|
virtual bool isActive() const;
|
||||||
void update();
|
virtual bool isTracking() const { return isActive(); }
|
||||||
|
|
||||||
bool isActive() const;
|
|
||||||
|
|
||||||
float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); }
|
float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); }
|
||||||
float getRightBlink() const { return getBlendshapeCoefficient(_rightBlinkIndex); }
|
float getRightBlink() const { return getBlendshapeCoefficient(_rightBlinkIndex); }
|
||||||
|
|
|
@ -25,37 +25,11 @@ using namespace fs;
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost";
|
||||||
const quint16 FACESHIFT_PORT = 33433;
|
const quint16 FACESHIFT_PORT = 33433;
|
||||||
float STARTING_FACESHIFT_FRAME_TIME = 0.033f;
|
const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f;
|
||||||
|
|
||||||
Faceshift::Faceshift() :
|
Faceshift::Faceshift() :
|
||||||
_tcpEnabled(true),
|
|
||||||
_tcpRetryCount(0),
|
|
||||||
_lastTrackingStateReceived(0),
|
|
||||||
_averageFrameTime(STARTING_FACESHIFT_FRAME_TIME),
|
|
||||||
_headAngularVelocity(0),
|
|
||||||
_headLinearVelocity(0),
|
|
||||||
_lastHeadTranslation(0),
|
|
||||||
_filteredHeadTranslation(0),
|
|
||||||
_eyeGazeLeftPitch(0.0f),
|
|
||||||
_eyeGazeLeftYaw(0.0f),
|
|
||||||
_eyeGazeRightPitch(0.0f),
|
|
||||||
_eyeGazeRightYaw(0.0f),
|
|
||||||
_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),
|
|
||||||
_longTermAverageEyePitch(0.0f),
|
|
||||||
_longTermAverageEyeYaw(0.0f),
|
|
||||||
_longTermAverageInitialized(false),
|
|
||||||
_eyeDeflection("faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION),
|
_eyeDeflection("faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION),
|
||||||
_hostname("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME)
|
_hostname("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME)
|
||||||
{
|
{
|
||||||
|
@ -71,31 +45,15 @@ Faceshift::Faceshift() :
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_FACESHIFT
|
||||||
void Faceshift::init() {
|
void Faceshift::init() {
|
||||||
#ifdef HAVE_FACESHIFT
|
|
||||||
setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift));
|
setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Faceshift::isConnectedOrConnecting() const {
|
void Faceshift::update(float deltaTime) {
|
||||||
return _tcpSocket.state() == QAbstractSocket::ConnectedState ||
|
|
||||||
(_tcpRetryCount == 0 && _tcpSocket.state() != QAbstractSocket::UnconnectedState);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Faceshift::isActive() const {
|
|
||||||
#ifdef HAVE_FACESHIFT
|
|
||||||
const quint64 ACTIVE_TIMEOUT_USECS = 1000000;
|
|
||||||
return (usecTimestampNow() - _lastTrackingStateReceived) < ACTIVE_TIMEOUT_USECS;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void Faceshift::update() {
|
|
||||||
if (!isActive()) {
|
if (!isActive()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PerformanceTimer perfTimer("faceshift");
|
|
||||||
// get the euler angles relative to the window
|
// get the euler angles relative to the window
|
||||||
glm::vec3 eulers = glm::degrees(safeEulerAngles(_headRotation * glm::quat(glm::radians(glm::vec3(
|
glm::vec3 eulers = glm::degrees(safeEulerAngles(_headRotation * glm::quat(glm::radians(glm::vec3(
|
||||||
(_eyeGazeLeftPitch + _eyeGazeRightPitch) / 2.0f, (_eyeGazeLeftYaw + _eyeGazeRightYaw) / 2.0f, 0.0f)))));
|
(_eyeGazeLeftPitch + _eyeGazeRightPitch) / 2.0f, (_eyeGazeLeftYaw + _eyeGazeRightYaw) / 2.0f, 0.0f)))));
|
||||||
|
@ -116,14 +74,28 @@ void Faceshift::update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Faceshift::reset() {
|
void Faceshift::reset() {
|
||||||
#ifdef HAVE_FACESHIFT
|
|
||||||
if (_tcpSocket.state() == QAbstractSocket::ConnectedState) {
|
if (_tcpSocket.state() == QAbstractSocket::ConnectedState) {
|
||||||
string message;
|
string message;
|
||||||
fsBinaryStream::encode_message(message, fsMsgCalibrateNeutral());
|
fsBinaryStream::encode_message(message, fsMsgCalibrateNeutral());
|
||||||
send(message);
|
send(message);
|
||||||
}
|
}
|
||||||
_longTermAverageInitialized = false;
|
_longTermAverageInitialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Faceshift::isActive() const {
|
||||||
|
const quint64 ACTIVE_TIMEOUT_USECS = 1000000;
|
||||||
|
return (usecTimestampNow() - _lastTrackingStateReceived) < ACTIVE_TIMEOUT_USECS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Faceshift::isTracking() const {
|
||||||
|
return isActive() && _tracking;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bool Faceshift::isConnectedOrConnecting() const {
|
||||||
|
return _tcpSocket.state() == QAbstractSocket::ConnectedState ||
|
||||||
|
(_tcpRetryCount == 0 && _tcpSocket.state() != QAbstractSocket::UnconnectedState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Faceshift::updateFakeCoefficients(float leftBlink, float rightBlink, float browUp,
|
void Faceshift::updateFakeCoefficients(float leftBlink, float rightBlink, float browUp,
|
||||||
|
@ -148,12 +120,13 @@ void Faceshift::updateFakeCoefficients(float leftBlink, float rightBlink, float
|
||||||
}
|
}
|
||||||
|
|
||||||
void Faceshift::setTCPEnabled(bool enabled) {
|
void Faceshift::setTCPEnabled(bool enabled) {
|
||||||
|
#ifdef HAVE_FACESHIFT
|
||||||
if ((_tcpEnabled = enabled)) {
|
if ((_tcpEnabled = enabled)) {
|
||||||
connectSocket();
|
connectSocket();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_tcpSocket.disconnectFromHost();
|
_tcpSocket.disconnectFromHost();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Faceshift::connectSocket() {
|
void Faceshift::connectSocket() {
|
||||||
|
@ -202,10 +175,6 @@ void Faceshift::readFromSocket() {
|
||||||
receive(_tcpSocket.readAll());
|
receive(_tcpSocket.readAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
float Faceshift::getBlendshapeCoefficient(int index) const {
|
|
||||||
return (index >= 0 && index < (int)_blendshapeCoefficients.size()) ? _blendshapeCoefficients[index] : 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Faceshift::send(const std::string& message) {
|
void Faceshift::send(const std::string& message) {
|
||||||
_tcpSocket.write(message.data(), message.size());
|
_tcpSocket.write(message.data(), message.size());
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,7 @@
|
||||||
|
|
||||||
#include "FaceTracker.h"
|
#include "FaceTracker.h"
|
||||||
|
|
||||||
const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f;
|
const float STARTING_FACESHIFT_FRAME_TIME = 0.033f;
|
||||||
const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost";
|
|
||||||
|
|
||||||
/// Handles interaction with the Faceshift software, which provides head position/orientation and facial features.
|
/// Handles interaction with the Faceshift software, which provides head position/orientation and facial features.
|
||||||
class Faceshift : public FaceTracker, public Dependency {
|
class Faceshift : public FaceTracker, public Dependency {
|
||||||
|
@ -33,11 +32,17 @@ class Faceshift : public FaceTracker, public Dependency {
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init();
|
#ifdef HAVE_FACESHIFT
|
||||||
|
// If we don't have faceshift, use the base class' methods
|
||||||
|
virtual void init();
|
||||||
|
virtual void update(float deltaTime);
|
||||||
|
virtual void reset();
|
||||||
|
|
||||||
bool isConnectedOrConnecting() const;
|
virtual bool isActive() const;
|
||||||
|
virtual bool isTracking() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool isActive() const;
|
bool isConnectedOrConnecting() const;
|
||||||
|
|
||||||
const glm::vec3& getHeadAngularVelocity() const { return _headAngularVelocity; }
|
const glm::vec3& getHeadAngularVelocity() const { return _headAngularVelocity; }
|
||||||
|
|
||||||
|
@ -68,9 +73,6 @@ public:
|
||||||
|
|
||||||
QString getHostname() { return _hostname.get(); }
|
QString getHostname() { return _hostname.get(); }
|
||||||
void setHostname(const QString& hostname);
|
void setHostname(const QString& hostname);
|
||||||
|
|
||||||
void update();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
void updateFakeCoefficients(float leftBlink,
|
void updateFakeCoefficients(float leftBlink,
|
||||||
float rightBlink,
|
float rightBlink,
|
||||||
|
@ -82,15 +84,12 @@ public:
|
||||||
QVector<float>& coefficients) const;
|
QVector<float>& coefficients) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void connectionStateChanged();
|
void connectionStateChanged();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void setTCPEnabled(bool enabled);
|
void setTCPEnabled(bool enabled);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void connectSocket();
|
void connectSocket();
|
||||||
void noteConnected();
|
void noteConnected();
|
||||||
void noteError(QAbstractSocket::SocketError error);
|
void noteError(QAbstractSocket::SocketError error);
|
||||||
|
@ -101,8 +100,6 @@ private:
|
||||||
Faceshift();
|
Faceshift();
|
||||||
virtual ~Faceshift() {}
|
virtual ~Faceshift() {}
|
||||||
|
|
||||||
float getBlendshapeCoefficient(int index) const;
|
|
||||||
|
|
||||||
void send(const std::string& message);
|
void send(const std::string& message);
|
||||||
void receive(const QByteArray& buffer);
|
void receive(const QByteArray& buffer);
|
||||||
|
|
||||||
|
@ -113,48 +110,48 @@ private:
|
||||||
fs::fsBinaryStream _stream;
|
fs::fsBinaryStream _stream;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool _tcpEnabled;
|
bool _tcpEnabled = true;
|
||||||
int _tcpRetryCount;
|
int _tcpRetryCount = 0;
|
||||||
bool _tracking;
|
bool _tracking = false;
|
||||||
quint64 _lastTrackingStateReceived;
|
quint64 _lastTrackingStateReceived = 0;
|
||||||
float _averageFrameTime;
|
float _averageFrameTime = STARTING_FACESHIFT_FRAME_TIME;
|
||||||
|
|
||||||
glm::vec3 _headAngularVelocity;
|
glm::vec3 _headAngularVelocity = glm::vec3(0.0f);
|
||||||
glm::vec3 _headLinearVelocity;
|
glm::vec3 _headLinearVelocity = glm::vec3(0.0f);
|
||||||
glm::vec3 _lastHeadTranslation;
|
glm::vec3 _lastHeadTranslation = glm::vec3(0.0f);
|
||||||
glm::vec3 _filteredHeadTranslation;
|
glm::vec3 _filteredHeadTranslation = glm::vec3(0.0f);
|
||||||
|
|
||||||
// degrees
|
// degrees
|
||||||
float _eyeGazeLeftPitch;
|
float _eyeGazeLeftPitch = 0.0f;
|
||||||
float _eyeGazeLeftYaw;
|
float _eyeGazeLeftYaw = 0.0f;
|
||||||
float _eyeGazeRightPitch;
|
float _eyeGazeRightPitch = 0.0f;
|
||||||
float _eyeGazeRightYaw;
|
float _eyeGazeRightYaw = 0.0f;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
// degrees
|
// degrees
|
||||||
float _longTermAverageEyePitch;
|
float _longTermAverageEyePitch = 0.0f;
|
||||||
float _longTermAverageEyeYaw;
|
float _longTermAverageEyeYaw = 0.0f;
|
||||||
bool _longTermAverageInitialized;
|
bool _longTermAverageInitialized = false;
|
||||||
|
|
||||||
Setting::Handle<float> _eyeDeflection;
|
Setting::Handle<float> _eyeDeflection;
|
||||||
Setting::Handle<QString> _hostname;
|
Setting::Handle<QString> _hostname;
|
||||||
|
|
||||||
|
// see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
|
||||||
|
int _leftBlinkIndex = 0;
|
||||||
|
int _rightBlinkIndex = 1;
|
||||||
|
int _leftEyeOpenIndex = 8;
|
||||||
|
int _rightEyeOpenIndex = 9;
|
||||||
|
|
||||||
|
// Brows
|
||||||
|
int _browDownLeftIndex = 14;
|
||||||
|
int _browDownRightIndex = 15;
|
||||||
|
int _browUpCenterIndex = 16;
|
||||||
|
int _browUpLeftIndex = 17;
|
||||||
|
int _browUpRightIndex = 18;
|
||||||
|
|
||||||
|
int _mouthSmileLeftIndex = 28;
|
||||||
|
int _mouthSmileRightIndex = 29;
|
||||||
|
|
||||||
|
int _jawOpenIndex = 21;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Faceshift_h
|
#endif // hifi_Faceshift_h
|
||||||
|
|
|
@ -126,13 +126,12 @@ void Visage::init() {
|
||||||
updateEnabled();
|
updateEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Visage::update() {
|
void Visage::update(float deltaTime) {
|
||||||
#ifdef HAVE_VISAGE
|
#ifdef HAVE_VISAGE
|
||||||
_active = (_tracker->getTrackingData(_data) == TRACK_STAT_OK);
|
_active = (_tracker->getTrackingData(_data) == TRACK_STAT_OK);
|
||||||
if (!_active) {
|
if (!_active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PerformanceTimer perfTimer("visage");
|
|
||||||
_headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2]));
|
_headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2]));
|
||||||
_headTranslation = (glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) -
|
_headTranslation = (glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) -
|
||||||
_headOrigin) * TRANSLATION_SCALE;
|
_headOrigin) * TRANSLATION_SCALE;
|
||||||
|
|
|
@ -31,12 +31,12 @@ class Visage : public FaceTracker, public Dependency {
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init();
|
virtual void init();
|
||||||
|
virtual void update(float deltaTime);
|
||||||
|
virtual void reset();
|
||||||
|
|
||||||
bool isActive() const { return _active; }
|
virtual bool isActive() const { return _active; }
|
||||||
|
virtual bool isTracking() const { return isActive(); }
|
||||||
void update();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue