From dac6667ee6dff76f2ba031de6c58d35e891bbaa8 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 27 Jul 2015 09:21:24 -0700 Subject: [PATCH] Start of state. --- libraries/animation/src/Rig.cpp | 69 +++++++++++++++++++++------- libraries/animation/src/Rig.h | 19 ++++++-- libraries/render-utils/src/Model.cpp | 2 +- 3 files changed, 68 insertions(+), 22 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 7d520e7930..c0602dc870 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #include "AnimationHandle.h" @@ -38,18 +39,15 @@ void Rig::removeAnimationHandle(const AnimationHandlePointer& handle) { void Rig::startAnimation(const QString& url, float fps, float priority, bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints) { - qCDebug(animation) << "startAnimation" << url << fps << priority << loop << hold << firstFrame << lastFrame << maskedJoints; - AnimationHandlePointer handle = nullptr; + //qCDebug(animation) << "startAnimation" << url << fps << priority << loop << hold << firstFrame << lastFrame << maskedJoints; foreach (const AnimationHandlePointer& candidate, _animationHandles) { if (candidate->getURL() == url) { - handle = candidate; - break; + candidate->start(); + return; } } - if (!handle) { - handle = createAnimationHandle(); - handle->setURL(url); - } + AnimationHandlePointer handle = createAnimationHandle(); + handle->setURL(url); handle->setFPS(fps); handle->setPriority(priority); handle->setLoop(loop); @@ -63,18 +61,17 @@ void Rig::startAnimation(const QString& url, float fps, float priority, void Rig::addAnimationByRole(const QString& role, const QString& url, float fps, float priority, bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints, bool startAutomatically) { // check for a configured animation for the role - qCDebug(animation) << "addAnimationByRole" << role << url << fps << priority << loop << hold << firstFrame << lastFrame << maskedJoints << startAutomatically; - AnimationHandlePointer handle = nullptr; + //qCDebug(animation) << "addAnimationByRole" << role << url << fps << priority << loop << hold << firstFrame << lastFrame << maskedJoints << startAutomatically; foreach (const AnimationHandlePointer& candidate, _animationHandles) { if (candidate->getRole() == role) { - handle = candidate; - break; + if (startAutomatically) { + candidate->start(); + } + return; } } - if (!handle) { - handle = createAnimationHandle(); - handle->setRole(role); - } + AnimationHandlePointer handle = createAnimationHandle(); + handle->setRole(role); handle->setURL(url); handle->setFPS(fps); handle->setPriority(priority); @@ -344,7 +341,45 @@ glm::mat4 Rig::getJointVisibleTransform(int jointIndex) const { return maybeCauterizeHead(jointIndex).getVisibleTransform(); } -void Rig::simulateInternal(float deltaTime, glm::mat4 parentTransform) { +void Rig::simulateInternal(float deltaTime, glm::mat4 parentTransform, const glm::vec3& worldPosition, const glm::quat& worldRotation) { + glm::vec3 front = worldRotation * IDENTITY_FRONT; + glm::vec3 delta = worldPosition - _lastPosition ; + float forwardSpeed = glm::dot(delta, front) / deltaTime; + float rotationalSpeed = glm::angle(front, _lastFront) / deltaTime; + bool isWalking = std::abs(forwardSpeed) > 0.01; + bool isTurning = std::abs(rotationalSpeed) > 0.5; + + // Crude, until we have blending: + const float EXPECTED_INTERVAL = 1.0f / 60.0f; + if (deltaTime >= EXPECTED_INTERVAL) { + isTurning = isTurning && !isWalking; // Only one of walk/turn, walk wins. + isTurning = false; // FIXME + bool isIdle = !isWalking && !isTurning; + auto singleRole = [](bool walking, bool turning, bool idling) { + return walking ? "walk" : (turning ? "turn" : (idling ? "idle" : "")); + }; + QString toStop = singleRole(_isWalking && !isWalking, _isTurning && !isTurning, _isIdle && !isIdle); + if (!toStop.isEmpty()) { + //qCDebug(animation) << "isTurning" << isTurning << "fronts" << front << _lastFront << glm::angle(front, _lastFront) << rotationalSpeed; + //stopAnimationByRole(toStop); + } + QString newRole = singleRole(isWalking && !_isWalking, isTurning && !_isTurning, isIdle && !_isIdle); + if (!newRole.isEmpty()) { + //startAnimationByRole(newRole); + qCDebug(animation) << deltaTime << ":" /*<< _lastPosition << worldPosition << "=>" */<< delta << "." << front << "=> " << forwardSpeed << newRole; + /*if (newRole == "idle") { + qCDebug(animation) << deltaTime << ":" << _lastPosition << worldPosition << "=>" << delta; + }*/ + } + + _lastPosition = worldPosition; + _positions[(++_positionIndex) % _positions.count()] = worldPosition; // exp. alt. to above line + _lastFront = front; + _isWalking = isWalking; + _isTurning = isTurning; + _isIdle = isIdle; + } + // update animations foreach (const AnimationHandlePointer& handle, _runningAnimations) { handle->simulate(deltaTime); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 2087ad6800..b56151b5be 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -71,8 +71,9 @@ public: float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f, float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList()); void stopAnimationByRole(const QString& role); - void addAnimationByRole(const QString& role, const QString& url, float fps, float priority, - bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints, bool startAutomatically); + void addAnimationByRole(const QString& role, const QString& url = QString(), float fps = 30.0f, + float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f, + float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList(), bool startAutomatically = false); float initJointStates(QVector states, glm::mat4 parentTransform, int neckJointIndex); bool jointStatesEmpty() { return _jointStates.isEmpty(); }; @@ -107,7 +108,7 @@ public: void setJointTransform(int jointIndex, glm::mat4 newTransform); glm::mat4 getJointVisibleTransform(int jointIndex) const; void setJointVisibleTransform(int jointIndex, glm::mat4 newTransform); - void simulateInternal(float deltaTime, glm::mat4 parentTransform); + void simulateInternal(float deltaTime, glm::mat4 parentTransform, const glm::vec3& worldPosition, const glm::quat& worldRotation); bool setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation, int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority, const QVector& freeLineage, glm::mat4 parentTransform); @@ -144,6 +145,16 @@ public: std::vector _headBones; bool _jointsAreDirty = false; int _neckJointIndex = -1; -}; + + bool _isWalking; + bool _isTurning; + bool _isIdle; + glm::vec3 _lastFront; + glm::vec3 _lastPosition; + // or, experimentally... + QVector _positions = QVector(4); + QVector _timeIntervals = QVector(4); + int _positionIndex; + }; #endif /* defined(__hifi__Rig__) */ diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index ddf18f6ef8..a316da0f99 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1346,7 +1346,7 @@ void Model::simulateInternal(float deltaTime) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - _rig->simulateInternal(deltaTime, parentTransform); + _rig->simulateInternal(deltaTime, parentTransform, getTranslation(), getRotation()); _shapesAreDirty = !_shapes.isEmpty();