Merge pull request #3507 from Atlante45/recording_frames_interpolation

Recording frames interpolation
This commit is contained in:
Andrzej Kapolka 2014-09-29 19:46:11 -07:00
commit 4cdfe87cf1
2 changed files with 73 additions and 11 deletions

View file

@ -19,6 +19,8 @@
Player::Player(AvatarData* avatar) : Player::Player(AvatarData* avatar) :
_recording(new Recording()), _recording(new Recording()),
_currentFrame(-1),
_frameInterpolationFactor(0.0f),
_pausedFrame(-1), _pausedFrame(-1),
_timerOffset(0), _timerOffset(0),
_avatar(avatar), _avatar(avatar),
@ -223,22 +225,65 @@ void Player::play() {
context = &_currentContext; context = &_currentContext;
} }
const RecordingFrame& currentFrame = _recording->getFrame(_currentFrame); const RecordingFrame& currentFrame = _recording->getFrame(_currentFrame);
const RecordingFrame& nextFrame = _recording->getFrame(_currentFrame + 1);
_avatar->setPosition(context->position + context->orientation * currentFrame.getTranslation()); glm::vec3 translation = glm::mix(currentFrame.getTranslation(),
_avatar->setOrientation(context->orientation * currentFrame.getRotation()); nextFrame.getTranslation(),
_avatar->setTargetScale(context->scale * currentFrame.getScale()); _frameInterpolationFactor);
_avatar->setJointRotations(currentFrame.getJointRotations()); _avatar->setPosition(context->position + context->orientation * translation);
glm::quat rotation = safeMix(currentFrame.getRotation(),
nextFrame.getRotation(),
_frameInterpolationFactor);
_avatar->setOrientation(context->orientation * rotation);
float scale = glm::mix(currentFrame.getScale(),
nextFrame.getScale(),
_frameInterpolationFactor);
_avatar->setTargetScale(context->scale * scale);
QVector<glm::quat> jointRotations(currentFrame.getJointRotations().size());
for (int i = 0; i < currentFrame.getJointRotations().size(); ++i) {
jointRotations[i] = safeMix(currentFrame.getJointRotations()[i],
nextFrame.getJointRotations()[i],
_frameInterpolationFactor);
}
_avatar->setJointRotations(jointRotations);
HeadData* head = const_cast<HeadData*>(_avatar->getHeadData()); HeadData* head = const_cast<HeadData*>(_avatar->getHeadData());
if (head) { if (head) {
head->setBlendshapeCoefficients(currentFrame.getBlendshapeCoefficients()); QVector<float> blendCoef(currentFrame.getBlendshapeCoefficients().size());
head->setLeanSideways(currentFrame.getLeanSideways()); for (int i = 0; i < currentFrame.getBlendshapeCoefficients().size(); ++i) {
head->setLeanForward(currentFrame.getLeanForward()); blendCoef[i] = glm::mix(currentFrame.getBlendshapeCoefficients()[i],
glm::vec3 eulers = glm::degrees(safeEulerAngles(currentFrame.getHeadRotation())); nextFrame.getBlendshapeCoefficients()[i],
_frameInterpolationFactor);
}
head->setBlendshapeCoefficients(blendCoef);
float leanSideways = glm::mix(currentFrame.getLeanSideways(),
nextFrame.getLeanSideways(),
_frameInterpolationFactor);
head->setLeanSideways(leanSideways);
float leanForward = glm::mix(currentFrame.getLeanForward(),
nextFrame.getLeanForward(),
_frameInterpolationFactor);
head->setLeanForward(leanForward);
glm::quat headRotation = safeMix(currentFrame.getHeadRotation(),
nextFrame.getHeadRotation(),
_frameInterpolationFactor);
glm::vec3 eulers = glm::degrees(safeEulerAngles(headRotation));
head->setFinalPitch(eulers.x); head->setFinalPitch(eulers.x);
head->setFinalYaw(eulers.y); head->setFinalYaw(eulers.y);
head->setFinalRoll(eulers.z); head->setFinalRoll(eulers.z);
head->setLookAtPosition(context->position + context->orientation * currentFrame.getLookAtPosition());
glm::vec3 lookAt = glm::mix(currentFrame.getLookAtPosition(),
nextFrame.getLookAtPosition(),
_frameInterpolationFactor);
head->setLookAtPosition(context->position + context->orientation * lookAt);
} else { } else {
qDebug() << "WARNING: Player couldn't find head data."; qDebug() << "WARNING: Player couldn't find head data.";
} }
@ -332,10 +377,26 @@ bool Player::computeCurrentFrame() {
_currentFrame = 0; _currentFrame = 0;
} }
while (_currentFrame < _recording->getFrameNumber() - 1 && qint64 elapsed = Player::elapsed();
_recording->getFrameTimestamp(_currentFrame) < elapsed()) { while (_currentFrame < _recording->getFrameNumber() &&
_recording->getFrameTimestamp(_currentFrame) < elapsed) {
++_currentFrame; ++_currentFrame;
} }
--_currentFrame;
if (_currentFrame == _recording->getFrameNumber() - 1) {
--_currentFrame;
_frameInterpolationFactor = 1.0f;
} else {
qint64 currentTimestamps = _recording->getFrameTimestamp(_currentFrame);
qint64 nextTimestamps = _recording->getFrameTimestamp(_currentFrame + 1);
_frameInterpolationFactor = (float)(elapsed - currentTimestamps) /
(float)(nextTimestamps - currentTimestamps);
}
if (_frameInterpolationFactor < 0.0f || _frameInterpolationFactor > 1.0f) {
_frameInterpolationFactor = 0.0f;
qDebug() << "Invalid frame interpolation value: overriding";
}
return true; return true;
} }

View file

@ -64,6 +64,7 @@ private:
QElapsedTimer _timer; QElapsedTimer _timer;
RecordingPointer _recording; RecordingPointer _recording;
int _currentFrame; int _currentFrame;
float _frameInterpolationFactor;
int _pausedFrame; int _pausedFrame;
qint64 _timerOffset; qint64 _timerOffset;