Added strafe and backward blending

This commit is contained in:
Anthony J. Thibault 2015-10-21 17:34:09 -07:00
parent 41cce4320a
commit c83af43d0e
3 changed files with 133 additions and 41 deletions

View file

@ -4,7 +4,7 @@
"id": "ikOverlay", "id": "ikOverlay",
"type": "overlay", "type": "overlay",
"data": { "data": {
"alpha": 0.0, "alpha": 1.0,
"boneSet": "fullBody" "boneSet": "fullBody"
}, },
"children": [ "children": [
@ -532,8 +532,8 @@
"alpha": 0.0, "alpha": 0.0,
"sync": true, "sync": true,
"timeScale": 1.0, "timeScale": 1.0,
"timeScaleVar": "walkTimeScale", "timeScaleVar": "moveForwardTimeScale",
"alphaVar": "walkAlpha" "alphaVar": "moveForwardAlpha"
}, },
"children": [ "children": [
{ {
@ -576,16 +576,40 @@
}, },
{ {
"id": "walkBwd", "id": "walkBwd",
"type": "clip", "type": "blendLinear",
"data": { "data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_bwd.fbx", "alpha": 1.0,
"startFrame": 0.0, "sync": true,
"endFrame": 37.0,
"timeScale": 1.0, "timeScale": 1.0,
"loopFlag": true, "timeScaleVar": "moveBackwardTimeScale",
"timeScaleVar": "walkTimeScale" "alphaVar": "moveBackwardAlpha"
}, },
"children": [] "children": [
{
"id": "walkBwdShort",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_short_bwd.fbx",
"startFrame": 0.0,
"endFrame": 38.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "walkBwdNormal",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_bwd.fbx",
"startFrame": 0.0,
"endFrame": 36.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
}
]
}, },
{ {
"id": "turnLeft", "id": "turnLeft",
@ -613,27 +637,77 @@
}, },
{ {
"id": "strafeLeft", "id": "strafeLeft",
"type": "clip", "type": "blendLinear",
"data": { "data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_left.fbx", "alpha": 0.0,
"startFrame": 0.0, "sync": true,
"endFrame": 30.0,
"timeScale": 1.0, "timeScale": 1.0,
"loopFlag": true "timeScaleVar": "moveLateralTimeScale",
"alphaVar": "moveLateralAlpha"
}, },
"children": [] "children": [
{
"id": "strafeLeftShort",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_short_left.fbx",
"startFrame": 0.0,
"endFrame": 28.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "strafeLeftNormal",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_left.fbx",
"startFrame": 0.0,
"endFrame": 30.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
}
]
}, },
{ {
"id": "strafeRight", "id": "strafeRight",
"type": "clip", "type": "blendLinear",
"data": { "data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_right.fbx", "alpha": 0.0,
"startFrame": 0.0, "sync": true,
"endFrame": 30.0,
"timeScale": 1.0, "timeScale": 1.0,
"loopFlag": true "timeScaleVar": "moveLateralTimeScale",
"alphaVar": "moveLateralAlpha"
}, },
"children": [] "children": [
{
"id": "strafeRightShort",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_short_right.fbx",
"startFrame": 0.0,
"endFrame": 28.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "strafeRightNormal",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_right.fbx",
"startFrame": 0.0,
"endFrame": 30.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
}
]
} }
] ]
} }

View file

