From cad8425c7bf07206f97d5190e36043e1b0ae92ca Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 19 Sep 2018 16:43:45 -0700 Subject: [PATCH] Time-based frames, max distance and setting animation from script --- interface/src/avatar/AvatarManager.cpp | 62 ++++++++++-- interface/src/avatar/AvatarManager.h | 3 + .../src/avatars-renderer/Avatar.cpp | 98 +++++++++---------- .../src/avatars-renderer/Avatar.h | 30 +++--- 4 files changed, 118 insertions(+), 75 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index edf9469670..4cc3c619b4 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -91,9 +91,11 @@ AvatarManager::AvatarManager(QObject* parent) : _transitConfig._triggerDistance = AVATAR_TRANSIT_TRIGGER_DISTANCE; _transitConfig._framesPerMeter = AVATAR_TRANSIT_FRAMES_PER_METER; _transitConfig._isDistanceBased = true; - _transitConfig._startTransitAnimation = AvatarTransit::TransitAnimation(START_ANIMATION_URL, 30, 0, 10); - _transitConfig._middleTransitAnimation = AvatarTransit::TransitAnimation(MIDDLE_ANIMATION_URL, 30, 11, 0); - _transitConfig._endTransitAnimation = AvatarTransit::TransitAnimation(END_ANIMATION_URL, 30, 12, 38); + + _transitConfig._startTransitAnimation = AvatarTransit::TransitAnimation(START_ANIMATION_URL, 0, 14); + _transitConfig._middleTransitAnimation = AvatarTransit::TransitAnimation(MIDDLE_ANIMATION_URL, 15, 0); + _transitConfig._endTransitAnimation = AvatarTransit::TransitAnimation(END_ANIMATION_URL, 16, 38); + } AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer) { @@ -145,28 +147,39 @@ void AvatarManager::playTransitAnimations(AvatarTransit::Status status) { auto startAnimation = _transitConfig._startTransitAnimation; auto middleAnimation = _transitConfig._middleTransitAnimation; auto endAnimation = _transitConfig._endTransitAnimation; + + const float REFERENCE_FPS = 30.0f; switch (status) { case AvatarTransit::Status::START_FRAME: - _myAvatar->overrideAnimation(startAnimation._animationUrl, startAnimation._fps, false, startAnimation._firstFrame, startAnimation._firstFrame + startAnimation._frameCount); + qDebug() << "START_FRAME"; + _myAvatar->overrideAnimation(startAnimation._animationUrl, REFERENCE_FPS, false, startAnimation._firstFrame, startAnimation._firstFrame + startAnimation._frameCount); break; case AvatarTransit::Status::START_TRANSIT: - _myAvatar->overrideAnimation(middleAnimation._animationUrl, middleAnimation._fps, false, middleAnimation._firstFrame, middleAnimation._firstFrame + middleAnimation._frameCount); + qDebug() << "START_TRANSIT"; + _myAvatar->overrideAnimation(middleAnimation._animationUrl, REFERENCE_FPS, false, middleAnimation._firstFrame, middleAnimation._firstFrame + middleAnimation._frameCount); break; case AvatarTransit::Status::END_TRANSIT: - _myAvatar->overrideAnimation(endAnimation._animationUrl, endAnimation._fps, false, endAnimation._firstFrame, endAnimation._firstFrame + endAnimation._frameCount); + qDebug() << "END_TRANSIT"; + _myAvatar->overrideAnimation(endAnimation._animationUrl, REFERENCE_FPS, false, endAnimation._firstFrame, endAnimation._firstFrame + endAnimation._frameCount); break; case AvatarTransit::Status::END_FRAME: + qDebug() << "END_FRAME"; _myAvatar->restoreAnimation(); break; + case AvatarTransit::Status::IDLE: + break; + case AvatarTransit::Status::TRANSITING: + break; } + } void AvatarManager::updateMyAvatar(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()"); - AvatarTransit::Status status = _myAvatar->updateTransit(_myAvatar->getWorldPosition(), _transitConfig); + AvatarTransit::Status status = _myAvatar->updateTransit(deltaTime, _myAvatar->getWorldPosition(), _transitConfig); if (_transitConfig._playAnimation) { playTransitAnimations(status); @@ -295,7 +308,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { } // smooth other avatars positions { - avatar->_transit.update(avatar->_globalPosition, _transitConfig); + avatar->_transit.update(deltaTime, avatar->_globalPosition, _transitConfig); } avatar->simulate(deltaTime, inView); @@ -911,4 +924,37 @@ void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptV if (data.contains("playAnimation")) { _transitConfig._playAnimation = data["playAnimation"].toBool(); } +} + + AvatarTransit::TransitAnimation AvatarManager::getAnimationFromJsonObject(const QJsonObject& object) { + QString animationUrl; + int firstFrame = 0; + int frameCount = 0; + if (object.contains("animationUrl")) { + animationUrl = object["animationUrl"].toString(); + } + if (object.contains("firstFrame")) { + firstFrame = object["firstFrame"].toInt(); + } + if (object.contains("frameCount")) { + frameCount = object["frameCount"].toInt(); + } + return AvatarTransit::TransitAnimation(animationUrl, firstFrame, frameCount); + } + + void AvatarManager::setAvatarTransitAnimationData(const QVariantMap& data) { + AvatarTransit::TransitAnimation startAnimation, middleAnimation, endAnimation; + + if (data.contains("startAnimation")) { + QJsonObject object = data["startAnimation"].toJsonObject(); + _transitConfig._startTransitAnimation = getAnimationFromJsonObject(object); + } + if (data.contains("middleAnimation")) { + QJsonObject object = data["middleAnimation"].toJsonObject(); + _transitConfig._middleTransitAnimation = getAnimationFromJsonObject(object); + } + if (data.contains("endAnimation")) { + QJsonObject object = data["endAnimation"].toJsonObject(); + _transitConfig._endTransitAnimation = getAnimationFromJsonObject(object); + } } \ No newline at end of file diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index e5936154a4..d0fcb13c01 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -180,6 +180,7 @@ public: Q_INVOKABLE QVariantMap getAvatarTransitData(); Q_INVOKABLE void setAvatarTransitData(const QVariantMap& data); + Q_INVOKABLE void setAvatarTransitAnimationData(const QVariantMap& data); float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); } int getIdentityRequestsSent() const { return _identityRequestsSent; } @@ -208,6 +209,8 @@ private: void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override; void playTransitAnimations(AvatarTransit::Status status); + AvatarTransit::TransitAnimation getAnimationFromJsonObject(const QJsonObject& object); + QVector _avatarsToFade; QVector _avatarsToCopy; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index a3c3286793..5098364540 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -113,70 +113,63 @@ void Avatar::setShowNamesAboveHeads(bool show) { showNamesAboveHeads = show; } -AvatarTransit::Status AvatarTransit::update(const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config) { +AvatarTransit::Status AvatarTransit::update(float deltaTime, const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config) { glm::vec3 currentPosition = _isTransiting ? _currentPosition : avatarPosition; float oneFrameDistance = glm::length(currentPosition - _lastPosition); - if (oneFrameDistance > config._triggerDistance && !_isTransiting) { - start(_lastPosition, currentPosition, config); + const float MAX_TRANSIT_DISTANCE = 20.0f; + if (oneFrameDistance > config._triggerDistance && oneFrameDistance < MAX_TRANSIT_DISTANCE && !_isTransiting) { + start(deltaTime, _lastPosition, currentPosition, config); } - return updatePosition(avatarPosition); + _lastPosition = currentPosition; + return updatePosition(deltaTime); } -void AvatarTransit::start(const glm::vec3& startPosition, const glm::vec3& endPosition, const AvatarTransit::TransitConfig& config) { +void AvatarTransit::start(float deltaTime, const glm::vec3& startPosition, const glm::vec3& endPosition, const AvatarTransit::TransitConfig& config) { _startPosition = startPosition; _endPosition = endPosition; - _framesBefore = config._startTransitAnimation._frameCount; - _framesAfter = config._endTransitAnimation._frameCount; - _step = 0; - if (!config._isDistanceBased) { - calculateSteps(config._totalFrames); - } else { - float distance = glm::length(_endPosition - _startPosition); - calculateSteps(config._framesPerMeter * distance); - } + + _transitLine = endPosition - startPosition; + _totalDistance = glm::length(_transitLine); + const float REFERENCE_FRAMES_PER_SECOND = 30.0f; + + int framesBefore = config._playAnimation ? config._startTransitAnimation._frameCount : 0; + int framesAfter = config._playAnimation ? config._endTransitAnimation._frameCount : 0; + _timeBefore = (float)framesBefore / REFERENCE_FRAMES_PER_SECOND; + _timeAfter = (float)framesAfter / REFERENCE_FRAMES_PER_SECOND; + + int transitFrames = (!config._isDistanceBased) ? config._totalFrames : config._framesPerMeter * _totalDistance; + _transitTime = (float)transitFrames / REFERENCE_FRAMES_PER_SECOND; + _totalTime = _transitTime + _timeBefore + _timeAfter; + _currentTime = 0.0f; _isTransiting = true; } -void AvatarTransit::calculateSteps(int stepCount) { - glm::vec3 startPosition = _isTransiting ? _transitSteps[_step] : _startPosition; - _transitSteps.clear(); - glm::vec3 transitLine = _endPosition - startPosition; - glm::vec3 direction = glm::normalize(transitLine); - glm::vec3 stepVector = (glm::length(transitLine) / stepCount) * direction; - int totalSteps = stepCount + _framesBefore + _framesAfter; - for (auto i = 0; i < totalSteps; i++) { - if (i < _framesBefore) { - _transitSteps.push_back(_startPosition); - } else if (i >= stepCount + _framesBefore) { - _transitSteps.push_back(_endPosition); - } else { - glm::vec3 localStep = _transitSteps.size() > _framesBefore ? _transitSteps[i - 1] + stepVector : _startPosition + stepVector; - _transitSteps.push_back(localStep); - } - } -} - -AvatarTransit::Status AvatarTransit::updatePosition(const glm::vec3& avatarPosition) { +AvatarTransit::Status AvatarTransit::updatePosition(float deltaTime) { Status status = Status::IDLE; - _lastPosition = _isTransiting ? _currentPosition : avatarPosition; if (_isTransiting) { - int lastIdx = (int)_transitSteps.size() - 1; - _isTransiting = _step < lastIdx; - if (_isTransiting) { - if (_step == 0) { + float nextTime = _currentTime + deltaTime; + glm::vec3 newPosition; + if (nextTime < _timeBefore) { + _currentPosition = _startPosition; + if (_currentTime == 0) { status = Status::START_FRAME; - qDebug() << "Transit starting"; - } else if (_step == _framesBefore - 1) { - status = Status::START_TRANSIT; - } else if (_step == (int)_transitSteps.size() - _framesAfter) { - status = Status::END_TRANSIT; } - _step++; - _currentPosition = _transitSteps[_step]; + } else if (nextTime >= _totalTime - _timeAfter) { + if (_currentTime < _totalTime - _timeAfter) { + status = Status::END_TRANSIT; + } else if (nextTime >= _totalTime) { + status = Status::END_FRAME; + _isTransiting = false; + } + _currentPosition = _endPosition; } else { - status = Status::END_FRAME; - qDebug() << "Transit ending"; - } + if (_currentTime <= _timeBefore) { + status = Status::START_TRANSIT; + } + float percentageIntoTransit = (nextTime - _timeBefore) / _transitTime; + _currentPosition = _startPosition + percentageIntoTransit * _transitLine; + } + _currentTime = nextTime; } return status; } @@ -521,7 +514,6 @@ void Avatar::simulate(float deltaTime, bool inView) { if (_transit.isTransiting()) { glm::vec3 nextPosition; if (_transit.getNextPosition(nextPosition)) { - // setWorldPosition(nextPosition); _globalPosition = nextPosition; _globalPositionChanged = usecTimestampNow(); if (!hasParent()) { @@ -540,7 +532,7 @@ void Avatar::simulate(float deltaTime, bool inView) { PROFILE_RANGE(simulation, "updateJoints"); if (inView) { Head* head = getHead(); - if (true) { + if (_hasNewJointData || _transit.isTransiting()) { _skeletonModel->getRig().copyJointsFromJointData(_jointData); glm::mat4 rootTransform = glm::scale(_skeletonModel->getScale()) * glm::translate(_skeletonModel->getOffset()); _skeletonModel->getRig().computeExternalPoses(rootTransform); @@ -1954,9 +1946,9 @@ float Avatar::getUnscaledEyeHeightFromSkeleton() const { } } -AvatarTransit::Status Avatar::updateTransit(const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config) { +AvatarTransit::Status Avatar::updateTransit(float deltaTime, const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config) { std::lock_guard lock(_transitLock); - return _transit.update(avatarPosition, config); + return _transit.update(deltaTime, avatarPosition, config); } void Avatar::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index b955706861..28593ff9c0 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -63,12 +63,11 @@ public: struct TransitAnimation { TransitAnimation() {}; - TransitAnimation(const QString& animationUrl, int fps, int firstFrame, int frameCount) : - _firstFrame(firstFrame), _frameCount(frameCount), _animationUrl(animationUrl), _fps(fps) {}; + TransitAnimation(const QString& animationUrl, int firstFrame, int frameCount) : + _firstFrame(firstFrame), _frameCount(frameCount), _animationUrl(animationUrl) {}; int _firstFrame; int _frameCount; QString _animationUrl; - int _fps; }; struct TransitConfig { @@ -83,27 +82,30 @@ public: TransitAnimation _endTransitAnimation; }; - AvatarTransit() {}; - Status update(const glm::vec3& avatarPosition, const TransitConfig& config); + Status update(float deltaTime, const glm::vec3& avatarPosition, const TransitConfig& config); bool isTransiting() { return _isTransiting; }; glm::vec3 getCurrentPosition() { return _currentPosition; }; bool getNextPosition(glm::vec3& nextPosition); - int getCurrentStep() { return _step; }; private: - void calculateSteps(int stepCount); - Status updatePosition(const glm::vec3& avatarPosition); - void start(const glm::vec3& startPosition, const glm::vec3& endPosition, const TransitConfig& config); + Status updatePosition(float deltaTime); + void start(float deltaTime, const glm::vec3& startPosition, const glm::vec3& endPosition, const TransitConfig& config); bool _isTransiting{ false }; + glm::vec3 _startPosition; glm::vec3 _endPosition; glm::vec3 _currentPosition; - int _framesBefore { 0 }; - int _framesAfter { 0 }; - std::vector _transitSteps; + glm::vec3 _lastPosition; - int _step { 0 }; + + glm::vec3 _transitLine; + float _totalDistance { 0.0f }; + float _totalTime { 0.0f }; + float _currentTime { 0.0f }; + float _transitTime { 0.0f }; + float _timeBefore { 0.0f }; + float _timeAfter { 0.0f }; }; class Avatar : public AvatarData, public scriptable::ModelProvider { @@ -419,7 +421,7 @@ public: std::shared_ptr getTransit() { return std::make_shared(_transit); }; - AvatarTransit::Status updateTransit(const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config); + AvatarTransit::Status updateTransit(float deltaTime, const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config); signals: void targetScaleChanged(float targetScale);