diff --git a/interface/resources/avatar/animations/settle_to_idle.fbx b/interface/resources/avatar/animations/settle_to_idle.fbx new file mode 100644 index 0000000000..7b801d2c54 Binary files /dev/null and b/interface/resources/avatar/animations/settle_to_idle.fbx differ diff --git a/interface/resources/avatar/animations/settle_to_idle02.fbx b/interface/resources/avatar/animations/settle_to_idle02.fbx new file mode 100644 index 0000000000..be7429091d Binary files /dev/null and b/interface/resources/avatar/animations/settle_to_idle02.fbx differ diff --git a/interface/resources/avatar/animations/settle_to_idle03.fbx b/interface/resources/avatar/animations/settle_to_idle03.fbx new file mode 100644 index 0000000000..e7b48309bb Binary files /dev/null and b/interface/resources/avatar/animations/settle_to_idle03.fbx differ diff --git a/interface/resources/avatar/animations/settle_to_idle04.fbx b/interface/resources/avatar/animations/settle_to_idle04.fbx new file mode 100644 index 0000000000..cc31a240cb Binary files /dev/null and b/interface/resources/avatar/animations/settle_to_idle04.fbx differ diff --git a/interface/resources/avatar/animations/settle_to_idle_small.fbx b/interface/resources/avatar/animations/settle_to_idle_small.fbx index 9161a95d95..21e2ee8478 100644 Binary files a/interface/resources/avatar/animations/settle_to_idle_small.fbx and b/interface/resources/avatar/animations/settle_to_idle_small.fbx differ diff --git a/interface/resources/avatar/avatar-animation.json b/interface/resources/avatar/avatar-animation.json index cfcf1cff73..9c417be90b 100644 --- a/interface/resources/avatar/avatar-animation.json +++ b/interface/resources/avatar/avatar-animation.json @@ -4804,16 +4804,117 @@ }, { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 59, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/settle_to_idle.fbx" + }, + "id": "idleSettle01", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "blendType": "", + "endFrame": 40, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/settle_to_idle02.fbx" + }, + "id": "idleSettle02", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 60, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/settle_to_idle03.fbx" + }, + "id": "idleSettle03", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 82, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/settle_to_idle04.fbx" + }, + "id": "idleSettle04", + "type": "clip" + } ], "data": { + "currentState": "idleSettle01", "endFrame": 59, "loopFlag": false, + "randomSwitchTimeMin": 1, "startFrame": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "idleSettle01", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "idleSettle02", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "idleSettle03", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "idleSettle04", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + } + ], "timeScale": 1, - "url": "qrc:///avatar/animations/settle_to_idle_small.fbx" + "url": "qrc:///avatar/animations/settle_to_idle.fbx" }, "id": "idleSettle", - "type": "clip" + "type": "randomSwitchStateMachine" }, { "children": [ @@ -5346,6 +5447,19 @@ }, "id": "LANDRUN", "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 40, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/settle_to_idle_small.fbx" + }, + "id": "idleSettleSmall", + "type": "clip" } ], "data": { @@ -5371,7 +5485,7 @@ { "easingType": "easeInOutQuad", "id": "idle", - "interpDuration": 15, + "interpDuration": 20, "interpTarget": 20, "interpType": "evaluateBoth", "transitions": [ @@ -5503,13 +5617,114 @@ { "easingType": "easeInOutQuad", "id": "idleSettle", - "interpDuration": 13, - "interpTarget": 14, + "interpDuration": 15, + "interpTarget": 15, "interpType": "snapshotPrev", "transitions": [ { "state": "idle", - "var": "idleSettleOnDone" + "var": "idleSettle01OnDone" + }, + { + "state": "idle", + "var": "idleSettle02OnDone" + }, + { + "state": "idle", + "var": "idleSettle03OnDone" + }, + { + "state": "idle", + "var": "idleSettle04OnDone" + }, + { + "state": "idle", + "var": "reactionPositiveTrigger" + }, + { + "state": "idle", + "var": "reactionNegativeTrigger" + }, + { + "state": "idle", + "var": "reactionRaiseHandEnabled" + }, + { + "state": "idle", + "var": "reactionApplaudEnabled" + }, + { + "state": "idle", + "var": "reactionPointEnabled" + }, + { + "state": "WALKFWD", + "var": "isInputForward" + }, + { + "state": "WALKBWD", + "var": "isInputBackward" + }, + { + "state": "STRAFERIGHT", + "var": "isInputRight" + }, + { + "state": "STRAFELEFT", + "var": "isInputLeft" + }, + { + "state": "strafeRightHmd", + "var": "isMovingRightHmd" + }, + { + "state": "strafeLeftHmd", + "var": "isMovingLeftHmd" + }, + { + "state": "turnRight", + "var": "isTurningRight" + }, + { + "state": "turnLeft", + "var": "isTurningLeft" + }, + { + "state": "fly", + "var": "isFlying" + }, + { + "state": "takeoffStand", + "var": "isTakeoffStand" + }, + { + "state": "TAKEOFFRUN", + "var": "isTakeoffRun" + }, + { + "state": "inAirStand", + "var": "isInAirStand" + }, + { + "state": "INAIRRUN", + "var": "isInAirRun" + }, + { + "state": "seated", + "var": "isSeated" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "idleSettleSmall", + "interpDuration": 10, + "interpTarget": 10, + "interpType": "snapshotPrev", + "transitions": [ + { + "state": "idle", + "var": "idleSettleSmallOnDone" }, { "state": "idle", @@ -5595,6 +5810,10 @@ "interpTarget": 35, "interpType": "snapshotPrev", "transitions": [ + { + "state": "idleSettleSmall", + "var": "isNotInputNoMomentum" + }, { "state": "idleSettle", "var": "isNotInputSlow" @@ -5659,6 +5878,10 @@ "interpTarget": 35, "interpType": "snapshotPrev", "transitions": [ + { + "state": "idleSettleSmall", + "var": "isNotInputNoMomentum" + }, { "state": "idleSettle", "var": "isNotInputSlow" @@ -5723,6 +5946,10 @@ "interpTarget": 25, "interpType": "snapshotPrev", "transitions": [ + { + "state": "idleSettleSmall", + "var": "isNotInputNoMomentum" + }, { "state": "idleSettle", "var": "isNotInputSlow" @@ -5787,6 +6014,10 @@ "interpTarget": 25, "interpType": "snapshotPrev", "transitions": [ + { + "state": "idleSettleSmall", + "var": "isNotInputNoMomentum" + }, { "state": "idleSettle", "var": "isNotInputSlow" diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index fc1885ea2b..fd8bdb1a0b 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1171,6 +1171,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _desiredStateAge += deltaTime; + if (_state == RigRole::Move) { glm::vec3 horizontalVel = localVel - glm::vec3(0.0f, localVel.y, 0.0f); if (glm::length(horizontalVel) > MOVE_ENTER_SPEED_THRESHOLD) { @@ -1437,17 +1438,37 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos //stategraph vars based on input const float INPUT_DEADZONE_THRESHOLD = 0.05f; const float SLOW_SPEED_THRESHOLD = 1.5f; + const float HAS_MOMENTUM_THRESHOLD = 2.2f; + const float RESET_MOMENTUM_THRESHOLD = 0.05f; if (fabsf(_previousControllerParameters.inputX) <= INPUT_DEADZONE_THRESHOLD && fabsf(_previousControllerParameters.inputZ) <= INPUT_DEADZONE_THRESHOLD) { // no WASD input if (fabsf(forwardSpeed) <= SLOW_SPEED_THRESHOLD && fabsf(lateralSpeed) <= SLOW_SPEED_THRESHOLD) { + + //reset this when stopped + if (fabsf(forwardSpeed) <= RESET_MOMENTUM_THRESHOLD && + fabsf(lateralSpeed) <= RESET_MOMENTUM_THRESHOLD) { + _isMovingWithMomentum = false; + } + + _animVars.set("isInputForward", false); _animVars.set("isInputBackward", false); _animVars.set("isInputRight", false); _animVars.set("isInputLeft", false); - _animVars.set("isNotInput", true); - _animVars.set("isNotInputSlow", true); + + // directly reflects input + _animVars.set("isNotInput", true); + + // no input + speed drops to SLOW_SPEED_THRESHOLD + // (don't transition run->idle - slow to walk first) + _animVars.set("isNotInputSlow", _isMovingWithMomentum); + + // no input + speed didn't get above HAS_MOMENTUM_THRESHOLD since last idle + // (brief inputs and movement adjustments) + _animVars.set("isNotInputNoMomentum", !_isMovingWithMomentum); + } else { _animVars.set("isInputForward", false); @@ -1456,8 +1477,13 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isInputLeft", false); _animVars.set("isNotInput", true); _animVars.set("isNotInputSlow", false); + _animVars.set("isNotInputNoMomentum", false); } } else if (fabsf(_previousControllerParameters.inputZ) >= fabsf(_previousControllerParameters.inputX)) { + if (fabsf(forwardSpeed) > HAS_MOMENTUM_THRESHOLD) { + _isMovingWithMomentum = true; + } + if (_previousControllerParameters.inputZ > 0.0f) { // forward _animVars.set("isInputForward", true); @@ -1466,6 +1492,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isInputLeft", false); _animVars.set("isNotInput", false); _animVars.set("isNotInputSlow", false); + _animVars.set("isNotInputNoMomentum", false); } else { // backward _animVars.set("isInputForward", false); @@ -1474,8 +1501,13 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isInputLeft", false); _animVars.set("isNotInput", false); _animVars.set("isNotInputSlow", false); + _animVars.set("isNotInputNoMomentum", false); } } else { + if (fabsf(lateralSpeed) > HAS_MOMENTUM_THRESHOLD) { + _isMovingWithMomentum = true; + } + if (_previousControllerParameters.inputX > 0.0f) { // right _animVars.set("isInputForward", false); @@ -1484,6 +1516,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isInputLeft", false); _animVars.set("isNotInput", false); _animVars.set("isNotInputSlow", false); + _animVars.set("isNotInputNoMomentum", false); } else { // left _animVars.set("isInputForward", false); @@ -1492,6 +1525,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isInputLeft", true); _animVars.set("isNotInput", false); _animVars.set("isNotInputSlow", false); + _animVars.set("isNotInputNoMomentum", false); } } diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index b2b9ecd5b4..60a2602316 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -330,6 +330,7 @@ protected: glm::vec3 _lastForward; glm::vec3 _lastPosition; glm::vec3 _lastVelocity; + bool _isMovingWithMomentum{ false }; QUrl _animGraphURL; std::shared_ptr _animNode;