mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 08:14:48 +02:00
Improved default avatar.json state machine.
Now triggers 7 states. Idle, WalkFwd, WalkBwd, StrafeLeft, StrafeRight, TurnLeft & TurnRight. As well as variable speed walking to match current velocity.
This commit is contained in:
parent
99586f259c
commit
46b3a7fd23
4 changed files with 181 additions and 54 deletions
|
@ -1225,7 +1225,7 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
|
|||
// https://gist.github.com/hyperlogic/7d6a0892a7319c69e2b9
|
||||
// python2 -m SimpleHTTPServer&
|
||||
//auto graphUrl = QUrl("http://localhost:8000/avatar.json");
|
||||
auto graphUrl = QUrl("https://gist.githubusercontent.com/hyperlogic/7d6a0892a7319c69e2b9/raw/a6e3754beef1524f95bae178066bae3b2f839952/avatar.json");
|
||||
auto graphUrl = QUrl("https://gist.githubusercontent.com/hyperlogic/7d6a0892a7319c69e2b9/raw/e2cb37aee601b6fba31d60eac3f6ae3ef72d4a66/avatar.json");
|
||||
|
||||
_skeletonModel.initAnimGraph(graphUrl, _skeletonModel.getGeometry()->getFBXGeometry());
|
||||
}
|
||||
|
|
|
@ -52,7 +52,9 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, fl
|
|||
if (_duringInterp) {
|
||||
_alpha += _alphaVel * dt;
|
||||
if (_alpha < 1.0f) {
|
||||
::blend(_poses.size(), &_prevPoses[0], &_nextPoses[0], _alpha, &_poses[0]);
|
||||
if (_poses.size() > 0) {
|
||||
::blend(_poses.size(), &_prevPoses[0], &_nextPoses[0], _alpha, &_poses[0]);
|
||||
}
|
||||
} else {
|
||||
_duringInterp = false;
|
||||
_prevPoses.clear();
|
||||
|
|
|
@ -416,52 +416,107 @@ glm::mat4 Rig::getJointVisibleTransform(int jointIndex) const {
|
|||
|
||||
void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation) {
|
||||
|
||||
glm::vec3 front = worldRotation * IDENTITY_FRONT;
|
||||
|
||||
// at the moment worldVelocity comes from the Avatar physics body, which is not always correct when
|
||||
// moving in the HMD, so let's compute our own veloicty.
|
||||
glm::vec3 worldVel = (worldPosition - _lastPosition) / deltaTime;
|
||||
glm::vec3 localVel = glm::inverse(worldRotation) * worldVel;
|
||||
float forwardSpeed = glm::dot(localVel, IDENTITY_FRONT);
|
||||
float lateralSpeed = glm::dot(localVel, IDENTITY_RIGHT);
|
||||
float turningSpeed = glm::orientedAngle(front, _lastFront, IDENTITY_UP) / deltaTime;
|
||||
|
||||
if (_enableAnimGraph) {
|
||||
|
||||
// sine wave LFO var for testing.
|
||||
static float t = 0.0f;
|
||||
_animVars.set("sine", static_cast<float>(0.5 * sin(t) + 0.5));
|
||||
|
||||
if (glm::length(worldVelocity) > 0.07f) {
|
||||
_animVars.set("isMoving", true);
|
||||
_animVars.set("isNotMoving", false);
|
||||
// default anim vars to notMoving and notTurning
|
||||
_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);
|
||||
|
||||
const float ANIM_WALK_SPEED = 1.4f; // m/s
|
||||
_animVars.set("walkTimeScale", glm::clamp(0.1f, 2.0f, glm::length(localVel) / ANIM_WALK_SPEED));
|
||||
|
||||
const float MOVE_SPEED_THRESHOLD = 0.01f; // m/sec
|
||||
const float TURN_SPEED_THRESHOLD = 0.5f; // rad/sec
|
||||
if (glm::length(localVel) > MOVE_SPEED_THRESHOLD) {
|
||||
if (fabs(forwardSpeed) > fabs(lateralSpeed)) {
|
||||
if (forwardSpeed > 0.0f) {
|
||||
// forward
|
||||
_animVars.set("isMovingForward", true);
|
||||
_animVars.set("isNotMoving", false);
|
||||
|
||||
} else {
|
||||
// backward
|
||||
_animVars.set("isMovingBackward", true);
|
||||
_animVars.set("isNotMoving", false);
|
||||
}
|
||||
} else {
|
||||
if (lateralSpeed > 0.0f) {
|
||||
// right
|
||||
_animVars.set("isMovingRight", true);
|
||||
_animVars.set("isNotMoving", false);
|
||||
} else {
|
||||
// left
|
||||
_animVars.set("isMovingLeft", true);
|
||||
_animVars.set("isNotMoving", false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_animVars.set("isMoving", false);
|
||||
_animVars.set("isNotMoving", true);
|
||||
if (fabs(turningSpeed) > TURN_SPEED_THRESHOLD) {
|
||||
if (turningSpeed > 0.0f) {
|
||||
// turning right
|
||||
_animVars.set("isTurningRight", true);
|
||||
_animVars.set("isNotTurning", false);
|
||||
} else {
|
||||
// turning left
|
||||
_animVars.set("isTurningLeft", true);
|
||||
_animVars.set("isNotTurning", false);
|
||||
}
|
||||
} else {
|
||||
// idle
|
||||
}
|
||||
}
|
||||
|
||||
t += deltaTime;
|
||||
}
|
||||
|
||||
if (!_enableRig) {
|
||||
return;
|
||||
if (_enableRig) {
|
||||
bool isMoving = false;
|
||||
auto updateRole = [&](const QString& role, bool isOn) {
|
||||
isMoving = isMoving || isOn;
|
||||
if (isOn) {
|
||||
if (!isRunningRole(role)) {
|
||||
qCDebug(animation) << "Rig STARTING" << role;
|
||||
startAnimationByRole(role);
|
||||
}
|
||||
} else {
|
||||
if (isRunningRole(role)) {
|
||||
qCDebug(animation) << "Rig stopping" << role;
|
||||
stopAnimationByRole(role);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
updateRole("walk", forwardSpeed > 0.01f);
|
||||
updateRole("backup", forwardSpeed < -0.01f);
|
||||
bool isTurning = std::abs(turningSpeed) > 0.5f;
|
||||
updateRole("rightTurn", isTurning && (turningSpeed > 0));
|
||||
updateRole("leftTurn", isTurning && (turningSpeed < 0));
|
||||
bool isStrafing = !isTurning && (std::abs(lateralSpeed) > 0.01f);
|
||||
updateRole("rightStrafe", isStrafing && (lateralSpeed > 0.0f));
|
||||
updateRole("leftStrafe", isStrafing && (lateralSpeed < 0.0f));
|
||||
updateRole("idle", !isMoving); // Must be last, as it makes isMoving bogus.
|
||||
}
|
||||
bool isMoving = false;
|
||||
glm::vec3 front = worldRotation * IDENTITY_FRONT;
|
||||
float forwardSpeed = glm::dot(worldVelocity, front);
|
||||
float rightLateralSpeed = glm::dot(worldVelocity, worldRotation * IDENTITY_RIGHT);
|
||||
float rightTurningSpeed = glm::orientedAngle(front, _lastFront, IDENTITY_UP) / deltaTime;
|
||||
auto updateRole = [&](const QString& role, bool isOn) {
|
||||
isMoving = isMoving || isOn;
|
||||
if (isOn) {
|
||||
if (!isRunningRole(role)) {
|
||||
qCDebug(animation) << "Rig STARTING" << role;
|
||||
startAnimationByRole(role);
|
||||
}
|
||||
} else {
|
||||
if (isRunningRole(role)) {
|
||||
qCDebug(animation) << "Rig stopping" << role;
|
||||
stopAnimationByRole(role);
|
||||
}
|
||||
}
|
||||
};
|
||||
updateRole("walk", forwardSpeed > 0.01f);
|
||||
updateRole("backup", forwardSpeed < -0.01f);
|
||||
bool isTurning = std::abs(rightTurningSpeed) > 0.5f;
|
||||
updateRole("rightTurn", isTurning && (rightTurningSpeed > 0));
|
||||
updateRole("leftTurn", isTurning && (rightTurningSpeed < 0));
|
||||
bool isStrafing = !isTurning && (std::abs(rightLateralSpeed) > 0.01f);
|
||||
updateRole("rightStrafe", isStrafing && (rightLateralSpeed > 0.0f));
|
||||
updateRole("leftStrafe", isStrafing && (rightLateralSpeed < 0.0f));
|
||||
updateRole("idle", !isMoving); // Must be last, as it makes isMoving bogus.
|
||||
|
||||
_lastFront = front;
|
||||
_lastPosition = worldPosition;
|
||||
}
|
||||
|
@ -487,13 +542,6 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
|
|||
setJointRotationInConstrainedFrame((int)i, glm::inverse(_animSkeleton->getRelativeBindPose(i).rot) * poses[i].rot, PRIORITY, false);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
updateJointState(i, rootTransform);
|
||||
}
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
_jointStates[i].resetTransformChanged();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// First normalize the fades so that they sum to 1.0.
|
||||
|
@ -538,13 +586,13 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
|
|||
handle->setMix(mix);
|
||||
handle->simulate(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
updateJointState(i, rootTransform);
|
||||
}
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
_jointStates[i].resetTransformChanged();
|
||||
}
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
updateJointState(i, rootTransform);
|
||||
}
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
_jointStates[i].resetTransformChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,12 @@
|
|||
"interpTarget": 6,
|
||||
"interpDuration": 6,
|
||||
"transitions": [
|
||||
{ "var": "isMoving", "state": "walkFwd" }
|
||||
{ "var": "isMovingForward", "state": "walkFwd" },
|
||||
{ "var": "isMovingBackward", "state": "walkBwd" },
|
||||
{ "var": "isMovingRight", "state": "strafeRight" },
|
||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||
{ "var": "isTurningRight", "state": "turnRight" },
|
||||
{ "var": "isTurningLeft", "state": "turnLeft" }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -19,7 +24,77 @@
|
|||
"interpTarget": 6,
|
||||
"interpDuration": 6,
|
||||
"transitions": [
|
||||
{ "var": "isNotMoving", "state": "idle" }
|
||||
{ "var": "isNotMoving", "state": "idle" },
|
||||
{ "var": "isMovingBackward", "state": "walkBwd" },
|
||||
{ "var": "isMovingRight", "state": "strafeRight" },
|
||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||
{ "var": "isTurningRight", "state": "turnRight" },
|
||||
{ "var": "isTurningLeft", "state": "turnLeft" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "walkBwd",
|
||||
"interpTarget": 6,
|
||||
"interpDuration": 6,
|
||||
"transitions": [
|
||||
{ "var": "isNotMoving", "state": "idle" },
|
||||
{ "var": "isMovingForward", "state": "walkFwd" },
|
||||
{ "var": "isMovingRight", "state": "strafeRight" },
|
||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||
{ "var": "isTurningRight", "state": "turnRight" },
|
||||
{ "var": "isTurningLeft", "state": "turnLeft" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "strafeRight",
|
||||
"interpTarget": 6,
|
||||
"interpDuration": 6,
|
||||
"transitions": [
|
||||
{ "var": "isNotMoving", "state": "idle" },
|
||||
{ "var": "isMovingForward", "state": "walkFwd" },
|
||||
{ "var": "isMovingBackward", "state": "walkBwd" },
|
||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||
{ "var": "isTurningRight", "state": "turnRight" },
|
||||
{ "var": "isTurningLeft", "state": "turnLeft" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "strafeLeft",
|
||||
"interpTarget": 6,
|
||||
"interpDuration": 6,
|
||||
"transitions": [
|
||||
{ "var": "isNotMoving", "state": "idle" },
|
||||
{ "var": "isMovingForward", "state": "walkFwd" },
|
||||
{ "var": "isMovingBackward", "state": "walkBwd" },
|
||||
{ "var": "isMovingRight", "state": "strafeRight" },
|
||||
{ "var": "isTurningRight", "state": "turnRight" },
|
||||
{ "var": "isTurningLeft", "state": "turnLeft" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "turnRight",
|
||||
"interpTarget": 6,
|
||||
"interpDuration": 6,
|
||||
"transitions": [
|
||||
{ "var": "isNotTurning", "state": "idle" },
|
||||
{ "var": "isMovingForward", "state": "walkFwd" },
|
||||
{ "var": "isMovingBackward", "state": "walkBwd" },
|
||||
{ "var": "isMovingRight", "state": "strafeRight" },
|
||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||
{ "var": "isTurningLeft", "state": "turnLeft" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "turnLeft",
|
||||
"interpTarget": 6,
|
||||
"interpDuration": 6,
|
||||
"transitions": [
|
||||
{ "var": "isNotTurning", "state": "idle" },
|
||||
{ "var": "isMovingForward", "state": "walkFwd" },
|
||||
{ "var": "isMovingBackward", "state": "walkBwd" },
|
||||
{ "var": "isMovingRight", "state": "strafeRight" },
|
||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||
{ "var": "isTurningRight", "state": "turnRight" }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -45,7 +120,8 @@
|
|||
"startFrame": 0.0,
|
||||
"endFrame": 35.0,
|
||||
"timeScale": 1.0,
|
||||
"loopFlag": true
|
||||
"loopFlag": true,
|
||||
"timeScaleVar": "walkTimeScale"
|
||||
},
|
||||
"children": []
|
||||
},
|
||||
|
@ -57,7 +133,8 @@
|
|||
"startFrame": 0.0,
|
||||
"endFrame": 37.0,
|
||||
"timeScale": 1.0,
|
||||
"loopFlag": true
|
||||
"loopFlag": true,
|
||||
"timeScaleVar": "walkTimeScale"
|
||||
},
|
||||
"children": []
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue