Merge pull request #16498 from DouglasWilcox/improve_seated_rotation

Improve seated rotation
This commit is contained in:
Brad Hefta-Gaub 2019-11-19 10:22:08 -08:00 committed by GitHub
commit 0f428f0afb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 320 additions and 79 deletions

View file

@ -684,139 +684,295 @@
"children": [
{
"children": [
{
"children": [
],
"data": {
"endFrame": 800,
"loopFlag": true,
"startFrame": 0,
"timeScale": 1,
"url": "qrc:///avatar/animations/sitting_idle.fbx"
},
"id": "seatedIdle01",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 800,
"loopFlag": true,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/sitting_idle02.fbx"
},
"id": "seatedIdle02",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 800,
"loopFlag": true,
"startFrame": 0,
"timeScale": 1,
"url": "qrc:///avatar/animations/sitting_idle03.fbx"
},
"id": "seatedIdle03",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 800,
"loopFlag": true,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/sitting_idle04.fbx"
},
"id": "seatedIdle04",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 332,
"loopFlag": true,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/sitting_idle05.fbx"
},
"id": "seatedIdle05",
"type": "clip"
}
],
"data": {
"endFrame": 800,
"loopFlag": true,
"startFrame": 0,
"currentState": "seatedIdle01",
"endFrame": 30,
"randomSwitchTimeMax": 40,
"randomSwitchTimeMin": 10,
"startFrame": 10,
"states": [
{
"easingType": "easeInOutQuad",
"id": "seatedIdle01",
"interpDuration": 30,
"interpTarget": 30,
"interpType": "evaluateBoth",
"priority": 1,
"resume": true,
"transitions": [
]
},
{
"easingType": "easeInOutQuad",
"id": "seatedIdle02",
"interpDuration": 30,
"interpTarget": 30,
"interpType": "evaluateBoth",
"priority": 1,
"resume": true,
"transitions": [
]
},
{
"easingType": "easeInOutQuad",
"id": "seatedIdle03",
"interpDuration": 30,
"interpTarget": 30,
"interpType": "evaluateBoth",
"priority": 1,
"resume": true,
"transitions": [
]
},
{
"easingType": "easeInOutQuad",
"id": "seatedIdle04",
"interpDuration": 30,
"interpTarget": 30,
"interpType": "evaluateBoth",
"priority": 1,
"resume": true,
"transitions": [
]
},
{
"easingType": "easeInOutQuad",
"id": "seatedIdle05",
"interpDuration": 30,
"interpTarget": 30,
"interpType": "evaluateBoth",
"priority": 1,
"resume": true,
"transitions": [
]
}
],
"timeScale": 1,
"url": "qrc:///avatar/animations/sitting_idle.fbx"
"triggerRandomSwitch": "seatedIdleSwitch",
"triggerTimeMax": 10
},
"id": "seatedIdle01",
"type": "clip"
"id": "masterSeatedIdleRand",
"type": "randomSwitchStateMachine"
},
{
"children": [
],
"data": {
"endFrame": 800,
"endFrame": 200,
"loopFlag": true,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/sitting_idle02.fbx"
"url": "qrc:///avatar/animations/sitting_turn_left.fbx"
},
"id": "seatedIdle02",
"id": "seatedTurnLeft",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 800,
"loopFlag": true,
"startFrame": 0,
"timeScale": 1,
"url": "qrc:///avatar/animations/sitting_idle03.fbx"
},
"id": "seatedIdle03",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 800,
"endFrame": 200,
"loopFlag": true,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/sitting_idle04.fbx"
"url": "qrc:///avatar/animations/sitting_turn_right.fbx"
},
"id": "seatedIdle04",
"id": "seatedTurnRight",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 332,
"loopFlag": true,
"endFrame": 45,
"loopFlag": false,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/sitting_idle05.fbx"
"url": "qrc:///avatar/animations/settle_sitturnright_to_sitidle.fbx"
},
"id": "seatedIdle05",
"id": "seatedTurnRight_to_Idle",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 45,
"loopFlag": false,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/settle_sitturnleft_to_sitidle.fbx"
},
"id": "seatedTurnLeft_to_Idle",
"type": "clip"
}
],
"data": {
"currentState": "seatedIdle01",
"endFrame": 30,
"randomSwitchTimeMax": 40,
"randomSwitchTimeMin": 10,
"startFrame": 10,
"currentState": "masterSeatedIdleRand",
"states": [
{
"easingType": "easeInOutQuad",
"id": "seatedIdle01",
"interpDuration": 30,
"interpTarget": 30,
"interpType": "evaluateBoth",
"priority": 1,
"resume": true,
"id": "masterSeatedIdleRand",
"interpDuration": 15,
"interpTarget": 15,
"interpType": "snapshotPrev",
"transitions": [
{
"state": "seatedTurnLeft",
"var": "isSeatedTurningLeft"
},
{
"state": "seatedTurnRight",
"var": "isSeatedTurningRight"
}
]
},
{
"easingType": "easeInOutQuad",
"id": "seatedIdle02",
"interpDuration": 30,
"interpTarget": 30,
"id": "seatedTurnLeft",
"interpDuration": 22,
"interpTarget": 22,
"interpType": "evaluateBoth",
"priority": 1,
"resume": true,
"transitions": [
{
"state": "seatedTurnLeft_to_Idle",
"var": "isSeatedNotTurning"
},
{
"state": "seatedTurnRight",
"var": "isSeatedTurningRight"
}
]
},
{
"easingType": "easeInOutQuad",
"id": "seatedIdle03",
"interpDuration": 30,
"interpTarget": 30,
"id": "seatedTurnRight",
"interpDuration": 22,
"interpTarget": 22,
"interpType": "evaluateBoth",
"priority": 1,
"resume": true,
"transitions": [
{
"state": "seatedTurnLeft",
"var": "isSeatedTurningLeft"
},
{
"state": "seatedTurnRight_to_Idle",
"var": "isSeatedNotTurning"
}
]
},
{
"easingType": "easeInOutQuad",
"id": "seatedIdle04",
"interpDuration": 30,
"interpTarget": 30,
"id": "seatedTurnRight_to_Idle",
"interpDuration": 22,
"interpTarget": 22,
"interpType": "evaluateBoth",
"priority": 1,
"resume": true,
"transitions": [
{
"state": "seatedTurnLeft",
"var": "isSeatedTurningLeft"
},
{
"state": "seatedTurnRight",
"var": "isSeatedTurningRight"
},
{
"state": "masterSeatedIdleRand",
"var": "seatedTurnRight_to_IdleOnDone"
}
]
},
{
"easingType": "easeInOutQuad",
"id": "seatedIdle05",
"interpDuration": 30,
"interpTarget": 30,
"id": "seatedTurnLeft_to_Idle",
"interpDuration": 22,
"interpTarget": 22,
"interpType": "evaluateBoth",
"priority": 1,
"resume": true,
"transitions": [
{
"state": "seatedTurnRight",
"var": "isSeatedTurningRight"
},
{
"state": "seatedTurnLeft",
"var": "isSeatedTurningLeft"
},
{
"state": "masterSeatedIdleRand",
"var": "seatedTurnLeft_to_IdleOnDone"
}
]
}
],
"timeScale": 1,
"triggerRandomSwitch": "seatedIdleSwitch",
"triggerTimeMax": 10
]
},
"id": "masterSeatedIdle",
"type": "randomSwitchStateMachine"
"type": "stateMachine"
},
{
"children": [
@ -1082,6 +1238,14 @@
{
"randomSwitchState": "masterSeatedIdle",
"var": "seatedFidgetShakeLegsOnDone"
},
{
"randomSwitchState": "masterSeatedIdle",
"var": "isSeatedTurningRight"
},
{
"randomSwitchState": "masterSeatedIdle",
"var": "isSeatedTurningLeft"
}
]
}

