From 9abfb0f503d25550c2d15e5f0d1e8dfacb7c53d2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 8 Aug 2014 14:25:55 -0700 Subject: [PATCH 01/14] Added Recorder suite --- interface/src/Recorder.cpp | 12 ++++++ interface/src/Recorder.h | 85 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 interface/src/Recorder.cpp create mode 100644 interface/src/Recorder.h diff --git a/interface/src/Recorder.cpp b/interface/src/Recorder.cpp new file mode 100644 index 0000000000..49ef833309 --- /dev/null +++ b/interface/src/Recorder.cpp @@ -0,0 +1,12 @@ +// +// Recorder.cpp +// +// +// Created by Clement on 8/7/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Recorder.h" diff --git a/interface/src/Recorder.h b/interface/src/Recorder.h new file mode 100644 index 0000000000..ffb013723c --- /dev/null +++ b/interface/src/Recorder.h @@ -0,0 +1,85 @@ +// +// Recorder.h +// +// +// Created by Clement on 8/7/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_Recorder_h +#define hifi_Recorder_h + +#include +#include +#include +#include + +#include + +/// Stores the different values associated to one recording frame +class RecordingFrame { +public: + QVector getBlendshapeCoefficients() const { return _blendshapeCoefficients; } + QVector getJointRotations() const { return _jointRotations; } + glm::vec3 getTranslation() const { return _translation; } + +private: + + QVector _blendshapeCoefficients; + QVector _jointRotations; + glm::vec3 _translation; +}; + +/// Stores a recording +class Recording { +public: + bool isEmpty() const { return _timestamps.isEmpty(); } + int getLength() const { return _timestamps.last(); } // in ms + + qint32 getFrameTimestamp(int i) const { return _timestamps[i]; } + const RecordingFrame& getFrame(int i) const { return _frames[i]; } + +protected: + void addFrame(int timestamp, RecordingFrame& frame); + void clear(); + +private: + QVector _timestamps; + QVector _frames; + + friend class Recorder; + friend void writeRecordingToFile(Recording& recording, QString file); + friend Recording& readRecordingFromFile(QString file); +}; + + +/// Records a recording +class Recorder { +public: + Recorder(); + + bool isRecording() const; + qint64 elapsed() const; + +public slots: + void startRecording(); + void stopRecording(); + void saveToFile(QString file); + +private: + QElapsedTimer _timer; + Recording _recording; +}; + +/// Plays back a recording +class Player { +public: + +private: + Recording _recording; +}; + +#endif // hifi_Recorder_h \ No newline at end of file From 5b4a3bd5f5eaed8bbfcb3a31a2c18ac8848799c5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 8 Aug 2014 14:26:16 -0700 Subject: [PATCH 02/14] Recording ground work --- interface/src/Recorder.cpp | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/interface/src/Recorder.cpp b/interface/src/Recorder.cpp index 49ef833309..85e2535141 100644 --- a/interface/src/Recorder.cpp +++ b/interface/src/Recorder.cpp @@ -10,3 +10,52 @@ // #include "Recorder.h" + +void Recording::addFrame(int timestamp, RecordingFrame &frame) { + _timestamps << timestamp; + _frames << frame; +} + +void Recording::clear() { + _timestamps.clear(); + _frames.clear(); +} + +void writeRecordingToFile(Recording& recording, QString file) { + qDebug() << "Writing recording to " << file; +} + +Recording& readRecordingFromFile(QString file) { + qDebug() << "Reading recording from " << file; + return *(new Recording()); +} + + +bool Recorder::isRecording() const { + return _timer.isValid(); +} + +qint64 Recorder::elapsed() const { + if (isRecording()) { + return _timer.elapsed(); + } else { + return 0; + } +} + +void Recorder::startRecording() { + _recording.clear(); + _timer.start(); +} + +void Recorder::stopRecording() { + _timer.invalidate(); +} + +void Recorder::saveToFile(QString file) { + if (_recording.isEmpty()) { + qDebug() << "Cannot save recording to file, recording is empty."; + } + + writeRecordingToFile(_recording, file); +} \ No newline at end of file From 96ee9e3f750fa0326956616c1c5239782f2a0823 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 11 Aug 2014 13:54:36 -0700 Subject: [PATCH 03/14] Work on Recording structure --- interface/src/Recorder.cpp | 70 +++++++++++++++++++++++++++++++++----- interface/src/Recorder.h | 40 ++++++++++++++++++++-- 2 files changed, 99 insertions(+), 11 deletions(-) diff --git a/interface/src/Recorder.cpp b/interface/src/Recorder.cpp index 85e2535141..87352fed98 100644 --- a/interface/src/Recorder.cpp +++ b/interface/src/Recorder.cpp @@ -11,6 +11,18 @@ #include "Recorder.h" +void RecordingFrame::setBlendshapeCoefficients(QVector blendshapeCoefficients) { + _blendshapeCoefficients = blendshapeCoefficients; +} + +void RecordingFrame::setJointRotations(QVector jointRotations) { + _jointRotations = jointRotations; +} + +void RecordingFrame::setTranslation(glm::vec3 translation) { + _translation = translation; +} + void Recording::addFrame(int timestamp, RecordingFrame &frame) { _timestamps << timestamp; _frames << frame; @@ -21,16 +33,9 @@ void Recording::clear() { _frames.clear(); } -void writeRecordingToFile(Recording& recording, QString file) { - qDebug() << "Writing recording to " << file; +Recorder::Recorder(AvatarData* avatar) : _avatar(avatar) { } -Recording& readRecordingFromFile(QString file) { - qDebug() << "Reading recording from " << file; - return *(new Recording()); -} - - bool Recorder::isRecording() const { return _timer.isValid(); } @@ -58,4 +63,53 @@ void Recorder::saveToFile(QString file) { } writeRecordingToFile(_recording, file); +} + +void Recorder::record() { + qDebug() << "Recording " << _avatar; + RecordingFrame frame; + frame.setBlendshapeCoefficients(_avatar->_) +} + +Player::Player(AvatarData* avatar) : _avatar(avatar) { +} + +bool Player::isPlaying() const { + return _timer.isValid(); +} + +qint64 Player::elapsed() const { + if (isPlaying()) { + return _timer.elapsed(); + } else { + return 0; + } +} + +void Player::startPlaying() { + _timer.start(); +} + +void Player::stopPlaying() { + _timer.invalidate(); +} + +void Player::loadFromFile(QString file) { + _recording.clear(); + readRecordingFromFile(_recording, file); +} + +void Player::play() { + qDebug() << "Playing " << _avatar; +} + +void writeRecordingToFile(Recording& recording, QString file) { + // TODO + qDebug() << "Writing recording to " << file; +} + +Recording& readRecordingFromFile(Recording& recording, QString file) { + // TODO + qDebug() << "Reading recording from " << file; + return recording; } \ No newline at end of file diff --git a/interface/src/Recorder.h b/interface/src/Recorder.h index ffb013723c..2d32e4a9b0 100644 --- a/interface/src/Recorder.h +++ b/interface/src/Recorder.h @@ -17,8 +17,14 @@ #include #include +#include +#include + +#include #include +class Recording; + /// Stores the different values associated to one recording frame class RecordingFrame { public: @@ -26,11 +32,19 @@ public: QVector getJointRotations() const { return _jointRotations; } glm::vec3 getTranslation() const { return _translation; } -private: +protected: + void setBlendshapeCoefficients(QVector blendshapeCoefficients); + void setJointRotations(QVector jointRotations); + void setTranslation(glm::vec3 translation); +private: QVector _blendshapeCoefficients; QVector _jointRotations; glm::vec3 _translation; + + friend class Recorder; + friend void writeRecordingToFile(Recording& recording, QString file); + friend Recording* readRecordingFromFile(QString file); }; /// Stores a recording @@ -51,15 +65,16 @@ private: QVector _frames; friend class Recorder; + friend class Player; friend void writeRecordingToFile(Recording& recording, QString file); - friend Recording& readRecordingFromFile(QString file); + friend Recording* readRecordingFromFile(QString file); }; /// Records a recording class Recorder { public: - Recorder(); + Recorder(AvatarData* avatar); bool isRecording() const; qint64 elapsed() const; @@ -68,18 +83,37 @@ public slots: void startRecording(); void stopRecording(); void saveToFile(QString file); + void record(); private: QElapsedTimer _timer; Recording _recording; + + AvatarData* _avatar; }; /// Plays back a recording class Player { public: + Player(AvatarData* avatar); + + bool isPlaying() const; + qint64 elapsed() const; + +public slots: + void startPlaying(); + void stopPlaying(); + void loadFromFile(QString file); + void play(); private: + QElapsedTimer _timer; Recording _recording; + + AvatarData* _avatar; }; +void writeRecordingToFile(Recording& recording, QString file); +Recording& readRecordingFromFile(Recording& recording, QString file); + #endif // hifi_Recorder_h \ No newline at end of file From 18ff49744368e23cb743137cf282d2123a61880b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 12 Aug 2014 16:11:53 -0700 Subject: [PATCH 04/14] Added all relevant curves to RecordingFrames --- interface/src/Recorder.cpp | 208 ++++++++++++++++++++++++++++++++++--- interface/src/Recorder.h | 56 +++++++++- 2 files changed, 248 insertions(+), 16 deletions(-) diff --git a/interface/src/Recorder.cpp b/interface/src/Recorder.cpp index 87352fed98..c15e17597e 100644 --- a/interface/src/Recorder.cpp +++ b/interface/src/Recorder.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "Recorder.h" void RecordingFrame::setBlendshapeCoefficients(QVector 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 Player::getBlendshapeCoefficients() { + computeCurrentFrame(); + return _recording->getFrame(_currentFrame).getBlendshapeCoefficients(); +} + +QVector 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(_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(_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) { diff --git a/interface/src/Recorder.h b/interface/src/Recorder.h index 2d32e4a9b0..798e3f5ba8 100644 --- a/interface/src/Recorder.h +++ b/interface/src/Recorder.h @@ -15,7 +15,9 @@ #include #include #include +#include #include +#include #include #include @@ -23,7 +25,15 @@ #include #include +class Recorder; class Recording; +class Player; + +typedef QSharedPointer RecordingPointer; +typedef QSharedPointer RecorderPointer; +typedef QWeakPointer WeakRecorderPointer; +typedef QSharedPointer PlayerPointer; +typedef QWeakPointer WeakPlayerPointer; /// Stores the different values associated to one recording frame class RecordingFrame { @@ -31,20 +41,41 @@ public: QVector getBlendshapeCoefficients() const { return _blendshapeCoefficients; } QVector 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 blendshapeCoefficients); void setJointRotations(QVector 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 _blendshapeCoefficients; QVector _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 getBlendshapeCoefficients(); + QVector 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; }; From ff0a5df2d6848e2f819f6d967ca5efa26b4511fc Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 12 Aug 2014 16:12:34 -0700 Subject: [PATCH 05/14] Joint rotations manipulation helper --- libraries/avatars/src/AvatarData.cpp | 15 +++++++++++++++ libraries/avatars/src/AvatarData.h | 2 ++ libraries/avatars/src/HeadData.h | 1 + 3 files changed, 18 insertions(+) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 039ccae4e9..fad07bedfc 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -683,6 +683,21 @@ glm::quat AvatarData::getJointRotation(const QString& name) const { return getJointRotation(getJointIndex(name)); } +QVector AvatarData::getJointRotations() const { + if (QThread::currentThread() != thread()) { + QVector result; + QMetaObject::invokeMethod(const_cast(this), + "getJointRotation", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QVector, result)); + return result; + } + QVector jointRotations(_jointData.size()); + for (int i = 0; i < _jointData.size(); ++i) { + jointRotations[i] = _jointData[i].rotation; + } + return jointRotations; +} + bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index a4bb0d48bb..eb3341ee26 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -210,6 +210,8 @@ public: Q_INVOKABLE void clearJointData(const QString& name); Q_INVOKABLE bool isJointDataValid(const QString& name) const; Q_INVOKABLE glm::quat getJointRotation(const QString& name) const; + + QVector getJointRotations() const; /// Returns the index of the joint with the specified name, or -1 if not found/unknown. Q_INVOKABLE virtual int getJointIndex(const QString& name) const { return _jointIndices.value(name) - 1; } diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index 782386c649..b6a3268ec0 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -56,6 +56,7 @@ public: void setBlendshape(QString name, float val); const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } + void setBlendshapeCoefficients(const QVector& blendshapeCoefficients) { _blendshapeCoefficients = blendshapeCoefficients; } float getPupilDilation() const { return _pupilDilation; } void setPupilDilation(float pupilDilation) { _pupilDilation = pupilDilation; } From 792f779bbff7600682bceb7907da2fcadf4862d6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 12 Aug 2014 16:16:01 -0700 Subject: [PATCH 06/14] Hooked up MyAvatar to playbacks --- interface/src/avatar/Avatar.cpp | 13 +++++++ interface/src/avatar/Avatar.h | 7 +++- interface/src/avatar/Head.cpp | 19 ++++++---- interface/src/avatar/MyAvatar.cpp | 62 +++++++++++++++++++++++++++++-- interface/src/avatar/MyAvatar.h | 9 +++++ 5 files changed, 97 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index c9e03d15cc..498281c98c 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -29,6 +29,7 @@ #include "Menu.h" #include "ModelReferential.h" #include "Physics.h" +#include "Recorder.h" #include "world.h" #include "devices/OculusManager.h" #include "renderer/TextureCache.h" @@ -63,6 +64,7 @@ Avatar::Avatar() : _mouseRayDirection(0.0f, 0.0f, 0.0f), _moving(false), _collisionGroups(0), + _player(NULL), _initialized(false), _shouldRenderBillboard(true) { @@ -725,6 +727,17 @@ bool Avatar::findCollisions(const QVector& shapes, CollisionList& return collided; } +QVector Avatar::getJointRotations() const { + if (QThread::currentThread() != thread()) { + return AvatarData::getJointRotations(); + } + QVector jointRotations(_skeletonModel.getJointStateCount()); + for (int i = 0; i < _skeletonModel.getJointStateCount(); ++i) { + _skeletonModel.getJointState(i, jointRotations[i]); + } + return jointRotations; +} + glm::quat Avatar::getJointRotation(int index) const { if (QThread::currentThread() != thread()) { return AvatarData::getJointRotation(index); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 555a0f6d32..35dec3b8d0 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -23,6 +23,7 @@ #include "Hand.h" #include "Head.h" #include "InterfaceConfig.h" +#include "Recorder.h" #include "SkeletonModel.h" #include "world.h" @@ -121,6 +122,7 @@ public: virtual bool isMyAvatar() { return false; } + virtual QVector getJointRotations() const; virtual glm::quat getJointRotation(int index) const; virtual int getJointIndex(const QString& name) const; virtual QStringList getJointNames() const; @@ -186,6 +188,9 @@ protected: bool _moving; ///< set when position is changing quint32 _collisionGroups; + + RecorderPointer _recorder; + PlayerPointer _player; // protected methods... glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } @@ -220,8 +225,6 @@ private: void renderBillboard(); float getBillboardSize() const; - - }; #endif // hifi_Avatar_h diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 995f3f2390..d547dc41c2 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -64,13 +64,18 @@ void Head::reset() { void Head::simulate(float deltaTime, bool isMine, bool billboard) { // Update audio trailing average for rendering facial animations if (isMine) { - FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); - if ((_isFaceshiftConnected = faceTracker)) { - _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); - _isFaceshiftConnected = true; - } else if (Application::getInstance()->getDDE()->isActive()) { - faceTracker = Application::getInstance()->getDDE(); - _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); + MyAvatar* myAvatar = static_cast(_owningAvatar); + + // Only use face trackers when not playing back a recording. + if (!myAvatar->isPlaying()) { + FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); + if ((_isFaceshiftConnected = faceTracker)) { + _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); + _isFaceshiftConnected = true; + } else if (Application::getInstance()->getDDE()->isActive()) { + faceTracker = Application::getInstance()->getDDE(); + _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); + } } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f59064732c..353c240507 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -35,6 +35,7 @@ #include "ModelReferential.h" #include "MyAvatar.h" #include "Physics.h" +#include "Recorder.h" #include "devices/Faceshift.h" #include "devices/OculusManager.h" #include "ui/TextRenderer.h" @@ -135,6 +136,12 @@ void MyAvatar::update(float deltaTime) { void MyAvatar::simulate(float deltaTime) { PerformanceTimer perfTimer("simulate"); + + // Play back recording + if (_player && _player->isPlaying()) { + _player->play(); + } + if (_scale != _targetScale) { float scale = (1.0f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale; setScale(scale); @@ -147,7 +154,7 @@ void MyAvatar::simulate(float deltaTime) { updateOrientation(deltaTime); updatePosition(deltaTime); } - + { PerformanceTimer perfTimer("hand"); // update avatar skeleton and simulate hand and head @@ -242,6 +249,11 @@ void MyAvatar::simulate(float deltaTime) { } } + // Record avatars movements. + if (_recorder && _recorder->isRecording()) { + _recorder->record(); + } + // consider updating our billboard maybeUpdateBillboard(); } @@ -250,7 +262,10 @@ void MyAvatar::simulate(float deltaTime) { void MyAvatar::updateFromTrackers(float deltaTime) { glm::vec3 estimatedPosition, estimatedRotation; - if (Application::getInstance()->getPrioVR()->hasHeadRotation()) { + if (isPlaying()) { + //estimatedPosition = _player->getHeadTranslation(); + estimatedRotation = glm::degrees(safeEulerAngles(_player->getHeadRotation())); + } else if (Application::getInstance()->getPrioVR()->hasHeadRotation()) { estimatedRotation = glm::degrees(safeEulerAngles(Application::getInstance()->getPrioVR()->getHeadRotation())); estimatedRotation.x *= -1.0f; estimatedRotation.z *= -1.0f; @@ -286,7 +301,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { Head* head = getHead(); - if (OculusManager::isConnected()) { + if (OculusManager::isConnected() || isPlaying()) { head->setDeltaPitch(estimatedRotation.x); head->setDeltaYaw(estimatedRotation.y); } else { @@ -297,7 +312,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { head->setDeltaRoll(estimatedRotation.z); // the priovr can give us exact lean - if (Application::getInstance()->getPrioVR()->isActive()) { + if (Application::getInstance()->getPrioVR()->isActive() && !isPlaying()) { glm::vec3 eulers = glm::degrees(safeEulerAngles(Application::getInstance()->getPrioVR()->getTorsoRotation())); head->setLeanSideways(eulers.z); head->setLeanForward(eulers.x); @@ -474,6 +489,45 @@ bool MyAvatar::setJointReferential(int id, int jointIndex) { } } +bool MyAvatar::isRecording() const { + return _recorder && _recorder->isRecording(); +} + +RecorderPointer MyAvatar::startRecording() { + if (!_recorder) { + _recorder = RecorderPointer(new Recorder(this)); + } + _recorder->startRecording(); + return _recorder; +} + +void MyAvatar::stopRecording() { + if (_recorder) { + _recorder->stopRecording(); + } +} + +bool MyAvatar::isPlaying() const { + return _player && _player->isPlaying(); +} + +PlayerPointer MyAvatar::startPlaying() { + if (!_player) { + _player = PlayerPointer(new Player(this)); + } + if (_recorder) { + _player->loadRecording(_recorder->getRecording()); + _player->startPlaying(); + } + return _player; +} + +void MyAvatar::stopPlaying() { + if (_player) { + _player->stopPlaying(); + } +} + void MyAvatar::setLocalGravity(glm::vec3 gravity) { _motionBehaviors |= AVATAR_MOTION_OBEY_LOCAL_GRAVITY; // Environmental and Local gravities are incompatible. Since Local is being set here diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 4f2802a35a..cd211a3530 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -155,6 +155,15 @@ public slots: bool setModelReferential(int id); bool setJointReferential(int id, int jointIndex); + bool isRecording() const; + RecorderPointer startRecording(); + void stopRecording(); + + bool isPlaying() const; + PlayerPointer startPlaying(); + void stopPlaying(); + + signals: void transformChanged(); From 73a3a13c59769a1cfb5520914fa578e5beb14ad9 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 12 Aug 2014 18:15:48 -0700 Subject: [PATCH 07/14] More recording work --- interface/src/Application.cpp | 13 ++- interface/src/Recorder.cpp | 123 +++++++++++++++++++------ interface/src/Recorder.h | 12 +-- interface/src/avatar/Avatar.cpp | 1 + interface/src/avatar/Head.h | 5 - interface/src/avatar/MyAvatar.cpp | 17 +++- interface/src/avatar/MyAvatar.h | 3 + interface/src/avatar/SkeletonModel.cpp | 8 +- libraries/avatars/src/AvatarData.cpp | 14 +++ libraries/avatars/src/AvatarData.h | 3 +- libraries/avatars/src/HeadData.h | 9 ++ 11 files changed, 158 insertions(+), 50 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6f7212e68f..198a3f9a8b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1048,10 +1048,19 @@ void Application::keyPressEvent(QKeyEvent* event) { break; case Qt::Key_R: if (isShifted) { - Menu::getInstance()->triggerOption(MenuOption::FrustumRenderMode); + if (_myAvatar->isRecording()) { + _myAvatar->stopRecording(); + } else { + _myAvatar->startRecording(); + } + } else { + if (_myAvatar->isPlaying()) { + _myAvatar->stopPlaying(); + } else { + _myAvatar->startPlaying(); + } } break; - break; case Qt::Key_Percent: Menu::getInstance()->triggerOption(MenuOption::Stats); break; diff --git a/interface/src/Recorder.cpp b/interface/src/Recorder.cpp index c15e17597e..de29a887fb 100644 --- a/interface/src/Recorder.cpp +++ b/interface/src/Recorder.cpp @@ -45,14 +45,6 @@ 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; @@ -93,15 +85,13 @@ void Recorder::startRecording() { 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(); + frame.setLeanForward(_avatar->getHeadData()->getLeanForward()); + frame.setLeanSideways(_avatar->getHeadData()->getLeanSideways()); _recording->addFrame(0, frame); } @@ -130,16 +120,16 @@ void Recorder::record() { 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(); + frame.setHeadRotation(rotation); + frame.setLeanForward(_avatar->getHeadData()->getLeanForward()); + frame.setLeanSideways(_avatar->getHeadData()->getLeanSideways()); + _recording->addFrame(_timer.elapsed(), frame); } } @@ -164,22 +154,82 @@ qint64 Player::elapsed() const { QVector Player::getBlendshapeCoefficients() { computeCurrentFrame(); - return _recording->getFrame(_currentFrame).getBlendshapeCoefficients(); + if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { + if (_currentFrame == _recording->getFrameNumber()) { + return _recording->getFrame(_currentFrame - 1).getBlendshapeCoefficients(); + } + + return _recording->getFrame(_currentFrame).getBlendshapeCoefficients(); + } + qWarning() << "Incorrect use of Player::getBlendshapeCoefficients()"; + return QVector(); } QVector Player::getJointRotations() { computeCurrentFrame(); - return _recording->getFrame(_currentFrame).getJointRotations(); + if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { + if (_currentFrame == _recording->getFrameNumber()) { + return _recording->getFrame(_currentFrame - 1).getJointRotations(); + } + + return _recording->getFrame(_currentFrame).getJointRotations(); + } + qWarning() << "Incorrect use of Player::getJointRotations()"; + return QVector(); +} + +glm::vec3 Player::getPosition() { + computeCurrentFrame(); + if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { + if (_currentFrame == _recording->getFrameNumber()) { + return _recording->getFrame(0).getTranslation() + + _recording->getFrame(_currentFrame - 1).getTranslation(); + } + if (_currentFrame == 0) { + return _recording->getFrame(_currentFrame).getTranslation(); + } + + return _recording->getFrame(0).getTranslation() + + _recording->getFrame(_currentFrame).getTranslation(); + } + qWarning() << "Incorrect use of Player::getTranslation()"; + return glm::vec3(); } glm::quat Player::getRotation() { computeCurrentFrame(); - return _recording->getFrame(_currentFrame).getRotation(); + if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { + if (_currentFrame == _recording->getFrameNumber()) { + return _recording->getFrame(0).getRotation() * + _recording->getFrame(_currentFrame - 1).getRotation(); + } + if (_currentFrame == 0) { + return _recording->getFrame(_currentFrame).getRotation(); + } + + return _recording->getFrame(0).getRotation() * + _recording->getFrame(_currentFrame).getRotation(); + } + qWarning() << "Incorrect use of Player::getRotation()"; + return glm::quat(); } float Player::getScale() { computeCurrentFrame(); - return _recording->getFrame(_currentFrame).getScale(); + if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { + if (_currentFrame == _recording->getFrameNumber()) { + return _recording->getFrame(0).getScale() * + _recording->getFrame(_currentFrame - 1).getScale(); + } + if (_currentFrame == 0) { + return _recording->getFrame(_currentFrame).getScale(); + } + + return _recording->getFrame(0).getScale() * + _recording->getFrame(_currentFrame).getScale(); + } + qWarning() << "Incorrect use of Player::getScale()"; + return 1.0f; } glm::quat Player::getHeadRotation() { @@ -200,14 +250,30 @@ glm::quat Player::getHeadRotation() { return glm::quat(); } -float Player::getEstimatedEyePitch() { +float Player::getLeanSideways() { computeCurrentFrame(); - return _recording->getFrame(_currentFrame).getEstimatedEyePitch(); + if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { + if (_currentFrame == _recording->getFrameNumber()) { + return _recording->getFrame(_currentFrame - 1).getLeanSideways(); + } + + return _recording->getFrame(_currentFrame).getLeanSideways(); + } + qWarning() << "Incorrect use of Player::getLeanSideways()"; + return 0.0f; } -float Player::getEstimatedEyeYaw() { +float Player::getLeanForward() { computeCurrentFrame(); - return _recording->getFrame(_currentFrame).getEstimatedEyeYaw(); + if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { + if (_currentFrame == _recording->getFrameNumber()) { + return _recording->getFrame(_currentFrame - 1).getLeanForward(); + } + + return _recording->getFrame(_currentFrame).getLeanForward(); + } + qWarning() << "Incorrect use of Player::getLeanForward()"; + return 0.0f; } @@ -249,10 +315,10 @@ void Player::play() { _avatar->setPosition(_recording->getFrame(_currentFrame).getTranslation()); _avatar->setOrientation(_recording->getFrame(_currentFrame).getRotation()); _avatar->setTargetScale(_recording->getFrame(_currentFrame).getScale()); + _avatar->setJointRotations(_recording->getFrame(_currentFrame).getJointRotations()); HeadData* head = const_cast(_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() + @@ -261,10 +327,10 @@ void Player::play() { _recording->getFrame(_currentFrame).getRotation()); _avatar->setTargetScale(_recording->getFrame(0).getScale() * _recording->getFrame(_currentFrame).getScale()); + _avatar->setJointRotations(_recording->getFrame(_currentFrame).getJointRotations()); HeadData* head = const_cast(_avatar->getHeadData()); head->setBlendshapeCoefficients(_recording->getFrame(_currentFrame).getBlendshapeCoefficients()); // TODO - // HEAD: Coeff, Translation, estimated eye rotations // BODY: Joint Rotations } } @@ -282,7 +348,6 @@ void Player::computeCurrentFrame() { while (_currentFrame < _recording->getFrameNumber() && _recording->getFrameTimestamp(_currentFrame) < _timer.elapsed()) { - qDebug() << "Loop"; ++_currentFrame; } } diff --git a/interface/src/Recorder.h b/interface/src/Recorder.h index 798e3f5ba8..f2a6f6a1c4 100644 --- a/interface/src/Recorder.h +++ b/interface/src/Recorder.h @@ -46,8 +46,6 @@ public: 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 blendshapeCoefficients); @@ -58,8 +56,6 @@ protected: void setHeadRotation(glm::quat headRotation); void setLeanSideways(float leanSideways); void setLeanForward(float leanForward); - void setEstimatedEyePitch(float estimatedEyePitch); - void setEstimatedEyeYaw(float estimatedEyeYaw); private: QVector _blendshapeCoefficients; @@ -70,8 +66,6 @@ private: glm::quat _headRotation; float _leanSideways; float _leanForward; - float _estimatedEyePitch; - float _estimatedEyeYaw; friend class Recorder; friend void writeRecordingToFile(Recording& recording, QString file); @@ -137,12 +131,12 @@ public: // Those should only be called if isPlaying() returns true QVector getBlendshapeCoefficients(); QVector getJointRotations(); + glm::vec3 getPosition(); glm::quat getRotation(); float getScale(); - glm::vec3 getHeadTranslation(); glm::quat getHeadRotation(); - float getEstimatedEyePitch(); - float getEstimatedEyeYaw(); + float getLeanSideways(); + float getLeanForward(); public slots: void startPlaying(); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 498281c98c..d50e9232ed 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -735,6 +735,7 @@ QVector Avatar::getJointRotations() const { for (int i = 0; i < _skeletonModel.getJointStateCount(); ++i) { _skeletonModel.getJointState(i, jointRotations[i]); } + qDebug() << "Get Joints"; return jointRotations; } diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 6d1e82b97f..1bcaadec73 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -48,8 +48,6 @@ public: void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; } void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; } void setRenderLookatVectors(bool onOff) { _renderLookatVectors = onOff; } - void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; } - void setLeanForward(float leanForward) { _leanForward = leanForward; } /// \return orientationBase+Delta glm::quat getFinalOrientationInLocalFrame() const; @@ -57,7 +55,6 @@ public: /// \return orientationBody * (orientationBase+Delta) glm::quat getFinalOrientationInWorldFrame() const; - /// \return orientationBody * orientationBasePitch glm::quat getCameraOrientation () const; @@ -71,8 +68,6 @@ public: glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } glm::vec3 getUpDirection() const { return getOrientation() * IDENTITY_UP; } glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; } - float getLeanSideways() const { return _leanSideways; } - float getLeanForward() const { return _leanForward; } float getFinalLeanSideways() const { return _leanSideways + _deltaLeanSideways; } float getFinalLeanForward() const { return _leanForward + _deltaLeanForward; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 353c240507..1133ac01c3 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -263,7 +263,6 @@ void MyAvatar::updateFromTrackers(float deltaTime) { glm::vec3 estimatedPosition, estimatedRotation; if (isPlaying()) { - //estimatedPosition = _player->getHeadTranslation(); estimatedRotation = glm::degrees(safeEulerAngles(_player->getHeadRotation())); } else if (Application::getInstance()->getPrioVR()->hasHeadRotation()) { estimatedRotation = glm::degrees(safeEulerAngles(Application::getInstance()->getPrioVR()->getHeadRotation())); @@ -311,14 +310,18 @@ void MyAvatar::updateFromTrackers(float deltaTime) { } head->setDeltaRoll(estimatedRotation.z); + if (isPlaying()) { + head->setLeanSideways(_player->getLeanSideways()); + head->setLeanForward(_player->getLeanForward()); + return; + } // the priovr can give us exact lean - if (Application::getInstance()->getPrioVR()->isActive() && !isPlaying()) { + if (Application::getInstance()->getPrioVR()->isActive()) { glm::vec3 eulers = glm::degrees(safeEulerAngles(Application::getInstance()->getPrioVR()->getTorsoRotation())); head->setLeanSideways(eulers.z); head->setLeanForward(eulers.x); return; } - // Update torso lean distance based on accelerometer data const float TORSO_LENGTH = 0.5f; glm::vec3 relativePosition = estimatedPosition - glm::vec3(0.0f, -TORSO_LENGTH, 0.0f); @@ -910,6 +913,14 @@ glm::vec3 MyAvatar::getUprightHeadPosition() const { const float JOINT_PRIORITY = 2.0f; +void MyAvatar::setJointRotations(QVector jointRotations) { + for (int i = 0; i < jointRotations.size(); ++i) { + if (i < _jointData.size()) { + _skeletonModel.setJointState(i, true, jointRotations[i]); + } + } +} + void MyAvatar::setJointData(int index, const glm::quat& rotation) { Avatar::setJointData(index, rotation); if (QThread::currentThread() == thread()) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index cd211a3530..bf57bf2367 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -112,6 +112,7 @@ public: void updateLookAtTargetAvatar(); void clearLookAtTargetAvatar(); + virtual void setJointRotations(QVector jointRotations); virtual void setJointData(int index, const glm::quat& rotation); virtual void clearJointData(int index); virtual void setFaceModelURL(const QUrl& faceModelURL); @@ -155,10 +156,12 @@ public slots: bool setModelReferential(int id); bool setJointReferential(int id, int jointIndex); + const RecorderPointer getRecorder() const { return _recorder; } bool isRecording() const; RecorderPointer startRecording(); void stopRecording(); + const PlayerPointer getPlayer() const { return _player; } bool isPlaying() const; PlayerPointer startPlaying(); void stopPlaying(); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 5e593526be..f4a507a8d3 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -59,9 +59,15 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { Model::simulate(deltaTime, fullUpdate); - if (!(isActive() && _owningAvatar->isMyAvatar())) { + if (!isActive() || !_owningAvatar->isMyAvatar()) { return; // only simulate for own avatar } + + MyAvatar* myAvatar = static_cast(_owningAvatar); + if (myAvatar->isPlaying()) { + // Don't take inputs if playing back a recording. + return; + } const FBXGeometry& geometry = _geometry->getFBXGeometry(); PrioVR* prioVR = Application::getInstance()->getPrioVR(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index fad07bedfc..569e099c2c 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -698,6 +698,20 @@ QVector AvatarData::getJointRotations() const { return jointRotations; } +void AvatarData::setJointRotations(QVector jointRotations) { + if (QThread::currentThread() != thread()) { + QVector result; + QMetaObject::invokeMethod(const_cast(this), + "setJointRotation", Qt::BlockingQueuedConnection, + Q_ARG(QVector, jointRotations)); + } + for (int i = 0; i < jointRotations.size(); ++i) { + if (i < _jointData.size()) { + setJointData(i, jointRotations[i]); + } + } +} + bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index eb3341ee26..7dec55b7e9 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -211,7 +211,8 @@ public: Q_INVOKABLE bool isJointDataValid(const QString& name) const; Q_INVOKABLE glm::quat getJointRotation(const QString& name) const; - QVector getJointRotations() const; + Q_INVOKABLE virtual QVector getJointRotations() const; + Q_INVOKABLE virtual void setJointRotations(QVector jointRotations); /// Returns the index of the joint with the specified name, or -1 if not found/unknown. Q_INVOKABLE virtual int getJointIndex(const QString& name) const { return _jointIndices.value(name) - 1; } diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index b6a3268ec0..310437689c 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -69,6 +69,15 @@ public: const glm::vec3& getLookAtPosition() const { return _lookAtPosition; } void setLookAtPosition(const glm::vec3& lookAtPosition) { _lookAtPosition = lookAtPosition; } + + float getLeanSideways() const { return _leanSideways; } + float getLeanForward() const { return _leanForward; } + virtual float getFinalLeanSideways() const { return _leanSideways; } + virtual float getFinalLeanForward() const { return _leanForward; } + + void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; } + void setLeanForward(float leanForward) { _leanForward = leanForward; } + friend class AvatarData; protected: From db5aeddc0f67dc2c93587fbe5a8979877b333383 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 14 Aug 2014 10:58:00 -0700 Subject: [PATCH 08/14] fix for joints not playing back --- interface/src/avatar/MyAvatar.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1133ac01c3..9e302c45fe 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -916,7 +916,8 @@ const float JOINT_PRIORITY = 2.0f; void MyAvatar::setJointRotations(QVector jointRotations) { for (int i = 0; i < jointRotations.size(); ++i) { if (i < _jointData.size()) { - _skeletonModel.setJointState(i, true, jointRotations[i]); + // TODO change animation priority to proper value + _skeletonModel.setJointState(i, true, jointRotations[i], 100.0f); } } } From cd0f2164197dfa9e8b358d4a966e3f6f84d0527f Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 14 Aug 2014 11:39:36 -0700 Subject: [PATCH 09/14] Added Recorder and Player to Audio class --- interface/src/Audio.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 8fae6f3bdd..de87291b55 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -17,6 +17,7 @@ #include "InterfaceConfig.h" #include "AudioStreamStats.h" +#include "Recorder.h" #include "RingBufferHistory.h" #include "MovingMinMaxAvg.h" @@ -101,6 +102,9 @@ public: float getAudioOutputMsecsUnplayed() const; float getAudioOutputAverageMsecsUnplayed() const { return (float)_audioOutputMsecsUnplayedStats.getWindowAverage(); } + + void setRecorder(RecorderPointer recorder) { _recorder = recorder; } + void setPlayer(PlayerPointer player) { _player = player; } public slots: void start(); @@ -297,6 +301,9 @@ private: MovingMinMaxAvg _packetSentTimeGaps; AudioOutputIODevice _audioOutputIODevice; + + WeakRecorderPointer _recorder; + WeakPlayerPointer _player; }; From 2eb1321cc2f1d207ed3b6cc812212516c45955a4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 18 Aug 2014 12:28:44 -0700 Subject: [PATCH 10/14] Sound and AudioInjector tweaks --- libraries/audio/src/AudioInjectorOptions.h | 4 ++-- libraries/audio/src/Sound.cpp | 11 +++++++++++ libraries/audio/src/Sound.h | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/libraries/audio/src/AudioInjectorOptions.h b/libraries/audio/src/AudioInjectorOptions.h index b90deb93f1..35575414d5 100644 --- a/libraries/audio/src/AudioInjectorOptions.h +++ b/libraries/audio/src/AudioInjectorOptions.h @@ -37,8 +37,8 @@ public: float getVolume() const { return _volume; } void setVolume(float volume) { _volume = volume; } - float getLoop() const { return _loop; } - void setLoop(float loop) { _loop = loop; } + bool getLoop() const { return _loop; } + void setLoop(bool loop) { _loop = loop; } const glm::quat& getOrientation() const { return _orientation; } void setOrientation(const glm::quat& orientation) { _orientation = orientation; } diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index 03c9f6b8ee..f52f5c04dd 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -82,6 +82,17 @@ Sound::Sound(const QUrl& sampleURL, QObject* parent) : connect(soundDownload, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(replyError(QNetworkReply::NetworkError))); } +Sound::Sound(const QByteArray byteArray, QObject* parent) : + QObject(parent), + _byteArray(byteArray), + _hasDownloaded(true) +{ +} + +void Sound::append(const QByteArray byteArray) { + _byteArray.append(byteArray); +} + void Sound::replyFinished() { QNetworkReply* reply = reinterpret_cast(sender()); diff --git a/libraries/audio/src/Sound.h b/libraries/audio/src/Sound.h index c473cdff83..7dae3679f1 100644 --- a/libraries/audio/src/Sound.h +++ b/libraries/audio/src/Sound.h @@ -22,6 +22,8 @@ class Sound : public QObject { public: Sound(const QUrl& sampleURL, QObject* parent = NULL); Sound(float volume, float frequency, float duration, float decay, QObject* parent = NULL); + Sound(const QByteArray byteArray, QObject* parent = NULL); + void append(const QByteArray byteArray); bool hasDownloaded() const { return _hasDownloaded; } From acb55ce65e3054864354551ba4955801afc8e366 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 18 Aug 2014 12:31:44 -0700 Subject: [PATCH 11/14] Switched audio play back to AudioInjector out of Audio --- interface/src/Application.cpp | 2 ++ interface/src/Audio.cpp | 9 +++-- interface/src/Recorder.cpp | 58 +++++++++++++++++++++++++++++---- interface/src/Recorder.h | 19 +++++++++-- interface/src/avatar/Avatar.cpp | 1 - 5 files changed, 77 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dba8174083..2fef2ced8a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1051,12 +1051,14 @@ void Application::keyPressEvent(QKeyEvent* event) { _myAvatar->stopRecording(); } else { _myAvatar->startRecording(); + _audio.setRecorder(_myAvatar->getRecorder()); } } else { if (_myAvatar->isPlaying()) { _myAvatar->stopPlaying(); } else { _myAvatar->startPlaying(); + _audio.setPlayer(_myAvatar->getPlayer()); } } break; diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 0484860c65..bb8b79ab59 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -82,7 +82,6 @@ Audio::Audio(QObject* parent) : _noiseGateSampleCounter(0), _noiseGateOpen(false), _noiseGateEnabled(true), - _peqEnabled(false), _toneInjectionEnabled(false), _noiseGateFramesToClose(0), _totalInputAudioSamples(0), @@ -102,6 +101,7 @@ Audio::Audio(QObject* parent) : _scopeOutputOffset(0), _framesPerScope(DEFAULT_FRAMES_PER_SCOPE), _samplesPerScope(NETWORK_SAMPLES_PER_FRAME * _framesPerScope), + _peqEnabled(false), _scopeInput(0), _scopeOutputLeft(0), _scopeOutputRight(0), @@ -475,7 +475,7 @@ void Audio::handleAudioInput() { int16_t* ioBuffer = (int16_t*)inputByteArray.data(); - _peq.render( ioBuffer, ioBuffer, inputByteArray.size() / sizeof(int16_t) ); + _peq.render(ioBuffer, ioBuffer, inputByteArray.size() / sizeof(int16_t)); } if (Menu::getInstance()->isOptionChecked(MenuOption::EchoLocalAudio) && !_muted && _audioOutput) { @@ -676,6 +676,11 @@ void Audio::handleAudioInput() { NodeList* nodeList = NodeList::getInstance(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); + + if (_recorder && _recorder.data()->isRecording()) { + _recorder.data()->record(reinterpret_cast(networkAudioSamples), numNetworkBytes); + } + if (audioMixer && audioMixer->getActiveSocket()) { MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar(); glm::vec3 headPosition = interfaceAvatar->getHead()->getPosition(); diff --git a/interface/src/Recorder.cpp b/interface/src/Recorder.cpp index de29a887fb..b0698b95cb 100644 --- a/interface/src/Recorder.cpp +++ b/interface/src/Recorder.cpp @@ -45,14 +45,30 @@ void RecordingFrame::setLeanForward(float leanForward) { _leanForward = leanForward; } +Recording::Recording() : _audio(NULL) { +} + +Recording::~Recording() { + delete _audio; +} + void Recording::addFrame(int timestamp, RecordingFrame &frame) { _timestamps << timestamp; _frames << frame; } +void Recording::addAudioPacket(QByteArray byteArray) { + if (!_audio) { + _audio = new Sound(byteArray); + } + _audio->append(byteArray); +} + void Recording::clear() { _timestamps.clear(); _frames.clear(); + delete _audio; + _audio = NULL; } Recorder::Recorder(AvatarData* avatar) : @@ -134,10 +150,19 @@ void Recorder::record() { } } +void Recorder::record(char* samples, int size) { + QByteArray byteArray(samples, size); + _recording->addAudioPacket(byteArray); +} + + Player::Player(AvatarData* avatar) : _recording(new Recording()), - _avatar(avatar) + _avatar(avatar), + _audioThread(NULL) { + _options.setLoop(false); + _options.setVolume(1.0f); } bool Player::isPlaying() const { @@ -276,18 +301,29 @@ float Player::getLeanForward() { return 0.0f; } - +#include void Player::startPlaying() { if (_recording && _recording->getFrameNumber() > 0) { qDebug() << "Recorder::startPlaying()"; - _timer.start(); _currentFrame = 0; + _options.setPosition(_avatar->getPosition()); + _options.setOrientation(_avatar->getOrientation()); + _injector.reset(new AudioInjector(_recording->getAudio(), _options)); + _audioThread = new QThread(); + _injector->moveToThread(_audioThread); + _audioThread->start(); + QMetaObject::invokeMethod(_injector.data(), "injectAudio", Qt::QueuedConnection); + _timer.start(); } } void Player::stopPlaying() { qDebug() << "Recorder::stopPlaying()"; _timer.invalidate(); + _injector->stop(); + _injector.clear(); + _audioThread->exit(); + _audioThread->deleteLater(); } void Player::loadFromFile(QString file) { @@ -311,6 +347,7 @@ void Player::play() { stopPlaying(); return; } + if (_currentFrame == 0) { _avatar->setPosition(_recording->getFrame(_currentFrame).getTranslation()); _avatar->setOrientation(_recording->getFrame(_currentFrame).getRotation()); @@ -318,8 +355,6 @@ void Player::play() { _avatar->setJointRotations(_recording->getFrame(_currentFrame).getJointRotations()); HeadData* head = const_cast(_avatar->getHeadData()); head->setBlendshapeCoefficients(_recording->getFrame(_currentFrame).getBlendshapeCoefficients()); - // TODO - // BODY: Joint Rotations } else { _avatar->setPosition(_recording->getFrame(0).getTranslation() + _recording->getFrame(_currentFrame).getTranslation()); @@ -330,11 +365,20 @@ void Player::play() { _avatar->setJointRotations(_recording->getFrame(_currentFrame).getJointRotations()); HeadData* head = const_cast(_avatar->getHeadData()); head->setBlendshapeCoefficients(_recording->getFrame(_currentFrame).getBlendshapeCoefficients()); - // TODO - // BODY: Joint Rotations } } +void Player::playAudio() { + _options.setPosition(_avatar->getPosition()); + _options.setOrientation(_avatar->getOrientation()); + + qDebug() << "Play"; + if (_injector) { + _injector->injectAudio(); + } + qDebug() << "Played"; +} + void Player::computeCurrentFrame() { if (!isPlaying()) { qDebug() << "Not Playing"; diff --git a/interface/src/Recorder.h b/interface/src/Recorder.h index f2a6f6a1c4..9a412aadbf 100644 --- a/interface/src/Recorder.h +++ b/interface/src/Recorder.h @@ -22,8 +22,10 @@ #include #include +#include #include #include +#include class Recorder; class Recording; @@ -75,28 +77,34 @@ private: /// Stores a recording class Recording { public: + Recording(); + ~Recording(); + 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]; } + Sound* getAudio() const { return _audio; } protected: void addFrame(int timestamp, RecordingFrame& frame); + void addAudioPacket(QByteArray byteArray); void clear(); private: QVector _timestamps; QVector _frames; + Sound* _audio; + friend class Recorder; friend class Player; friend void writeRecordingToFile(Recording& recording, QString file); friend RecordingPointer readRecordingFromFile(QString file); }; - /// Records a recording class Recorder { public: @@ -112,6 +120,7 @@ public slots: void stopRecording(); void saveToFile(QString file); void record(); + void record(char* samples, int size); private: QElapsedTimer _timer; @@ -138,12 +147,14 @@ public: float getLeanSideways(); float getLeanForward(); + public slots: void startPlaying(); void stopPlaying(); void loadFromFile(QString file); void loadRecording(RecordingPointer recording); void play(); + void playAudio(); private: void computeCurrentFrame(); @@ -152,7 +163,11 @@ private: RecordingPointer _recording; int _currentFrame; + QSharedPointer _injector; + AudioInjectorOptions _options; + AvatarData* _avatar; + QThread* _audioThread; }; void writeRecordingToFile(Recording& recording, QString file); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index d50e9232ed..498281c98c 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -735,7 +735,6 @@ QVector Avatar::getJointRotations() const { for (int i = 0; i < _skeletonModel.getJointStateCount(); ++i) { _skeletonModel.getJointState(i, jointRotations[i]); } - qDebug() << "Get Joints"; return jointRotations; } From 52640c8482351a0629fc9ba08ab85537d5fa0f34 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 18 Aug 2014 14:23:29 -0700 Subject: [PATCH 12/14] Various tweaks and code cleanup --- interface/src/Application.cpp | 2 ++ interface/src/Recorder.cpp | 29 ++++++++++++++-------------- interface/src/Recorder.h | 13 ++++++------- interface/src/avatar/MyAvatar.cpp | 12 ++++++++++-- interface/src/avatar/MyAvatar.h | 1 + interface/src/renderer/Model.cpp | 8 ++++++++ interface/src/renderer/Model.h | 3 +++ libraries/avatars/src/AvatarData.cpp | 6 ++++++ libraries/avatars/src/AvatarData.h | 4 +++- 9 files changed, 53 insertions(+), 25 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2fef2ced8a..5a689180e5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1047,6 +1047,8 @@ void Application::keyPressEvent(QKeyEvent* event) { break; case Qt::Key_R: if (isShifted) { + Menu::getInstance()->triggerOption(MenuOption::FrustumRenderMode); + } else if (isMeta) { if (_myAvatar->isRecording()) { _myAvatar->stopRecording(); } else { diff --git a/interface/src/Recorder.cpp b/interface/src/Recorder.cpp index b0698b95cb..a2101b28b8 100644 --- a/interface/src/Recorder.cpp +++ b/interface/src/Recorder.cpp @@ -75,6 +75,7 @@ Recorder::Recorder(AvatarData* avatar) : _recording(new Recording()), _avatar(avatar) { + _timer.invalidate(); } bool Recorder::isRecording() const { @@ -124,7 +125,7 @@ void Recorder::saveToFile(QString file) { qDebug() << "Cannot save recording to file, recording is empty."; } - writeRecordingToFile(*_recording, file); + writeRecordingToFile(_recording, file); } void Recorder::record() { @@ -161,6 +162,7 @@ Player::Player(AvatarData* avatar) : _avatar(avatar), _audioThread(NULL) { + _timer.invalidate(); _options.setLoop(false); _options.setVolume(1.0f); } @@ -318,8 +320,16 @@ void Player::startPlaying() { } void Player::stopPlaying() { + if (!isPlaying()) { + return; + } + qDebug() << "Recorder::stopPlaying()"; _timer.invalidate(); + + _avatar->clearJointsData(); + + // Cleanup audio thread _injector->stop(); _injector.clear(); _audioThread->exit(); @@ -332,7 +342,7 @@ void Player::loadFromFile(QString file) { } else { _recording = RecordingPointer(new Recording()); } - readRecordingFromFile(*_recording, file); + readRecordingFromFile(_recording, file); } void Player::loadRecording(RecordingPointer recording) { @@ -368,17 +378,6 @@ void Player::play() { } } -void Player::playAudio() { - _options.setPosition(_avatar->getPosition()); - _options.setOrientation(_avatar->getOrientation()); - - qDebug() << "Play"; - if (_injector) { - _injector->injectAudio(); - } - qDebug() << "Played"; -} - void Player::computeCurrentFrame() { if (!isPlaying()) { qDebug() << "Not Playing"; @@ -396,12 +395,12 @@ void Player::computeCurrentFrame() { } } -void writeRecordingToFile(Recording& recording, QString file) { +void writeRecordingToFile(RecordingPointer recording, QString file) { // TODO qDebug() << "Writing recording to " << file; } -Recording& readRecordingFromFile(Recording& recording, QString file) { +RecordingPointer readRecordingFromFile(RecordingPointer recording, QString file) { // TODO qDebug() << "Reading recording from " << file; return recording; diff --git a/interface/src/Recorder.h b/interface/src/Recorder.h index 9a412aadbf..e1a1119449 100644 --- a/interface/src/Recorder.h +++ b/interface/src/Recorder.h @@ -70,8 +70,8 @@ private: float _leanForward; friend class Recorder; - friend void writeRecordingToFile(Recording& recording, QString file); - friend RecordingPointer readRecordingFromFile(QString file); + friend void writeRecordingToFile(RecordingPointer recording, QString file); + friend RecordingPointer readRecordingFromFile(RecordingPointer recording, QString file); }; /// Stores a recording @@ -101,8 +101,8 @@ private: friend class Recorder; friend class Player; - friend void writeRecordingToFile(Recording& recording, QString file); - friend RecordingPointer readRecordingFromFile(QString file); + friend void writeRecordingToFile(RecordingPointer recording, QString file); + friend RecordingPointer readRecordingFromFile(RecordingPointer recording, QString file); }; /// Records a recording @@ -154,7 +154,6 @@ public slots: void loadFromFile(QString file); void loadRecording(RecordingPointer recording); void play(); - void playAudio(); private: void computeCurrentFrame(); @@ -170,7 +169,7 @@ private: QThread* _audioThread; }; -void writeRecordingToFile(Recording& recording, QString file); -Recording& readRecordingFromFile(Recording& recording, QString file); +void writeRecordingToFile(RecordingPointer recording, QString file); +RecordingPointer readRecordingFromFile(RecordingPointer recording, QString file); #endif // hifi_Recorder_h \ No newline at end of file diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9ff60dd610..5ed2e3c011 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -922,8 +922,7 @@ const float JOINT_PRIORITY = 2.0f; void MyAvatar::setJointRotations(QVector jointRotations) { for (int i = 0; i < jointRotations.size(); ++i) { if (i < _jointData.size()) { - // TODO change animation priority to proper value - _skeletonModel.setJointState(i, true, jointRotations[i], 100.0f); + _skeletonModel.setJointState(i, true, jointRotations[i], JOINT_PRIORITY + 1.0f); } } } @@ -942,6 +941,15 @@ void MyAvatar::clearJointData(int index) { } } +void MyAvatar::clearJointsData() { + for (int i = 0; i < _jointData.size(); ++i) { + Avatar::clearJointData(i); + if (QThread::currentThread() == thread()) { + _skeletonModel.clearJointState(i); + } + } +} + void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) { Avatar::setFaceModelURL(faceModelURL); _billboardValid = false; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index bf57bf2367..67d19b87eb 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -115,6 +115,7 @@ public: virtual void setJointRotations(QVector jointRotations); virtual void setJointData(int index, const glm::quat& rotation); virtual void clearJointData(int index); + virtual void clearJointsData(); virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); virtual void setAttachmentData(const QVector& attachmentData); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 2ec676de53..290f9b5c6f 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -692,6 +692,14 @@ bool Model::getVisibleJointState(int index, glm::quat& rotation) const { return !state.rotationIsDefault(rotation); } +void Model::clearJointState(int index) { + if (index != -1 && index < _jointStates.size()) { + JointState& state = _jointStates[index]; + state.setRotationInConstrainedFrame(glm::quat()); + state._animationPriority = 0.0f; + } +} + void Model::setJointState(int index, bool valid, const glm::quat& rotation, float priority) { if (index != -1 && index < _jointStates.size()) { JointState& state = _jointStates[index]; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 7a29b61420..e45b8091d3 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -118,6 +118,9 @@ public: /// \return whether or not the joint state is "valid" (that is, non-default) bool getVisibleJointState(int index, glm::quat& rotation) const; + /// Clear the joint states + void clearJointState(int index); + /// Sets the joint state at the specified index. void setJointState(int index, bool valid, const glm::quat& rotation = glm::quat(), float priority = 1.0f); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 569e099c2c..9653999555 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -712,6 +712,12 @@ void AvatarData::setJointRotations(QVector jointRotations) { } } +void AvatarData::clearJointsData() { + for (int i = 0; i < _jointData.size(); ++i) { + clearJointData(i); + } +} + bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 7dec55b7e9..fa884c0229 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -213,7 +213,9 @@ public: Q_INVOKABLE virtual QVector getJointRotations() const; Q_INVOKABLE virtual void setJointRotations(QVector jointRotations); - + + Q_INVOKABLE virtual void clearJointsData(); + /// Returns the index of the joint with the specified name, or -1 if not found/unknown. Q_INVOKABLE virtual int getJointIndex(const QString& name) const { return _jointIndices.value(name) - 1; } From 698699dea8cf608564f7919ee62e6a2a4a6f3838 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 18 Aug 2014 15:56:27 -0700 Subject: [PATCH 13/14] CR --- interface/src/Recorder.cpp | 143 +++++++------------------------------ interface/src/Recorder.h | 7 +- 2 files changed, 26 insertions(+), 124 deletions(-) diff --git a/interface/src/Recorder.cpp b/interface/src/Recorder.cpp index a2101b28b8..b782112778 100644 --- a/interface/src/Recorder.cpp +++ b/interface/src/Recorder.cpp @@ -11,6 +11,8 @@ #include +#include + #include "Recorder.h" void RecordingFrame::setBlendshapeCoefficients(QVector blendshapeCoefficients) { @@ -179,131 +181,37 @@ qint64 Player::elapsed() const { } } -QVector Player::getBlendshapeCoefficients() { - computeCurrentFrame(); - if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { - if (_currentFrame == _recording->getFrameNumber()) { - return _recording->getFrame(_currentFrame - 1).getBlendshapeCoefficients(); - } - - return _recording->getFrame(_currentFrame).getBlendshapeCoefficients(); - } - qWarning() << "Incorrect use of Player::getBlendshapeCoefficients()"; - return QVector(); -} - -QVector Player::getJointRotations() { - computeCurrentFrame(); - if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { - if (_currentFrame == _recording->getFrameNumber()) { - return _recording->getFrame(_currentFrame - 1).getJointRotations(); - } - - return _recording->getFrame(_currentFrame).getJointRotations(); - } - qWarning() << "Incorrect use of Player::getJointRotations()"; - return QVector(); -} - -glm::vec3 Player::getPosition() { - computeCurrentFrame(); - if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { - if (_currentFrame == _recording->getFrameNumber()) { - return _recording->getFrame(0).getTranslation() + - _recording->getFrame(_currentFrame - 1).getTranslation(); - } - if (_currentFrame == 0) { - return _recording->getFrame(_currentFrame).getTranslation(); - } - - return _recording->getFrame(0).getTranslation() + - _recording->getFrame(_currentFrame).getTranslation(); - } - qWarning() << "Incorrect use of Player::getTranslation()"; - return glm::vec3(); -} - -glm::quat Player::getRotation() { - computeCurrentFrame(); - if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { - if (_currentFrame == _recording->getFrameNumber()) { - return _recording->getFrame(0).getRotation() * - _recording->getFrame(_currentFrame - 1).getRotation(); - } - if (_currentFrame == 0) { - return _recording->getFrame(_currentFrame).getRotation(); - } - - return _recording->getFrame(0).getRotation() * - _recording->getFrame(_currentFrame).getRotation(); - } - qWarning() << "Incorrect use of Player::getRotation()"; - return glm::quat(); -} - -float Player::getScale() { - computeCurrentFrame(); - if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { - if (_currentFrame == _recording->getFrameNumber()) { - return _recording->getFrame(0).getScale() * - _recording->getFrame(_currentFrame - 1).getScale(); - } - if (_currentFrame == 0) { - return _recording->getFrame(_currentFrame).getScale(); - } - - return _recording->getFrame(0).getScale() * - _recording->getFrame(_currentFrame).getScale(); - } - qWarning() << "Incorrect use of Player::getScale()"; - return 1.0f; -} - 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(); + if (computeCurrentFrame()) { + qWarning() << "Incorrect use of Player::getHeadRotation()"; + return glm::quat(); } - qWarning() << "Incorrect use of Player::getHeadRotation()"; - return glm::quat(); + + if (_currentFrame == 0) { + return _recording->getFrame(_currentFrame).getHeadRotation(); + } + return _recording->getFrame(0).getHeadRotation() * + _recording->getFrame(_currentFrame).getHeadRotation(); } float Player::getLeanSideways() { - computeCurrentFrame(); - if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { - if (_currentFrame == _recording->getFrameNumber()) { - return _recording->getFrame(_currentFrame - 1).getLeanSideways(); - } - - return _recording->getFrame(_currentFrame).getLeanSideways(); + if (computeCurrentFrame()) { + qWarning() << "Incorrect use of Player::getLeanSideways()"; + return 0.0f; } - qWarning() << "Incorrect use of Player::getLeanSideways()"; - return 0.0f; + + return _recording->getFrame(_currentFrame).getLeanSideways(); } float Player::getLeanForward() { - computeCurrentFrame(); - if (_currentFrame >= 0 && _currentFrame <= _recording->getFrameNumber()) { - if (_currentFrame == _recording->getFrameNumber()) { - return _recording->getFrame(_currentFrame - 1).getLeanForward(); - } - - return _recording->getFrame(_currentFrame).getLeanForward(); + if (computeCurrentFrame()) { + qWarning() << "Incorrect use of Player::getLeanForward()"; + return 0.0f; } - qWarning() << "Incorrect use of Player::getLeanForward()"; - return 0.0f; + + return _recording->getFrame(_currentFrame).getLeanForward(); } -#include void Player::startPlaying() { if (_recording && _recording->getFrameNumber() > 0) { qDebug() << "Recorder::startPlaying()"; @@ -350,7 +258,6 @@ void Player::loadRecording(RecordingPointer recording) { } void Player::play() { - qDebug() << "Playing " << _timer.elapsed() / 1000.0f; computeCurrentFrame(); if (_currentFrame < 0 || _currentFrame >= _recording->getFrameNumber()) { // If it's the end of the recording, stop playing @@ -378,14 +285,12 @@ void Player::play() { } } -void Player::computeCurrentFrame() { +bool Player::computeCurrentFrame() { if (!isPlaying()) { - qDebug() << "Not Playing"; _currentFrame = -1; - return; + return false; } if (_currentFrame < 0) { - qDebug() << "Reset to 0"; _currentFrame = 0; } @@ -393,6 +298,8 @@ void Player::computeCurrentFrame() { _recording->getFrameTimestamp(_currentFrame) < _timer.elapsed()) { ++_currentFrame; } + + return true; } void writeRecordingToFile(RecordingPointer recording, QString file) { diff --git a/interface/src/Recorder.h b/interface/src/Recorder.h index e1a1119449..9f7eb66ec6 100644 --- a/interface/src/Recorder.h +++ b/interface/src/Recorder.h @@ -138,11 +138,6 @@ public: qint64 elapsed() const; // Those should only be called if isPlaying() returns true - QVector getBlendshapeCoefficients(); - QVector getJointRotations(); - glm::vec3 getPosition(); - glm::quat getRotation(); - float getScale(); glm::quat getHeadRotation(); float getLeanSideways(); float getLeanForward(); @@ -156,7 +151,7 @@ public slots: void play(); private: - void computeCurrentFrame(); + bool computeCurrentFrame(); QElapsedTimer _timer; RecordingPointer _recording; From c113dd350eabb6f2c18911d660d70355a8437dcf Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 18 Aug 2014 16:25:38 -0700 Subject: [PATCH 14/14] Moved members to MyAvatar --- interface/src/avatar/Avatar.cpp | 1 - interface/src/avatar/Avatar.h | 3 --- interface/src/avatar/MyAvatar.h | 3 +++ 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 498281c98c..41912afd09 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -64,7 +64,6 @@ Avatar::Avatar() : _mouseRayDirection(0.0f, 0.0f, 0.0f), _moving(false), _collisionGroups(0), - _player(NULL), _initialized(false), _shouldRenderBillboard(true) { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 35dec3b8d0..c8ecb23913 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -188,9 +188,6 @@ protected: bool _moving; ///< set when position is changing quint32 _collisionGroups; - - RecorderPointer _recorder; - PlayerPointer _player; // protected methods... glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 67d19b87eb..2c1695a499 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -205,6 +205,9 @@ private: QList _animationHandles; PhysicsSimulation _physicsSimulation; + RecorderPointer _recorder; + PlayerPointer _player; + // private methods float computeDistanceToFloor(const glm::vec3& startPoint); void updateOrientation(float deltaTime);