mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 18:26:26 +02:00
Added all relevant curves to RecordingFrames
This commit is contained in:
parent
96ee9e3f75
commit
18ff497443
2 changed files with 248 additions and 16 deletions
|
@ -9,6 +9,8 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <GLMHelpers.h>
|
||||||
|
|
||||||
#include "Recorder.h"
|
#include "Recorder.h"
|
||||||
|
|
||||||
void RecordingFrame::setBlendshapeCoefficients(QVector<float> blendshapeCoefficients) {
|
void RecordingFrame::setBlendshapeCoefficients(QVector<float> blendshapeCoefficients) {
|
||||||
|
@ -23,6 +25,34 @@ void RecordingFrame::setTranslation(glm::vec3 translation) {
|
||||||
_translation = translation;
|
_translation = translation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RecordingFrame::setRotation(glm::quat rotation) {
|
||||||
|
_rotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordingFrame::setScale(float scale) {
|
||||||
|
_scale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordingFrame::setHeadRotation(glm::quat headRotation) {
|
||||||
|
_headRotation = headRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordingFrame::setLeanSideways(float leanSideways) {
|
||||||
|
_leanSideways = leanSideways;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordingFrame::setLeanForward(float leanForward) {
|
||||||
|
_leanForward = leanForward;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordingFrame::setEstimatedEyePitch(float estimatedEyePitch) {
|
||||||
|
_estimatedEyePitch = estimatedEyePitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordingFrame::setEstimatedEyeYaw(float estimatedEyeYaw) {
|
||||||
|
_estimatedEyeYaw = estimatedEyeYaw;
|
||||||
|
}
|
||||||
|
|
||||||
void Recording::addFrame(int timestamp, RecordingFrame &frame) {
|
void Recording::addFrame(int timestamp, RecordingFrame &frame) {
|
||||||
_timestamps << timestamp;
|
_timestamps << timestamp;
|
||||||
_frames << frame;
|
_frames << frame;
|
||||||
|
@ -33,7 +63,10 @@ void Recording::clear() {
|
||||||
_frames.clear();
|
_frames.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Recorder::Recorder(AvatarData* avatar) : _avatar(avatar) {
|
Recorder::Recorder(AvatarData* avatar) :
|
||||||
|
_recording(new Recording()),
|
||||||
|
_avatar(avatar)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Recorder::isRecording() const {
|
bool Recorder::isRecording() const {
|
||||||
|
@ -49,29 +82,72 @@ qint64 Recorder::elapsed() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Recorder::startRecording() {
|
void Recorder::startRecording() {
|
||||||
_recording.clear();
|
qDebug() << "Recorder::startRecording()";
|
||||||
|
_recording->clear();
|
||||||
_timer.start();
|
_timer.start();
|
||||||
|
|
||||||
|
RecordingFrame frame;
|
||||||
|
frame.setBlendshapeCoefficients(_avatar->getHeadData()->getBlendshapeCoefficients());
|
||||||
|
frame.setJointRotations(_avatar->getJointRotations());
|
||||||
|
frame.setTranslation(_avatar->getPosition());
|
||||||
|
frame.setRotation(_avatar->getOrientation());
|
||||||
|
frame.setScale(_avatar->getTargetScale());
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
const HeadData* head = _avatar->getHeadData();
|
||||||
|
glm::quat rotation = glm::quat(glm::radians(glm::vec3(head->getFinalPitch(),
|
||||||
|
head->getFinalYaw(),
|
||||||
|
head->getFinalRoll())));
|
||||||
|
frame.setHeadRotation(rotation);
|
||||||
|
// TODO
|
||||||
|
//frame.setEstimatedEyePitch();
|
||||||
|
//frame.setEstimatedEyeYaw();
|
||||||
|
|
||||||
|
_recording->addFrame(0, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Recorder::stopRecording() {
|
void Recorder::stopRecording() {
|
||||||
|
qDebug() << "Recorder::stopRecording()";
|
||||||
_timer.invalidate();
|
_timer.invalidate();
|
||||||
|
|
||||||
|
qDebug().nospace() << "Recorded " << _recording->getFrameNumber() << " during " << _recording->getLength() << " msec (" << _recording->getFrameNumber() / (_recording->getLength() / 1000.0f) << " fps)";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Recorder::saveToFile(QString file) {
|
void Recorder::saveToFile(QString file) {
|
||||||
if (_recording.isEmpty()) {
|
if (_recording->isEmpty()) {
|
||||||
qDebug() << "Cannot save recording to file, recording is empty.";
|
qDebug() << "Cannot save recording to file, recording is empty.";
|
||||||
}
|
}
|
||||||
|
|
||||||
writeRecordingToFile(_recording, file);
|
writeRecordingToFile(*_recording, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Recorder::record() {
|
void Recorder::record() {
|
||||||
qDebug() << "Recording " << _avatar;
|
if (isRecording()) {
|
||||||
RecordingFrame frame;
|
const RecordingFrame& referenceFrame = _recording->getFrame(0);
|
||||||
frame.setBlendshapeCoefficients(_avatar->_)
|
RecordingFrame frame;
|
||||||
|
frame.setBlendshapeCoefficients(_avatar->getHeadData()->getBlendshapeCoefficients());
|
||||||
|
frame.setJointRotations(_avatar->getJointRotations());
|
||||||
|
frame.setTranslation(_avatar->getPosition() - referenceFrame.getTranslation());
|
||||||
|
frame.setRotation(glm::inverse(referenceFrame.getRotation()) * _avatar->getOrientation());
|
||||||
|
frame.setScale(_avatar->getTargetScale() / referenceFrame.getScale());
|
||||||
|
// TODO
|
||||||
|
//frame.setHeadTranslation();
|
||||||
|
const HeadData* head = _avatar->getHeadData();
|
||||||
|
glm::quat rotation = glm::quat(glm::radians(glm::vec3(head->getFinalPitch(),
|
||||||
|
head->getFinalYaw(),
|
||||||
|
head->getFinalRoll())));
|
||||||
|
frame.setHeadRotation(glm::inverse(referenceFrame.getHeadRotation()) * rotation);
|
||||||
|
// TODO
|
||||||
|
//frame.setEstimatedEyePitch();
|
||||||
|
//frame.setEstimatedEyeYaw();
|
||||||
|
_recording->addFrame(_timer.elapsed(), frame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Player::Player(AvatarData* avatar) : _avatar(avatar) {
|
Player::Player(AvatarData* avatar) :
|
||||||
|
_recording(new Recording()),
|
||||||
|
_avatar(avatar)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::isPlaying() const {
|
bool Player::isPlaying() const {
|
||||||
|
@ -86,21 +162,129 @@ qint64 Player::elapsed() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<float> Player::getBlendshapeCoefficients() {
|
||||||
|
computeCurrentFrame();
|
||||||
|
return _recording->getFrame(_currentFrame).getBlendshapeCoefficients();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<glm::quat> Player::getJointRotations() {
|
||||||
|
computeCurrentFrame();
|
||||||
|
return _recording->getFrame(_currentFrame).getJointRotations();
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::quat Player::getRotation() {
|
||||||
|
computeCurrentFrame();
|
||||||
|
return _recording->getFrame(_currentFrame).getRotation();
|
||||||
|
}
|
||||||
|
|
||||||
|
float Player::getScale() {
|
||||||
|
computeCurrentFrame();
|
||||||
|
return _recording->getFrame(_currentFrame).getScale();
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::quat Player::getHeadRotation() {
|
||||||
|
computeCurrentFrame();
|
||||||
|
if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) {
|
||||||
|
if (_currentFrame == _recording->getFrameNumber()) {
|
||||||
|
return _recording->getFrame(0).getHeadRotation() *
|
||||||
|
_recording->getFrame(_currentFrame - 1).getHeadRotation();
|
||||||
|
}
|
||||||
|
if (_currentFrame == 0) {
|
||||||
|
return _recording->getFrame(_currentFrame).getHeadRotation();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _recording->getFrame(0).getHeadRotation() *
|
||||||
|
_recording->getFrame(_currentFrame).getHeadRotation();
|
||||||
|
}
|
||||||
|
qWarning() << "Incorrect use of Player::getHeadRotation()";
|
||||||
|
return glm::quat();
|
||||||
|
}
|
||||||
|
|
||||||
|
float Player::getEstimatedEyePitch() {
|
||||||
|
computeCurrentFrame();
|
||||||
|
return _recording->getFrame(_currentFrame).getEstimatedEyePitch();
|
||||||
|
}
|
||||||
|
|
||||||
|
float Player::getEstimatedEyeYaw() {
|
||||||
|
computeCurrentFrame();
|
||||||
|
return _recording->getFrame(_currentFrame).getEstimatedEyeYaw();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Player::startPlaying() {
|
void Player::startPlaying() {
|
||||||
_timer.start();
|
if (_recording && _recording->getFrameNumber() > 0) {
|
||||||
|
qDebug() << "Recorder::startPlaying()";
|
||||||
|
_timer.start();
|
||||||
|
_currentFrame = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::stopPlaying() {
|
void Player::stopPlaying() {
|
||||||
|
qDebug() << "Recorder::stopPlaying()";
|
||||||
_timer.invalidate();
|
_timer.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::loadFromFile(QString file) {
|
void Player::loadFromFile(QString file) {
|
||||||
_recording.clear();
|
if (_recording) {
|
||||||
readRecordingFromFile(_recording, file);
|
_recording->clear();
|
||||||
|
} else {
|
||||||
|
_recording = RecordingPointer(new Recording());
|
||||||
|
}
|
||||||
|
readRecordingFromFile(*_recording, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::loadRecording(RecordingPointer recording) {
|
||||||
|
_recording = recording;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::play() {
|
void Player::play() {
|
||||||
qDebug() << "Playing " << _avatar;
|
qDebug() << "Playing " << _timer.elapsed() / 1000.0f;
|
||||||
|
computeCurrentFrame();
|
||||||
|
if (_currentFrame < 0 || _currentFrame >= _recording->getFrameNumber()) {
|
||||||
|
// If it's the end of the recording, stop playing
|
||||||
|
stopPlaying();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_currentFrame == 0) {
|
||||||
|
_avatar->setPosition(_recording->getFrame(_currentFrame).getTranslation());
|
||||||
|
_avatar->setOrientation(_recording->getFrame(_currentFrame).getRotation());
|
||||||
|
_avatar->setTargetScale(_recording->getFrame(_currentFrame).getScale());
|
||||||
|
HeadData* head = const_cast<HeadData*>(_avatar->getHeadData());
|
||||||
|
head->setBlendshapeCoefficients(_recording->getFrame(_currentFrame).getBlendshapeCoefficients());
|
||||||
|
// TODO
|
||||||
|
// HEAD: Coeff, Translation, estimated eye rotations
|
||||||
|
// BODY: Joint Rotations
|
||||||
|
} else {
|
||||||
|
_avatar->setPosition(_recording->getFrame(0).getTranslation() +
|
||||||
|
_recording->getFrame(_currentFrame).getTranslation());
|
||||||
|
_avatar->setOrientation(_recording->getFrame(0).getRotation() *
|
||||||
|
_recording->getFrame(_currentFrame).getRotation());
|
||||||
|
_avatar->setTargetScale(_recording->getFrame(0).getScale() *
|
||||||
|
_recording->getFrame(_currentFrame).getScale());
|
||||||
|
HeadData* head = const_cast<HeadData*>(_avatar->getHeadData());
|
||||||
|
head->setBlendshapeCoefficients(_recording->getFrame(_currentFrame).getBlendshapeCoefficients());
|
||||||
|
// TODO
|
||||||
|
// HEAD: Coeff, Translation, estimated eye rotations
|
||||||
|
// BODY: Joint Rotations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::computeCurrentFrame() {
|
||||||
|
if (!isPlaying()) {
|
||||||
|
qDebug() << "Not Playing";
|
||||||
|
_currentFrame = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_currentFrame < 0) {
|
||||||
|
qDebug() << "Reset to 0";
|
||||||
|
_currentFrame = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (_currentFrame < _recording->getFrameNumber() &&
|
||||||
|
_recording->getFrameTimestamp(_currentFrame) < _timer.elapsed()) {
|
||||||
|
qDebug() << "Loop";
|
||||||
|
++_currentFrame;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeRecordingToFile(Recording& recording, QString file) {
|
void writeRecordingToFile(Recording& recording, QString file) {
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
#include <QBitArray>
|
#include <QBitArray>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QSharedPointer>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <QWeakPointer>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
@ -23,7 +25,15 @@
|
||||||
#include <AvatarData.h>
|
#include <AvatarData.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
class Recorder;
|
||||||
class Recording;
|
class Recording;
|
||||||
|
class Player;
|
||||||
|
|
||||||
|
typedef QSharedPointer<Recording> RecordingPointer;
|
||||||
|
typedef QSharedPointer<Recorder> RecorderPointer;
|
||||||
|
typedef QWeakPointer<Recorder> WeakRecorderPointer;
|
||||||
|
typedef QSharedPointer<Player> PlayerPointer;
|
||||||
|
typedef QWeakPointer<Player> WeakPlayerPointer;
|
||||||
|
|
||||||
/// Stores the different values associated to one recording frame
|
/// Stores the different values associated to one recording frame
|
||||||
class RecordingFrame {
|
class RecordingFrame {
|
||||||
|
@ -31,20 +41,41 @@ public:
|
||||||
QVector<float> getBlendshapeCoefficients() const { return _blendshapeCoefficients; }
|
QVector<float> getBlendshapeCoefficients() const { return _blendshapeCoefficients; }
|
||||||
QVector<glm::quat> getJointRotations() const { return _jointRotations; }
|
QVector<glm::quat> getJointRotations() const { return _jointRotations; }
|
||||||
glm::vec3 getTranslation() const { return _translation; }
|
glm::vec3 getTranslation() const { return _translation; }
|
||||||
|
glm::quat getRotation() const { return _rotation; }
|
||||||
|
float getScale() const { return _scale; }
|
||||||
|
glm::quat getHeadRotation() const { return _headRotation; }
|
||||||
|
float getLeanSideways() const { return _leanSideways; }
|
||||||
|
float getLeanForward() const { return _leanForward; }
|
||||||
|
float getEstimatedEyePitch() const { return _estimatedEyePitch; }
|
||||||
|
float getEstimatedEyeYaw() const { return _estimatedEyeYaw; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setBlendshapeCoefficients(QVector<float> blendshapeCoefficients);
|
void setBlendshapeCoefficients(QVector<float> blendshapeCoefficients);
|
||||||
void setJointRotations(QVector<glm::quat> jointRotations);
|
void setJointRotations(QVector<glm::quat> jointRotations);
|
||||||
void setTranslation(glm::vec3 translation);
|
void setTranslation(glm::vec3 translation);
|
||||||
|
void setRotation(glm::quat rotation);
|
||||||
|
void setScale(float scale);
|
||||||
|
void setHeadRotation(glm::quat headRotation);
|
||||||
|
void setLeanSideways(float leanSideways);
|
||||||
|
void setLeanForward(float leanForward);
|
||||||
|
void setEstimatedEyePitch(float estimatedEyePitch);
|
||||||
|
void setEstimatedEyeYaw(float estimatedEyeYaw);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVector<float> _blendshapeCoefficients;
|
QVector<float> _blendshapeCoefficients;
|
||||||
QVector<glm::quat> _jointRotations;
|
QVector<glm::quat> _jointRotations;
|
||||||
glm::vec3 _translation;
|
glm::vec3 _translation;
|
||||||
|
glm::quat _rotation;
|
||||||
|
float _scale;
|
||||||
|
glm::quat _headRotation;
|
||||||
|
float _leanSideways;
|
||||||
|
float _leanForward;
|
||||||
|
float _estimatedEyePitch;
|
||||||
|
float _estimatedEyeYaw;
|
||||||
|
|
||||||
friend class Recorder;
|
friend class Recorder;
|
||||||
friend void writeRecordingToFile(Recording& recording, QString file);
|
friend void writeRecordingToFile(Recording& recording, QString file);
|
||||||
friend Recording* readRecordingFromFile(QString file);
|
friend RecordingPointer readRecordingFromFile(QString file);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Stores a recording
|
/// Stores a recording
|
||||||
|
@ -52,6 +83,7 @@ class Recording {
|
||||||
public:
|
public:
|
||||||
bool isEmpty() const { return _timestamps.isEmpty(); }
|
bool isEmpty() const { return _timestamps.isEmpty(); }
|
||||||
int getLength() const { return _timestamps.last(); } // in ms
|
int getLength() const { return _timestamps.last(); } // in ms
|
||||||
|
int getFrameNumber() const { return _frames.size(); }
|
||||||
|
|
||||||
qint32 getFrameTimestamp(int i) const { return _timestamps[i]; }
|
qint32 getFrameTimestamp(int i) const { return _timestamps[i]; }
|
||||||
const RecordingFrame& getFrame(int i) const { return _frames[i]; }
|
const RecordingFrame& getFrame(int i) const { return _frames[i]; }
|
||||||
|
@ -67,7 +99,7 @@ private:
|
||||||
friend class Recorder;
|
friend class Recorder;
|
||||||
friend class Player;
|
friend class Player;
|
||||||
friend void writeRecordingToFile(Recording& recording, QString file);
|
friend void writeRecordingToFile(Recording& recording, QString file);
|
||||||
friend Recording* readRecordingFromFile(QString file);
|
friend RecordingPointer readRecordingFromFile(QString file);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,6 +111,8 @@ public:
|
||||||
bool isRecording() const;
|
bool isRecording() const;
|
||||||
qint64 elapsed() const;
|
qint64 elapsed() const;
|
||||||
|
|
||||||
|
RecordingPointer getRecording() const { return _recording; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void startRecording();
|
void startRecording();
|
||||||
void stopRecording();
|
void stopRecording();
|
||||||
|
@ -87,7 +121,7 @@ public slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QElapsedTimer _timer;
|
QElapsedTimer _timer;
|
||||||
Recording _recording;
|
RecordingPointer _recording;
|
||||||
|
|
||||||
AvatarData* _avatar;
|
AvatarData* _avatar;
|
||||||
};
|
};
|
||||||
|
@ -100,15 +134,29 @@ public:
|
||||||
bool isPlaying() const;
|
bool isPlaying() const;
|
||||||
qint64 elapsed() const;
|
qint64 elapsed() const;
|
||||||
|
|
||||||
|
// Those should only be called if isPlaying() returns true
|
||||||
|
QVector<float> getBlendshapeCoefficients();
|
||||||
|
QVector<glm::quat> getJointRotations();
|
||||||
|
glm::quat getRotation();
|
||||||
|
float getScale();
|
||||||
|
glm::vec3 getHeadTranslation();
|
||||||
|
glm::quat getHeadRotation();
|
||||||
|
float getEstimatedEyePitch();
|
||||||
|
float getEstimatedEyeYaw();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void startPlaying();
|
void startPlaying();
|
||||||
void stopPlaying();
|
void stopPlaying();
|
||||||
void loadFromFile(QString file);
|
void loadFromFile(QString file);
|
||||||
|
void loadRecording(RecordingPointer recording);
|
||||||
void play();
|
void play();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void computeCurrentFrame();
|
||||||
|
|
||||||
QElapsedTimer _timer;
|
QElapsedTimer _timer;
|
||||||
Recording _recording;
|
RecordingPointer _recording;
|
||||||
|
int _currentFrame;
|
||||||
|
|
||||||
AvatarData* _avatar;
|
AvatarData* _avatar;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue