mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 08:49:05 +02:00
More progress on Faceplus integration.
This commit is contained in:
parent
5b0e7f818d
commit
55e0035fc8
7 changed files with 135 additions and 8 deletions
|
@ -301,6 +301,11 @@ Menu::Menu() :
|
||||||
true,
|
true,
|
||||||
appInstance->getFaceshift(),
|
appInstance->getFaceshift(),
|
||||||
SLOT(setTCPEnabled(bool)));
|
SLOT(setTCPEnabled(bool)));
|
||||||
|
#ifdef HAVE_FACEPLUS
|
||||||
|
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Faceplus, 0, true,
|
||||||
|
appInstance->getFaceplus(), SLOT(updateEnabled()));
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_VISAGE
|
#ifdef HAVE_VISAGE
|
||||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Visage, 0, true,
|
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Visage, 0, true,
|
||||||
appInstance->getVisage(), SLOT(updateEnabled()));
|
appInstance->getVisage(), SLOT(updateEnabled()));
|
||||||
|
|
|
@ -250,6 +250,7 @@ namespace MenuOption {
|
||||||
const QString EchoLocalAudio = "Echo Local Audio";
|
const QString EchoLocalAudio = "Echo Local Audio";
|
||||||
const QString EchoServerAudio = "Echo Server Audio";
|
const QString EchoServerAudio = "Echo Server Audio";
|
||||||
const QString Enable3DTVMode = "Enable 3DTV Mode";
|
const QString Enable3DTVMode = "Enable 3DTV Mode";
|
||||||
|
const QString Faceplus = "Faceplus";
|
||||||
const QString Faceshift = "Faceshift";
|
const QString Faceshift = "Faceshift";
|
||||||
const QString FilterSixense = "Smooth Sixense Movement";
|
const QString FilterSixense = "Smooth Sixense Movement";
|
||||||
const QString FirstPerson = "First Person";
|
const QString FirstPerson = "First Person";
|
||||||
|
|
|
@ -10,23 +10,132 @@
|
||||||
#include <faceplus.h>
|
#include <faceplus.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
#include "Faceplus.h"
|
#include "Faceplus.h"
|
||||||
|
#include "renderer/FBXReader.h"
|
||||||
|
|
||||||
Faceplus::Faceplus() :
|
Faceplus::Faceplus() :
|
||||||
|
_enabled(false),
|
||||||
_active(false) {
|
_active(false) {
|
||||||
}
|
|
||||||
|
|
||||||
void Faceplus::init() {
|
|
||||||
#ifdef HAVE_FACEPLUS
|
#ifdef HAVE_FACEPLUS
|
||||||
// these are ignored--any values will do
|
// these are ignored--any values will do
|
||||||
faceplus_log_in("username", "password");
|
faceplus_log_in("username", "password");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Faceplus::~Faceplus() {
|
||||||
|
setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Faceplus::init() {
|
||||||
|
connect(Application::getInstance()->getFaceshift(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled()));
|
||||||
|
updateEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_FACEPLUS
|
||||||
|
static QMultiHash<QByteArray, QPair<int, float> > createChannelNameMap() {
|
||||||
|
QMultiHash<QByteArray, QPair<QByteArray, float> > blendshapeMap;
|
||||||
|
blendshapeMap.insert("JawFwd", QPair<QByteArray, float>("au_jaw_z_push", 1.0f));
|
||||||
|
blendshapeMap.insert("JawLeft", QPair<QByteArray, float>("au_jaw_x_push", 1.0f));
|
||||||
|
blendshapeMap.insert("JawOpen", QPair<QByteArray, float>("au_jaw_drop", 1.0f));
|
||||||
|
blendshapeMap.insert("LipsLowerDown", QPair<QByteArray, float>("au_lower_lip_drop", 1.0f));
|
||||||
|
blendshapeMap.insert("LipsUpperOpen", QPair<QByteArray, float>("au_upper_lip_raiser", 1.0f));
|
||||||
|
blendshapeMap.insert("LipsStretch_R", QPair<QByteArray, float>("au_lip_stretcher_left", 0.5f));
|
||||||
|
blendshapeMap.insert("MouthSmile_L", QPair<QByteArray, float>("au_lip_corner_depressor", -1.0f));
|
||||||
|
blendshapeMap.insert("MouthSmile_R", QPair<QByteArray, float>("au_lip_corner_depressor", -1.0f));
|
||||||
|
blendshapeMap.insert("BrowsU_R", QPair<QByteArray, float>("au_left_outer_brow_raiser", 1.0f));
|
||||||
|
blendshapeMap.insert("BrowsU_C", QPair<QByteArray, float>("au_left_inner_brow_raiser", 1.0f));
|
||||||
|
blendshapeMap.insert("BrowsD_R", QPair<QByteArray, float>("au_left_brow_lowerer", 1.0f));
|
||||||
|
blendshapeMap.insert("EyeBlink_L", QPair<QByteArray, float>("au_leye_closed", 1.0f));
|
||||||
|
blendshapeMap.insert("EyeBlink_R", QPair<QByteArray, float>("au_reye_closed", 1.0f));
|
||||||
|
blendshapeMap.insert("EyeOpen_L", QPair<QByteArray, float>("au_upper_lid_raiser", 1.0f));
|
||||||
|
blendshapeMap.insert("EyeOpen_R", QPair<QByteArray, float>("au_upper_lid_raiser", 1.0f));
|
||||||
|
blendshapeMap.insert("LipLowerOpen", QPair<QByteArray, float>("au_lower_lip_x_push", 1.0f));
|
||||||
|
blendshapeMap.insert("LipsStretch_L", QPair<QByteArray, float>("au_lip_stretcher_right", 0.5f));
|
||||||
|
blendshapeMap.insert("BrowsU_L", QPair<QByteArray, float>("au_right_outer_brow_raiser", 1.0f));
|
||||||
|
blendshapeMap.insert("BrowsU_C", QPair<QByteArray, float>("au_right_inner_brow_raiser", 1.0f));
|
||||||
|
blendshapeMap.insert("BrowsD_L", QPair<QByteArray, float>("au_right_brow_lowerer", 1.0f));
|
||||||
|
|
||||||
|
QMultiHash<QByteArray, QPair<int, float> > channelNameMap;
|
||||||
|
for (int i = 0;; i++) {
|
||||||
|
QByteArray blendshape = FACESHIFT_BLENDSHAPES[i];
|
||||||
|
if (blendshape.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (QMultiHash<QByteArray, QPair<QByteArray, float> >::const_iterator it = blendshapeMap.constFind(blendshape);
|
||||||
|
it != blendshapeMap.constEnd() && it.key() == blendshape; it++) {
|
||||||
|
channelNameMap.insert(it.value().first, QPair<int, float>(i, it.value().second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return channelNameMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const QMultiHash<QByteArray, QPair<int, float> >& getChannelNameMap() {
|
||||||
|
static QMultiHash<QByteArray, QPair<int, float> > channelNameMap = createChannelNameMap();
|
||||||
|
return channelNameMap;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Faceplus::update() {
|
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<int, QPair<int, float> >::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::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<QByteArray, QPair<int, float> >::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
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
#ifndef __interface__Faceplus__
|
#ifndef __interface__Faceplus__
|
||||||
#define __interface__Faceplus__
|
#define __interface__Faceplus__
|
||||||
|
|
||||||
|
#include <QMultiHash>
|
||||||
|
#include <QPair>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
#include "FaceTracker.h"
|
#include "FaceTracker.h"
|
||||||
|
|
||||||
/// Interface for Mixamo FacePlus.
|
/// Interface for Mixamo FacePlus.
|
||||||
|
@ -18,6 +22,7 @@ class Faceplus : public FaceTracker {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Faceplus();
|
Faceplus();
|
||||||
|
virtual ~Faceplus();
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
@ -26,9 +31,21 @@ public:
|
||||||
void update();
|
void update();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void updateEnabled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void setEnabled(bool enabled);
|
||||||
|
|
||||||
|
bool _enabled;
|
||||||
bool _active;
|
bool _active;
|
||||||
|
|
||||||
|
#ifdef HAVE_VISAGE
|
||||||
|
QMultiHash<int, QPair<int, float> > _channelIndexMap;
|
||||||
|
QVector<float> _outputVector;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__interface__Faceplus__) */
|
#endif /* defined(__interface__Faceplus__) */
|
||||||
|
|
|
@ -12,9 +12,6 @@
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
#include <QUdpSocket>
|
#include <QUdpSocket>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <glm/gtc/quaternion.hpp>
|
|
||||||
|
|
||||||
#include <fsbinarystream.h>
|
#include <fsbinarystream.h>
|
||||||
|
|
||||||
#include "FaceTracker.h"
|
#include "FaceTracker.h"
|
||||||
|
|
|
@ -159,6 +159,7 @@ void Visage::reset() {
|
||||||
|
|
||||||
void Visage::updateEnabled() {
|
void Visage::updateEnabled() {
|
||||||
setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) &&
|
setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) &&
|
||||||
|
!Menu::getInstance()->isOptionChecked(MenuOption::Faceplus) &&
|
||||||
!(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) &&
|
!(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) &&
|
||||||
Application::getInstance()->getFaceshift()->isConnectedOrConnecting()));
|
Application::getInstance()->getFaceshift()->isConnectedOrConnecting()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,6 @@
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <glm/gtc/quaternion.hpp>
|
|
||||||
|
|
||||||
#include "FaceTracker.h"
|
#include "FaceTracker.h"
|
||||||
|
|
||||||
namespace VisageSDK {
|
namespace VisageSDK {
|
||||||
|
|
Loading…
Reference in a new issue