From ef740140750e2ef1a143f86f2d2672e883ccfd91 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Fri, 19 Oct 2018 13:55:56 -0700 Subject: [PATCH] Small avatars now have a minimum jump height of 0.25 meters This should improve the quality of the jump animation and improve the mobility of small avatars. --- interface/src/avatar/MySkeletonModel.cpp | 2 +- libraries/animation/src/Rig.cpp | 16 ++++++++++++---- libraries/animation/src/Rig.h | 3 ++- libraries/physics/src/CharacterController.cpp | 8 +++++--- libraries/shared/src/AvatarConstants.h | 7 ++++--- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index c1a49d7a10..08a1e190f1 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -298,7 +298,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { auto velocity = myAvatar->getLocalVelocity() / myAvatar->getSensorToWorldScale(); auto position = myAvatar->getLocalPosition(); auto orientation = myAvatar->getLocalOrientation(); - _rig.computeMotionAnimationState(deltaTime, position, velocity, orientation, ccState); + _rig.computeMotionAnimationState(deltaTime, position, velocity, orientation, ccState, myAvatar->getSensorToWorldScale()); // evaluate AnimGraph animation and update jointStates. Model::updateRig(deltaTime, parentTransform); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 341b554949..335cddf218 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -30,6 +30,7 @@ #include "AnimOverlay.h" #include "AnimSkeleton.h" #include "AnimUtil.h" +#include "AvatarConstants.h" #include "IKTarget.h" @@ -629,7 +630,8 @@ bool Rig::getRelativeDefaultJointTranslation(int index, glm::vec3& translationOu } } -void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation, CharacterControllerState ccState) { +void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, + const glm::quat& worldRotation, CharacterControllerState ccState, float sensorToWorldScale) { glm::vec3 forward = worldRotation * IDENTITY_FORWARD; glm::vec3 workingVelocity = worldVelocity; @@ -924,9 +926,15 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos } _animVars.set("isNotInAir", false); - // compute blend based on velocity - const float JUMP_SPEED = 3.5f; - float alpha = glm::clamp(-workingVelocity.y / JUMP_SPEED, -1.0f, 1.0f) + 1.0f; + // We want to preserve the apparent jump height in sensor space. + const float jumpHeight = std::max(sensorToWorldScale * DEFAULT_AVATAR_JUMP_HEIGHT, DEFAULT_AVATAR_MIN_JUMP_HEIGHT); + + // convert jump height to a initial jump speed with the given gravity. + const float jumpSpeed = sqrtf(2.0f * -DEFAULT_AVATAR_GRAVITY * jumpHeight); + + // compute inAirAlpha blend based on velocity + float alpha = glm::clamp((-workingVelocity.y * sensorToWorldScale) / jumpSpeed, -1.0f, 1.0f) + 1.0f; + _animVars.set("inAirAlpha", alpha); } diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index ed0b70d4b6..5330a06a01 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -172,7 +172,8 @@ public: AnimPose getJointPose(int jointIndex) const; // Start or stop animations as needed. - void computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation, CharacterControllerState ccState); + void computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, + const glm::quat& worldRotation, CharacterControllerState ccState, float sensorToWorldScale); // Regardless of who started the animations or how many, update the joints. void updateAnimations(float deltaTime, const glm::mat4& rootTransform, const glm::mat4& rigToWorldTransform); diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 626184d1dc..8fd6d4eada 100755 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -766,14 +766,16 @@ void CharacterController::updateState() { SET_STATE(State::InAir, "takeoff done"); // compute jumpSpeed based on the scaled jump height for the default avatar in default gravity. - float jumpSpeed = sqrtf(2.0f * DEFAULT_AVATAR_GRAVITY * _scaleFactor * DEFAULT_AVATAR_JUMP_HEIGHT); + const float jumpHeight = std::max(_scaleFactor * DEFAULT_AVATAR_JUMP_HEIGHT, DEFAULT_AVATAR_MIN_JUMP_HEIGHT); + const float jumpSpeed = sqrtf(2.0f * -DEFAULT_AVATAR_GRAVITY * jumpHeight); velocity += jumpSpeed * _currentUp; _rigidBody->setLinearVelocity(velocity); } break; case State::InAir: { - const float JUMP_SPEED = _scaleFactor * DEFAULT_AVATAR_JUMP_SPEED; - if ((velocity.dot(_currentUp) <= (JUMP_SPEED / 2.0f)) && ((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport)) { + const float jumpHeight = std::max(_scaleFactor * DEFAULT_AVATAR_JUMP_HEIGHT, DEFAULT_AVATAR_MIN_JUMP_HEIGHT); + const float jumpSpeed = sqrtf(2.0f * -DEFAULT_AVATAR_GRAVITY * jumpHeight); + if ((velocity.dot(_currentUp) <= (jumpSpeed / 2.0f)) && ((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport)) { SET_STATE(State::Ground, "hit ground"); } else if (_flyingAllowed) { btVector3 desiredVelocity = _targetVelocity; diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index 6c38d08c96..87da47a27a 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -70,9 +70,10 @@ const float DEFAULT_AVATAR_MAX_WALKING_BACKWARD_SPEED = 2.2f; // meters / second const float DEFAULT_AVATAR_MAX_FLYING_SPEED = 30.0f; // meters / second const float DEFAULT_AVATAR_WALK_SPEED_THRESHOLD = 0.15f; -const float DEFAULT_AVATAR_GRAVITY = -5.0f; // meters / second^2 -const float DEFAULT_AVATAR_JUMP_SPEED = 3.5f; // meters / second -const float DEFAULT_AVATAR_JUMP_HEIGHT = (DEFAULT_AVATAR_JUMP_SPEED * DEFAULT_AVATAR_JUMP_SPEED) / (2.0f * DEFAULT_AVATAR_GRAVITY); // meters +const float DEFAULT_AVATAR_GRAVITY = -5.0f; // meters / second^2 (world) +const float DEFAULT_AVATAR_JUMP_SPEED = 3.5f; // meters / second (sensor) +const float DEFAULT_AVATAR_JUMP_HEIGHT = (DEFAULT_AVATAR_JUMP_SPEED * DEFAULT_AVATAR_JUMP_SPEED) / (2.0f * -DEFAULT_AVATAR_GRAVITY); // meters (sensor) +const float DEFAULT_AVATAR_MIN_JUMP_HEIGHT = 0.25f; // meters (world) // hack const float DEFAULT_AVATAR_FALL_HEIGHT = 20.0f; // meters const float DEFAULT_AVATAR_MIN_HOVER_HEIGHT = 2.5f; // meters