@ -408,25 +408,20 @@ glm::mat4 Rig::getJointTransform(int jointIndex) const {
return _jointStates[jointIndex].getTransform(); return _jointStates[jointIndex].getTransform();
} }
void Rig::calcWalkForwardAlphaAndTimeScale(float speed, float* alphaOut, float* timeScaleOut) { void Rig::calcAnimAlphaAndTimeScale(float speed, const std::vector<float>& referenceSpeeds, float* alphaOut, float* timeScaleOut) const {
// filter speed using a moving average. assert(referenceSpeeds.size() > 0);
_averageForwardSpeed.updateAverage(speed);
speed = _averageForwardSpeed.getAverage();
const int NUM_FWD_SPEEDS = 3;
float FWD_SPEEDS[NUM_FWD_SPEEDS] = { 0.3f, 1.4f, 2.7f }; // m/s
// first calculate alpha by lerping between speeds. // first calculate alpha by lerping between speeds.
float alpha = 0.0f; float alpha = 0.0f;
if (speed <= FWD_SPEEDS[0]) { if (speed <= referenceSpeeds.front()) {
alpha = 0.0f; alpha = 0.0f;
} else if (speed > FWD_SPEEDS[NUM_FWD_SPEEDS - 1]) { } else if (speed > referenceSpeeds.back()) {
alpha = (float)(NUM_FWD_SPEEDS - 1); alpha = (float)(referenceSpeeds.size() - 1);
} else { } else {
for (int i = 0; i < NUM_FWD_SPEEDS - 1; i++) { for (size_t i = 0; i < referenceSpeeds.size() - 1; i++) {
if (FWD_SPEEDS[i] < speed && speed < FWD_SPEEDS[i + 1]) { if (referenceSpeeds[i] < speed && speed < referenceSpeeds[i + 1]) {
alpha = (float)i + ((speed - FWD_SPEEDS[i]) / (FWD_SPEEDS[i + 1] - FWD_SPEEDS[i])); alpha = (float)i + ((speed - referenceSpeeds[i]) / (referenceSpeeds[i + 1] - referenceSpeeds[i]));
break; break;
} }
} }
@ -436,13 +431,18 @@ void Rig::calcWalkForwardAlphaAndTimeScale(float speed, float* alphaOut, float*
// NOTE: This makes the assumption that the velocity of a linear blend between two animations is also linear. // NOTE: This makes the assumption that the velocity of a linear blend between two animations is also linear.
int prevIndex = glm::floor(alpha); int prevIndex = glm::floor(alpha);
int nextIndex = glm::ceil(alpha); int nextIndex = glm::ceil(alpha);
float animSpeed = lerp(FWD_SPEEDS[prevIndex], FWD_SPEEDS[nextIndex], (float)glm::fract(alpha)); float animSpeed = lerp(referenceSpeeds[prevIndex], referenceSpeeds[nextIndex], (float)glm::fract(alpha));
float timeScale = glm::clamp(0.5f, 2.0f, speed / animSpeed); float timeScale = glm::clamp(0.5f, 2.0f, speed / animSpeed);
*alphaOut = alpha; *alphaOut = alpha;
*timeScaleOut = timeScale; *timeScaleOut = timeScale;
} }
// animation reference speeds.
static const std::vector<float> FORWARD_SPEEDS = { 0.4f, 1.4f, 2.5f }; // m/s
static const std::vector<float> BACKWARD_SPEEDS = { 0.45f, 1.4f }; // m/s
static const std::vector<float> LATERAL_SPEEDS = { 0.2f, 0.65f }; // m/s
void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation) { void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation) {
glm::vec3 front = worldRotation * IDENTITY_FRONT; glm::vec3 front = worldRotation * IDENTITY_FRONT;
@ -468,15 +468,32 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
float lateralSpeed = glm::dot(localVel, IDENTITY_RIGHT); float lateralSpeed = glm::dot(localVel, IDENTITY_RIGHT);
float turningSpeed = glm::orientedAngle(front, _lastFront, IDENTITY_UP) / deltaTime; float turningSpeed = glm::orientedAngle(front, _lastFront, IDENTITY_UP) / deltaTime;
// filter speeds using a simple moving average.
_averageForwardSpeed.updateAverage(forwardSpeed);
_averageLateralSpeed.updateAverage(lateralSpeed);
// sine wave LFO var for testing. // sine wave LFO var for testing.
static float t = 0.0f; static float t = 0.0f;
_animVars.set("sine", 2.0f * static_cast<float>(0.5 * sin(t) + 0.5)); _animVars.set("sine", 2.0f * static_cast<float>(0.5 * sin(t) + 0.5));
float walkAlpha, walkTimeScale; float moveForwardAlpha = 0.0f;
calcWalkForwardAlphaAndTimeScale(glm::length(localVel), &walkAlpha, &walkTimeScale); float moveForwardTimeScale = 1.0f;
float moveBackwardAlpha = 0.0f;
float moveBackwardTimeScale = 1.0f;
float moveLateralAlpha = 0.0f;
float moveLateralTimeScale = 1.0f;
_animVars.set("walkTimeScale", walkTimeScale); // calcuate the animation alpha and timeScale values based on current speeds and animation reference speeds.
_animVars.set("walkAlpha", walkAlpha); calcAnimAlphaAndTimeScale(_averageForwardSpeed.getAverage(), FORWARD_SPEEDS, &moveForwardAlpha, &moveForwardTimeScale);
calcAnimAlphaAndTimeScale(-_averageForwardSpeed.getAverage(), BACKWARD_SPEEDS, &moveBackwardAlpha, &moveBackwardTimeScale);
calcAnimAlphaAndTimeScale(fabsf(_averageLateralSpeed.getAverage()), LATERAL_SPEEDS, &moveLateralAlpha, &moveLateralTimeScale);
_animVars.set("moveFowardTimeScale", moveForwardTimeScale);
_animVars.set("moveForwardAlpha", moveForwardAlpha);
_animVars.set("moveBackwardTimeScale", moveBackwardTimeScale);
_animVars.set("moveBackwardAlpha", moveBackwardAlpha);
_animVars.set("moveLateralTimeScale", moveLateralTimeScale);
_animVars.set("moveLateralAlpha", moveLateralAlpha);
const float MOVE_ENTER_SPEED_THRESHOLD = 0.2f; // m/sec const float MOVE_ENTER_SPEED_THRESHOLD = 0.2f; // m/sec
const float MOVE_EXIT_SPEED_THRESHOLD = 0.07f; // m/sec const float MOVE_EXIT_SPEED_THRESHOLD = 0.07f; // m/sec

View file

@ -208,7 +208,7 @@ public:
void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist); void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist);
void updateNeckJoint(int index, const HeadParameters& params); void updateNeckJoint(int index, const HeadParameters& params);
void updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade); void updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade);
void calcWalkForwardAlphaAndTimeScale(float speed, float* alphaOut, float* timeScaleOut); void calcAnimAlphaAndTimeScale(float speed, const std::vector<float>& referenceSpeeds, float* alphaOut, float* timeScaleOut) const;
QVector<JointState> _jointStates; QVector<JointState> _jointStates;
int _rootJointIndex = -1; int _rootJointIndex = -1;
@ -245,6 +245,7 @@ public:
float _rightHandOverlayAlpha = 0.0f; float _rightHandOverlayAlpha = 0.0f;
SimpleMovingAverage _averageForwardSpeed{ 25 }; SimpleMovingAverage _averageForwardSpeed{ 25 };
SimpleMovingAverage _averageLateralSpeed{ 25 };
}; };
#endif /* defined(__hifi__Rig__) */ #endif /* defined(__hifi__Rig__) */