mirror of
https://github.com/overte-org/overte.git
synced 2025-06-15 21:59:22 +02:00
Add velocity filtering to DDE head movement
Based on filtering code in Faceshift.cpp.
This commit is contained in:
parent
3e484ee208
commit
c46f21152f
2 changed files with 48 additions and 3 deletions
|
@ -17,6 +17,8 @@
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
|
|
||||||
|
#include <GLMHelpers.h>
|
||||||
|
|
||||||
#include "DdeFaceTracker.h"
|
#include "DdeFaceTracker.h"
|
||||||
#include "FaceshiftConstants.h"
|
#include "FaceshiftConstants.h"
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
|
@ -267,6 +269,8 @@ float DdeFaceTracker::getBlendshapeCoefficient(int index) const {
|
||||||
|
|
||||||
void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
|
void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
|
||||||
if(buffer.size() > MIN_PACKET_SIZE) {
|
if(buffer.size() > MIN_PACKET_SIZE) {
|
||||||
|
bool isFitering = Menu::getInstance()->isOptionChecked(MenuOption::DDEFiltering);
|
||||||
|
|
||||||
Packet packet;
|
Packet packet;
|
||||||
int bytesToCopy = glm::min((int)sizeof(packet), buffer.size());
|
int bytesToCopy = glm::min((int)sizeof(packet), buffer.size());
|
||||||
memset(&packet.name, '\n', MAX_NAME_SIZE + 1);
|
memset(&packet.name, '\n', MAX_NAME_SIZE + 1);
|
||||||
|
@ -287,11 +291,36 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
|
||||||
translation -= _referenceTranslation;
|
translation -= _referenceTranslation;
|
||||||
translation /= LEAN_DAMPING_FACTOR;
|
translation /= LEAN_DAMPING_FACTOR;
|
||||||
translation.x *= -1;
|
translation.x *= -1;
|
||||||
|
if (isFitering) {
|
||||||
|
glm::vec3 linearVelocity = (translation - _lastHeadTranslation) / _averageMessageTime;
|
||||||
|
const float LINEAR_VELOCITY_FILTER_STRENGTH = 0.3f;
|
||||||
|
float velocityFilter = glm::clamp(1.0f - glm::length(linearVelocity) *
|
||||||
|
LINEAR_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f);
|
||||||
|
_filteredHeadTranslation = velocityFilter * _filteredHeadTranslation + (1.0f - velocityFilter) * translation;
|
||||||
|
_lastHeadTranslation = translation;
|
||||||
|
_headTranslation = _filteredHeadTranslation;
|
||||||
|
} else {
|
||||||
_headTranslation = translation;
|
_headTranslation = translation;
|
||||||
|
}
|
||||||
|
|
||||||
// Compute relative rotation
|
// Compute relative rotation
|
||||||
rotation = glm::inverse(_referenceRotation) * rotation;
|
rotation = glm::inverse(_referenceRotation) * rotation;
|
||||||
|
if (isFitering) {
|
||||||
|
glm::quat r = rotation * glm::inverse(_headRotation);
|
||||||
|
float theta = 2 * acos(r.w);
|
||||||
|
glm::vec3 angularVelocity;
|
||||||
|
if (theta > EPSILON) {
|
||||||
|
float rMag = glm::length(glm::vec3(r.x, r.y, r.z));
|
||||||
|
angularVelocity = theta / _averageMessageTime * glm::vec3(r.x, r.y, r.z) / rMag;
|
||||||
|
} else {
|
||||||
|
angularVelocity = glm::vec3(0, 0, 0);
|
||||||
|
}
|
||||||
|
const float ANGULAR_VELOCITY_FILTER_STRENGTH = 0.3f;
|
||||||
|
_headRotation = safeMix(_headRotation, rotation, glm::clamp(glm::length(angularVelocity) *
|
||||||
|
ANGULAR_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f));
|
||||||
|
} else {
|
||||||
_headRotation = rotation;
|
_headRotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
// Translate DDE coefficients to Faceshift compatible coefficients
|
// Translate DDE coefficients to Faceshift compatible coefficients
|
||||||
for (int i = 0; i < NUM_EXPRESSIONS; i += 1) {
|
for (int i = 0; i < NUM_EXPRESSIONS; i += 1) {
|
||||||
|
@ -339,6 +368,15 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
|
||||||
= glm::clamp(DDE_COEFFICIENT_SCALES[i] * _coefficients[i], 0.0f, 1.0f);
|
= glm::clamp(DDE_COEFFICIENT_SCALES[i] * _coefficients[i], 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate average frame time
|
||||||
|
const float FRAME_AVERAGING_FACTOR = 0.99f;
|
||||||
|
quint64 usecsNow = usecTimestampNow();
|
||||||
|
if (_lastMessageReceived != 0) {
|
||||||
|
_averageMessageTime = FRAME_AVERAGING_FACTOR * _averageMessageTime
|
||||||
|
+ (1.0f - FRAME_AVERAGING_FACTOR) * (float)(usecsNow - _lastMessageReceived) / 1000000.0f;
|
||||||
|
}
|
||||||
|
_lastMessageReceived = usecsNow;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
qCDebug(interfaceapp) << "[Error] DDE Face Tracker Decode Error";
|
qCDebug(interfaceapp) << "[Error] DDE Face Tracker Decode Error";
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#include "FaceTracker.h"
|
#include "FaceTracker.h"
|
||||||
|
|
||||||
|
const float STARTING_DDE_MESSAGE_TIME = 0.033f;
|
||||||
|
|
||||||
class DdeFaceTracker : public FaceTracker, public Dependency {
|
class DdeFaceTracker : public FaceTracker, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
@ -100,6 +102,11 @@ private:
|
||||||
int _jawOpenIndex;
|
int _jawOpenIndex;
|
||||||
|
|
||||||
QVector<float> _coefficients;
|
QVector<float> _coefficients;
|
||||||
|
|
||||||
|
quint64 _lastMessageReceived = 0;
|
||||||
|
float _averageMessageTime = STARTING_DDE_MESSAGE_TIME;
|
||||||
|
glm::vec3 _lastHeadTranslation = glm::vec3(0.0f);
|
||||||
|
glm::vec3 _filteredHeadTranslation = glm::vec3(0.0f);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_DdeFaceTracker_h
|
#endif // hifi_DdeFaceTracker_h
|
Loading…
Reference in a new issue