View file

@ -3508,8 +3508,46 @@ void MyAvatar::updateOrientation(float deltaTime) {
}
setWorldOrientation(glm::slerp(getWorldOrientation(), faceRotation, blend));
} else if (isRotatingWhileSeated) {
float rotatingWhileSeatedYaw = -getDriveKey(TRANSLATE_X) * _yawSpeed * deltaTime;
setWorldOrientation(getWorldOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, rotatingWhileSeatedYaw, 0.0f))));
float direction = -getDriveKey(TRANSLATE_X);
float seatedTargetSpeed = direction * _yawSpeed * deltaTime; //deg/renderframe
const float SEATED_ROTATION_ACCEL_SCALE = 3.5;
float blend = deltaTime * SEATED_ROTATION_ACCEL_SCALE;
if (blend > 1.0f) {
blend = 1.0f;
}
//init, accelerate or clamp rotation at target speed
if (fabsf(_seatedBodyYawDelta) > 0.0f) {
if (fabsf(_seatedBodyYawDelta) >= fabsf(seatedTargetSpeed)) {
_seatedBodyYawDelta = seatedTargetSpeed;
} else {
_seatedBodyYawDelta += blend * direction;
}
} else {
_seatedBodyYawDelta = blend * direction;
}
setWorldOrientation(getWorldOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, _seatedBodyYawDelta, 0.0f))));
} else if (_seatedBodyYawDelta != 0.0f) {
//decelerate from seated rotation
const float ROTATION_DECAY_TIMESCALE = 0.25f;
float attenuation = 1.0f - deltaTime / ROTATION_DECAY_TIMESCALE;
if (attenuation < 0.0f) {
attenuation = 0.0f;
}
_seatedBodyYawDelta *= attenuation;
float MINIMUM_ROTATION_RATE = 2.0f;
if (fabsf(_seatedBodyYawDelta) < MINIMUM_ROTATION_RATE * deltaTime) {
_seatedBodyYawDelta = 0.0f;
}
setWorldOrientation(getWorldOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, _seatedBodyYawDelta, 0.0f))));
} else {
_seatedBodyYawDelta = 0.0f;
}
}
@ -3568,20 +3606,20 @@ void MyAvatar::updateOrientation(float deltaTime) {
const float DEFAULT_REORIENT_ANGLE = 65.0f;
const float FIRST_PERSON_REORIENT_ANGLE = 95.0f;
const float TRIGGER_REORIENT_ANGLE = 45.0f;
const float TRIGGER_REORIENT_ANGLE = 135.0f;
const float FIRST_PERSON_TRIGGER_REORIENT_ANGLE = 65.0f;
glm::vec3 ajustedYawVector = cameraYawVector;
float limitAngle = 0.0f;
float triggerAngle = -glm::sin(glm::radians(TRIGGER_REORIENT_ANGLE));
float triggerAngle = glm::cos(glm::radians(TRIGGER_REORIENT_ANGLE));
float limitAngle = triggerAngle;
if (mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT) {
limitAngle = glm::sin(glm::radians(90.0f - FIRST_PERSON_TRIGGER_REORIENT_ANGLE));
limitAngle = glm::cos(glm::radians(FIRST_PERSON_TRIGGER_REORIENT_ANGLE));
triggerAngle = limitAngle;
}
float reorientAngle = mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT ? FIRST_PERSON_REORIENT_ANGLE : DEFAULT_REORIENT_ANGLE;
if (frontBackDot < 0.0f) {
ajustedYawVector = (leftRightDot < 0.0f ? -avatarVectorRight : avatarVectorRight);
}
if (frontBackDot < limitAngle) {
if (frontBackDot < 0.0f) {
ajustedYawVector = (leftRightDot < 0.0f ? -avatarVectorRight : avatarVectorRight);
}
if (!isRotatingWhileSeated) {
if (frontBackDot < triggerAngle) {
_shouldTurnToFaceCamera = true;
@ -3589,6 +3627,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
}
} else {
setWorldOrientation(previousOrientation);
_seatedBodyYawDelta = 0.0f;
}
} else if (frontBackDot > glm::sin(glm::radians(reorientAngle))) {
_shouldTurnToFaceCamera = false;

View file

@ -1093,6 +1093,12 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
const float TURN_ENTER_SPEED_THRESHOLD = 0.5f; // rad/sec
const float TURN_EXIT_SPEED_THRESHOLD = 0.2f; // rad/sec
//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 (ccState == CharacterControllerState::Hover) {
if (_desiredState != RigRole::Hover) {
_desiredStateAge = 0.0f;
@ -1245,6 +1251,9 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_animVars.set("isNotInAir", true);
_animVars.set("isSeated", false);
_animVars.set("isNotSeated", true);
_animVars.set("isSeatedTurningRight", false);
_animVars.set("isSeatedTurningLeft", false);
_animVars.set("isSeatedNotTurning", false);
} else if (_state == RigRole::Turn) {
if (turningSpeed > 0.0f) {
@ -1275,6 +1284,9 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_animVars.set("isNotInAir", true);
_animVars.set("isSeated", false);
_animVars.set("isNotSeated", true);
_animVars.set("isSeatedTurningRight", false);
_animVars.set("isSeatedTurningLeft", false);
_animVars.set("isSeatedNotTurning", false);
} else if (_state == RigRole::Idle) {
// default anim vars to notMoving and notTurning
@ -1298,6 +1310,9 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_animVars.set("isNotInAir", true);
_animVars.set("isSeated", false);
_animVars.set("isNotSeated", true);
_animVars.set("isSeatedTurningRight", false);
_animVars.set("isSeatedTurningLeft", false);
_animVars.set("isSeatedNotTurning", false);
} else if (_state == RigRole::Hover) {
// flying.
@ -1321,6 +1336,9 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_animVars.set("isNotInAir", true);
_animVars.set("isSeated", false);
_animVars.set("isNotSeated", true);
_animVars.set("isSeatedTurningRight", false);
_animVars.set("isSeatedTurningLeft", false);
_animVars.set("isSeatedNotTurning", false);
} else if (_state == RigRole::Takeoff) {
// jumping in-air
@ -1352,6 +1370,9 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_animVars.set("isNotInAir", false);
_animVars.set("isSeated", false);
_animVars.set("isNotSeated", true);
_animVars.set("isSeatedTurningRight", false);
_animVars.set("isSeatedTurningLeft", false);
_animVars.set("isSeatedNotTurning", false);
} else if (_state == RigRole::InAir) {
// jumping in-air
@ -1372,6 +1393,9 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_animVars.set("isNotTakeoff", true);
_animVars.set("isSeated", false);
_animVars.set("isNotSeated", true);
_animVars.set("isSeatedTurningRight", false);
_animVars.set("isSeatedTurningLeft", false);
_animVars.set("isSeatedNotTurning", false);
bool inAirRun = forwardSpeed > 0.1f;
if (inAirRun) {
@ -1394,6 +1418,23 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_animVars.set("inAirAlpha", alpha);
} else if (_state == RigRole::Seated) {
if (fabsf(_previousControllerParameters.inputX) <= INPUT_DEADZONE_THRESHOLD) {
// seated not turning
_animVars.set("isSeatedTurningRight", false);
_animVars.set("isSeatedTurningLeft", false);
_animVars.set("isSeatedNotTurning", true);
} else if (_previousControllerParameters.inputX > 0.0f) {
// seated turning right
_animVars.set("isSeatedTurningRight", true);
_animVars.set("isSeatedTurningLeft", false);
_animVars.set("isSeatedNotTurning", false);
} else {
// seated turning left
_animVars.set("isSeatedTurningRight", false);
_animVars.set("isSeatedTurningLeft", true);
_animVars.set("isSeatedNotTurning", false);
}
_animVars.set("isMovingForward", false);
_animVars.set("isMovingBackward", false);
_animVars.set("isMovingRight", false);
@ -1435,11 +1476,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_lastEnableInverseKinematics = _enableInverseKinematics;
//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) {

View file

@ -662,6 +662,7 @@ protected:
std::vector<std::shared_ptr<Model>> _attachmentsToDelete;
float _bodyYawDelta { 0.0f }; // degrees/sec
float _seatedBodyYawDelta{ 0.0f }; // degrees/renderframe
// These position histories and derivatives are in the world-frame.
// The derivatives are the MEASURED results of all external and internal forces