mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 18:44:00 +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
|
||||
//
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
#include "Recorder.h"
|
||||
|
||||
void RecordingFrame::setBlendshapeCoefficients(QVector<float> blendshapeCoefficients) {
|
||||
|
@ -23,6 +25,34 @@ void RecordingFrame::setTranslation(glm::vec3 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) {
|
||||
_timestamps << timestamp;
|
||||
_frames << frame;
|
||||
|
@ -33,7 +63,10 @@ void Recording::clear() {
|
|||
_frames.clear();
|
||||
}
|
||||
|
||||
Recorder::Recorder(AvatarData* avatar) : _avatar(avatar) {
|
||||
Recorder::Recorder(AvatarData* avatar) :
|
||||
_recording(new Recording()),
|
||||
_avatar(avatar)
|
||||
{
|
||||
}
|
||||
|
||||
bool Recorder::isRecording() const {
|
||||
|
@ -49,29 +82,72 @@ qint64 Recorder::elapsed() const {
|
|||
}
|
||||
|
||||
void Recorder::startRecording() {
|
||||
_recording.clear();
|
||||
qDebug() << "Recorder::startRecording()";
|
||||
_recording->clear();
|
||||
_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() {
|
||||
qDebug() << "Recorder::stopRecording()";
|
||||
_timer.invalidate();
|
||||
|
||||
qDebug().nospace() << "Recorded " << _recording->getFrameNumber() << " during " << _recording->getLength() << " msec (" << _recording->getFrameNumber() / (_recording->getLength() / 1000.0f) << " fps)";
|
||||
}
|
||||
|
||||
void Recorder::saveToFile(QString file) {
|
||||
if (_recording.isEmpty()) {
|
||||
if (_recording->isEmpty()) {
|
||||
qDebug() << "Cannot save recording to file, recording is empty.";
|
||||
}
|
||||
|
||||
writeRecordingToFile(_recording, file);
|
||||
writeRecordingToFile(*_recording, file);
|
||||
}
|
||||
|
||||
void Recorder::record() {
|
||||
qDebug() << "Recording " << _avatar;
|
||||
RecordingFrame frame;
|
||||
frame.setBlendshapeCoefficients(_avatar->_)
|
||||
if (isRecording()) {
|
||||
const RecordingFrame& referenceFrame = _recording->getFrame(0);
|
||||
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 {
|
||||
|
@ -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() {
|
||||
_timer.start();
|
||||
if (_recording && _recording->getFrameNumber() > 0) {
|
||||
qDebug() << "Recorder::startPlaying()";
|
||||
_timer.start();
|
||||
_currentFrame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::stopPlaying() {
|
||||
qDebug() << "Recorder::stopPlaying()";
|
||||
_timer.invalidate();
|
||||
}
|
||||
|
||||
void Player::loadFromFile(QString file) {
|
||||
_recording.clear();
|
||||
readRecordingFromFile(_recording, file);
|
||||
if (_recording) {
|
||||
_recording->clear();
|
||||
} else {
|
||||
_recording = RecordingPointer(new Recording());
|
||||
}
|
||||
readRecordingFromFile(*_recording, file);
|
||||
}
|
||||
|
||||
void Player::loadRecording(RecordingPointer recording) {
|
||||
_recording = recording;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
#include <QBitArray>
|
||||
#include <QElapsedTimer>
|
||||
#include <QHash>
|
||||
#include <QSharedPointer>
|
||||
#include <QVector>
|
||||
#include <QWeakPointer>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
@ -23,7 +25,15 @@
|
|||
#include <AvatarData.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
class Recorder;
|
||||
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
|
||||
class RecordingFrame {
|
||||
|
@ -31,20 +41,41 @@ public:
|
|||
QVector<float> getBlendshapeCoefficients() const { return _blendshapeCoefficients; }
|
||||
QVector<glm::quat> getJointRotations() const { return _jointRotations; }
|
||||
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:
|
||||
void setBlendshapeCoefficients(QVector<float> blendshapeCoefficients);
|
||||
void setJointRotations(QVector<glm::quat> jointRotations);
|
||||
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:
|
||||
QVector<float> _blendshapeCoefficients;
|
||||
QVector<glm::quat> _jointRotations;
|
||||
glm::vec3 _translation;
|
||||
glm::quat _rotation;
|
||||
float _scale;
|
||||
glm::quat _headRotation;
|
||||
float _leanSideways;
|
||||
float _leanForward;
|
||||
float _estimatedEyePitch;
|
||||
float _estimatedEyeYaw;
|
||||
|
||||
friend class Recorder;
|
||||
friend void writeRecordingToFile(Recording& recording, QString file);
|
||||
friend Recording* readRecordingFromFile(QString file);
|
||||
friend RecordingPointer readRecordingFromFile(QString file);
|
||||
};
|
||||
|
||||
/// Stores a recording
|
||||
|
@ -52,6 +83,7 @@ class Recording {
|
|||
public:
|
||||
bool isEmpty() const { return _timestamps.isEmpty(); }
|
||||
int getLength() const { return _timestamps.last(); } // in ms
|
||||
int getFrameNumber() const { return _frames.size(); }
|
||||
|
||||
qint32 getFrameTimestamp(int i) const { return _timestamps[i]; }
|
||||
const RecordingFrame& getFrame(int i) const { return _frames[i]; }
|
||||
|
@ -67,7 +99,7 @@ private:
|
|||
friend class Recorder;
|
||||
friend class Player;
|
||||
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;
|
||||
qint64 elapsed() const;
|
||||
|
||||
RecordingPointer getRecording() const { return _recording; }
|
||||
|
||||
public slots:
|
||||
void startRecording();
|
||||
void stopRecording();
|
||||
|
@ -87,7 +121,7 @@ public slots:
|
|||
|
||||
private:
|
||||
QElapsedTimer _timer;
|
||||
Recording _recording;
|
||||
RecordingPointer _recording;
|
||||
|
||||
AvatarData* _avatar;
|
||||
};
|
||||
|
@ -100,15 +134,29 @@ public:
|
|||
bool isPlaying() 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:
|
||||
void startPlaying();
|
||||
void stopPlaying();
|
||||
void loadFromFile(QString file);
|
||||
void loadRecording(RecordingPointer recording);
|
||||
void play();
|
||||
|
||||
private:
|
||||
void computeCurrentFrame();
|
||||
|
||||
QElapsedTimer _timer;
|
||||
Recording _recording;
|
||||
RecordingPointer _recording;
|
||||
int _currentFrame;
|
||||
|
||||
AvatarData* _avatar;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue