From 2936811484541b5b6133f8e1560393a70a3a8e56 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 29 Jan 2016 18:05:18 -0800 Subject: [PATCH] Added takeoff animation, WIP Character controller still has some jump/in-air bugs. --- .../defaultAvatar_full/avatar-animation.json | 39 ++++++++++++++++--- interface/src/avatar/SkeletonModel.cpp | 2 + libraries/animation/src/Rig.cpp | 35 +++++++++++++++++ libraries/animation/src/Rig.h | 2 + libraries/physics/src/CharacterController.cpp | 33 ++++++++++------ libraries/physics/src/CharacterController.h | 2 + 6 files changed, 97 insertions(+), 16 deletions(-) diff --git a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json index 46912120db..37da0c37cc 100644 --- a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json +++ b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json @@ -248,6 +248,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -265,6 +266,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -281,6 +283,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -297,6 +300,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -313,6 +317,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -329,6 +334,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -345,6 +351,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -361,6 +368,7 @@ { "var": "isTurningRight", "state": "turnRight" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -397,10 +405,19 @@ { "var": "isNotFlying", "state": "idle" } ] }, + { + "id": "takeoff", + "interpTarget": 0, + "interpDuration": 6, + "transitions": [ + { "var": "isAway", "state": "awayIntro" }, + { "var": "isNotTakeoff", "state": "inAir" } + ] + }, { "id": "inAir", - "interpTarget": 3, - "interpDuration": 3, + "interpTarget": 0, + "interpDuration": 6, "transitions": [ { "var": "isAway", "state": "awayIntro" }, { "var": "isNotInAir", "state": "idle" } @@ -704,6 +721,18 @@ }, "children": [] }, + { + "id": "takeoff", + "type": "clip", + "data": { + "url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/jump_takeoff.fbx", + "startFrame": 1.0, + "endFrame": 2.5, + "timeScale": 1.0, + "loopFlag": false + }, + "children": [] + }, { "id": "inAir", "type": "blendLinear", @@ -720,7 +749,7 @@ "startFrame": 0.0, "endFrame": 0.0, "timeScale": 0.0, - "loopFlag": true + "loopFlag": false }, "children": [] }, @@ -732,7 +761,7 @@ "startFrame": 6.0, "endFrame": 6.0, "timeScale": 1.0, - "loopFlag": true + "loopFlag": false }, "children": [] }, @@ -744,7 +773,7 @@ "startFrame": 11.0, "endFrame": 11.0, "timeScale": 1.0, - "loopFlag": true + "loopFlag": false }, "children": [] } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index c8f14578b4..92bdef686d 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -77,6 +77,8 @@ Rig::CharacterControllerState convertCharacterControllerState(CharacterControlle default: case CharacterController::State::Ground: return Rig::CharacterControllerState::Ground; + case CharacterController::State::Takeoff: + return Rig::CharacterControllerState::Takeoff; case CharacterController::State::InAir: return Rig::CharacterControllerState::InAir; case CharacterController::State::Hover: diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 33c8f33ac8..9e811fa358 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -582,6 +582,11 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _desiredStateAge = 0.0f; } _desiredState = RigRole::InAir; + } else if (ccState == CharacterControllerState::Takeoff) { + if (_desiredState != RigRole::Takeoff) { + _desiredStateAge = 0.0f; + } + _desiredState = RigRole::Takeoff; } else { float moveThresh; if (_state != RigRole::Move) { @@ -667,6 +672,8 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotTurning", true); _animVars.set("isFlying", false); _animVars.set("isNotFlying", true); + _animVars.set("isTakeoff", false); + _animVars.set("isNotTakeoff", true); _animVars.set("isInAir", false); _animVars.set("isNotInAir", true); } @@ -689,8 +696,11 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotMoving", true); _animVars.set("isFlying", false); _animVars.set("isNotFlying", true); + _animVars.set("isTakeoff", false); + _animVars.set("isNotTakeoff", true); _animVars.set("isInAir", false); _animVars.set("isNotInAir", true); + } else if (_state == RigRole::Idle ) { // default anim vars to notMoving and notTurning _animVars.set("isMovingForward", false); @@ -703,8 +713,11 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotTurning", true); _animVars.set("isFlying", false); _animVars.set("isNotFlying", true); + _animVars.set("isTakeoff", false); + _animVars.set("isNotTakeoff", true); _animVars.set("isInAir", false); _animVars.set("isNotInAir", true); + } else if (_state == RigRole::Hover) { // flying. _animVars.set("isMovingForward", false); @@ -717,8 +730,28 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotTurning", true); _animVars.set("isFlying", true); _animVars.set("isNotFlying", false); + _animVars.set("isTakeoff", false); + _animVars.set("isNotTakeoff", true); _animVars.set("isInAir", false); _animVars.set("isNotInAir", true); + + } else if (_state == RigRole::Takeoff) { + // jumping in-air + _animVars.set("isMovingForward", false); + _animVars.set("isMovingBackward", false); + _animVars.set("isMovingLeft", false); + _animVars.set("isMovingRight", false); + _animVars.set("isNotMoving", true); + _animVars.set("isTurningLeft", false); + _animVars.set("isTurningRight", false); + _animVars.set("isNotTurning", true); + _animVars.set("isFlying", false); + _animVars.set("isNotFlying", true); + _animVars.set("isTakeoff", true); + _animVars.set("isNotTakeoff", false); + _animVars.set("isInAir", true); + _animVars.set("isNotInAir", false); + } else if (_state == RigRole::InAir) { // jumping in-air _animVars.set("isMovingForward", false); @@ -731,6 +764,8 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotTurning", true); _animVars.set("isFlying", false); _animVars.set("isNotFlying", true); + _animVars.set("isTakeoff", false); + _animVars.set("isNotTakeoff", true); _animVars.set("isInAir", true); _animVars.set("isNotInAir", false); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index dc07a32efd..e12af16e41 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -75,6 +75,7 @@ public: enum class CharacterControllerState { Ground = 0, + Takeoff, InAir, Hover }; @@ -278,6 +279,7 @@ public: Turn, Move, Hover, + Takeoff, InAir }; RigRole _state { RigRole::Idle }; diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 055f846793..93b924d9bc 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -54,6 +54,7 @@ CharacterController::CharacterController() { _state = State::Hover; _isPushingUp = false; _jumpToHoverStart = 0; + _takeoffToInAirStart = 0; _followTime = 0.0f; _followLinearDisplacement = btVector3(0, 0, 0); _followAngularDisplacement = btQuaternion::getIdentity(); @@ -257,18 +258,18 @@ void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) { void CharacterController::jump() { // check for case where user is holding down "jump" key... // we'll eventually transition to "hover" - if (_state != State::InAir) { - if (_state != State::Hover) { - _jumpToHoverStart = usecTimestampNow(); - _pendingFlags |= PENDING_FLAG_JUMP; - } - } else { + if (_state == State::Hover) { quint64 now = usecTimestampNow(); const quint64 JUMP_TO_HOVER_PERIOD = 75 * (USECS_PER_SECOND / 100); if (now - _jumpToHoverStart > JUMP_TO_HOVER_PERIOD) { _isPushingUp = true; setState(State::Hover); } + } else { + if (_state != State::Takeoff) { + _jumpToHoverStart = usecTimestampNow(); + _pendingFlags |= PENDING_FLAG_JUMP; + } } } @@ -430,7 +431,7 @@ void CharacterController::preSimulation() { } // TODO: use collision events rather than ray-trace test to disable jumping const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius; - if (_floorDistance < JUMP_PROXIMITY_THRESHOLD || _hasSupport) { + if (_state != State::Takeoff && (_floorDistance < JUMP_PROXIMITY_THRESHOLD || _hasSupport)) { setState(State::Ground); } } else if (!_hasSupport) { @@ -438,15 +439,25 @@ void CharacterController::preSimulation() { setState(State::Hover); } + quint64 now = usecTimestampNow(); + if (_pendingFlags & PENDING_FLAG_JUMP) { _pendingFlags &= ~ PENDING_FLAG_JUMP; if (onGround()) { - setState(State::InAir); - btVector3 velocity = _rigidBody->getLinearVelocity(); - velocity += _jumpSpeed * _currentUp; - _rigidBody->setLinearVelocity(velocity); + setState(State::Takeoff); + _takeoffToInAirStart = now; } } + + const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 200 * MSECS_PER_SECOND; + if (_state == State::Takeoff && (now - _takeoffToInAirStart) > TAKE_OFF_TO_IN_AIR_PERIOD) { + setState(State::InAir); + + _takeoffToInAirStart = now + USECS_PER_SECOND * 86500.0f; + btVector3 velocity = _rigidBody->getLinearVelocity(); + velocity += _jumpSpeed * _currentUp; + _rigidBody->setLinearVelocity(velocity); + } } _followTime = 0.0f; diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index c8b360237d..5470104a1a 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -77,6 +77,7 @@ public: enum class State { Ground = 0, + Takeoff, InAir, Hover }; @@ -107,6 +108,7 @@ protected: glm::vec3 _boxScale; // used to compute capsule shape + quint64 _takeoffToInAirStart; quint64 _jumpToHoverStart; btScalar _halfHeight;