mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-09 13:12:40 +02:00
Improved state machine for right hand.
The hand state machine has the following features * There's a idle to point animation, followed by a looping point hold state. * There's a point to idle animation. * The grab state is composed of a linear blend between an open and closed pose. Additionally the C++ code will ramp on the left and right hand overlays, This allows the fingers to be animated normally when the user is not actively pointing or grabbing.
This commit is contained in:
parent
90f46ba2c8
commit
1948829ca8
5 changed files with 144 additions and 81 deletions
|
@ -1296,10 +1296,13 @@ void MyAvatar::initAnimGraph() {
|
|||
// ik-avatar.json
|
||||
// https://gist.github.com/hyperlogic/e58e0a24cc341ad5d060
|
||||
//
|
||||
// ik-avatar-hands.json
|
||||
// https://gist.githubusercontent.com/hyperlogic/04a02c47eb56d8bfaebb
|
||||
//
|
||||
// or run a local web-server
|
||||
// python -m SimpleHTTPServer&
|
||||
auto graphUrl = QUrl("http://localhost:8000/avatar.json");
|
||||
//auto graphUrl = QUrl("https://gist.githubusercontent.com/hyperlogic/e58e0a24cc341ad5d060/raw/8f824da2908fd89ad1befadd1d8f5d7b3b6efa66/ik-avatar.json");
|
||||
//auto graphUrl = QUrl("http://localhost:8000/avatar.json");
|
||||
auto graphUrl = QUrl("https://gist.githubusercontent.com/hyperlogic/04a02c47eb56d8bfaebb/raw/883c7ce8e75ad3f72a0d513c317fe4b74a41c3b8/ik-avatar-hands.json");
|
||||
_rig->initAnimGraph(graphUrl, _skeletonModel.getGeometry()->getFBXGeometry());
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
headParams.leftEyeJointIndex = geometry.leftEyeJointIndex;
|
||||
headParams.rightEyeJointIndex = geometry.rightEyeJointIndex;
|
||||
|
||||
_rig->updateFromHeadParameters(headParams);
|
||||
_rig->updateFromHeadParameters(headParams, deltaTime);
|
||||
|
||||
Rig::HandParameters handParams;
|
||||
|
||||
|
@ -171,7 +171,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
handParams.isRightEnabled = false;
|
||||
}
|
||||
|
||||
_rig->updateFromHandParameters(handParams);
|
||||
_rig->updateFromHandParameters(handParams, deltaTime);
|
||||
|
||||
} else {
|
||||
// This is a little more work than we really want.
|
||||
|
|
|
@ -952,7 +952,7 @@ glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) {
|
|||
return _jointStates[jointIndex].getDefaultRotationInParentFrame();
|
||||
}
|
||||
|
||||
void Rig::updateFromHeadParameters(const HeadParameters& params) {
|
||||
void Rig::updateFromHeadParameters(const HeadParameters& params, float dt) {
|
||||
if (params.enableLean) {
|
||||
updateLeanJoint(params.leanJointIndex, params.leanSideways, params.leanForward, params.torsoTwist);
|
||||
}
|
||||
|
@ -1048,59 +1048,49 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm
|
|||
}
|
||||
}
|
||||
|
||||
void Rig::updateFromHandParameters(const HandParameters& params) {
|
||||
void Rig::updateFromHandParameters(const HandParameters& params, float dt) {
|
||||
|
||||
if (_enableAnimGraph && _animSkeleton) {
|
||||
|
||||
// AJT: TODO rotate these into the correct coordinate space
|
||||
/*
|
||||
if (params.isLeftEnabled) {
|
||||
auto rootTrans = _animSkeleton->getAbsoluteBindPose(_rootJointIndex).trans;
|
||||
_animVars.set("leftHandPosition", params.leftPosition + rootTrans);
|
||||
_animVars.set("leftHandRotation", params.leftOrientation);
|
||||
} else {
|
||||
_animVars.unset("leftHandPosition");
|
||||
_animVars.unset("leftHandRotation");
|
||||
}
|
||||
|
||||
if (params.isRightEnabled) {
|
||||
auto rootTrans = _animSkeleton->getAbsoluteBindPose(_rootJointIndex).trans;
|
||||
_animVars.set("rightHandPosition", params.rightPosition + rootTrans);
|
||||
_animVars.set("rightHandRotation", params.rightOrientation);
|
||||
} else {
|
||||
_animVars.unset("rightHandPosition");
|
||||
_animVars.unset("rightHandRotation");
|
||||
}
|
||||
*/
|
||||
|
||||
// AJT: REMOVE for grab/point debugging.
|
||||
// set leftHand grab vars
|
||||
_animVars.set("isLeftHandIdle", false);
|
||||
_animVars.set("isLeftHandPoint", false);
|
||||
_animVars.set("isLeftHandClose", false);
|
||||
if (params.leftTrigger > 0.3333f) {
|
||||
if (params.leftTrigger > 0.6666f) {
|
||||
_animVars.set("isLeftHandClose", true);
|
||||
} else {
|
||||
_animVars.set("isLeftHandPoint", true);
|
||||
}
|
||||
_animVars.set("isLeftHandGrab", false);
|
||||
|
||||
// Split the trigger range into three zones.
|
||||
bool rampOut = false;
|
||||
if (params.leftTrigger > 0.6666f) {
|
||||
_animVars.set("isLeftHandGrab", true);
|
||||
} else if (params.leftTrigger > 0.3333f) {
|
||||
_animVars.set("isLeftHandPoint", true);
|
||||
} else {
|
||||
_animVars.set("isLeftHandIdle", true);
|
||||
rampOut = true;
|
||||
}
|
||||
const float OVERLAY_RAMP_OUT_SPEED = 6.0f; // ramp in and out over 1/6th of a sec
|
||||
_leftHandOverlayAlpha = glm::clamp(_leftHandOverlayAlpha + (rampOut ? -1.0f : 1.0f) * OVERLAY_RAMP_OUT_SPEED * dt, 0.0f, 1.0f);
|
||||
_animVars.set("leftHandOverlayAlpha", _leftHandOverlayAlpha);
|
||||
_animVars.set("leftHandGrabBlend", params.leftTrigger);
|
||||
|
||||
// AJT: REMOVE for grab/point debugging.
|
||||
|
||||
// set leftHand grab vars
|
||||
_animVars.set("isRightHandIdle", false);
|
||||
_animVars.set("isRightHandPoint", false);
|
||||
_animVars.set("isRightHandClose", false);
|
||||
if (params.rightTrigger > 0.3333f) {
|
||||
if (params.rightTrigger > 0.6666f) {
|
||||
_animVars.set("isRightHandClose", true);
|
||||
} else {
|
||||
_animVars.set("isRightHandPoint", true);
|
||||
}
|
||||
_animVars.set("isRightHandGrab", false);
|
||||
|
||||
// Split the trigger range into three zones
|
||||
rampOut = false;
|
||||
if (params.rightTrigger > 0.6666f) {
|
||||
_animVars.set("isRightHandGrab", true);
|
||||
} else if (params.rightTrigger > 0.3333f) {
|
||||
_animVars.set("isRightHandPoint", true);
|
||||
} else {
|
||||
_animVars.set("isRightHandIdle", true);
|
||||
rampOut = true;
|
||||
}
|
||||
|
||||
_rightHandOverlayAlpha = glm::clamp(_rightHandOverlayAlpha + (rampOut ? -1.0f : 1.0f) * OVERLAY_RAMP_OUT_SPEED * dt, 0.0f, 1.0f);
|
||||
_animVars.set("rightHandOverlayAlpha", _rightHandOverlayAlpha);
|
||||
_animVars.set("rightHandGrabBlend", params.rightTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -179,11 +179,11 @@ public:
|
|||
void setEnableAnimGraph(bool isEnabled) { _enableAnimGraph = isEnabled; }
|
||||
bool getEnableAnimGraph() const { return _enableAnimGraph; }
|
||||
|
||||
void updateFromHeadParameters(const HeadParameters& params);
|
||||
void updateFromHeadParameters(const HeadParameters& params, float dt);
|
||||
void updateEyeJoints(int leftEyeIndex, int rightEyeIndex, const glm::vec3& modelTranslation, const glm::quat& modelRotation,
|
||||
const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade = glm::vec3(0.0f));
|
||||
|
||||
void updateFromHandParameters(const HandParameters& params);
|
||||
void updateFromHandParameters(const HandParameters& params, float dt);
|
||||
|
||||
virtual void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation,
|
||||
float scale, float priority) = 0;
|
||||
|
@ -228,6 +228,8 @@ public:
|
|||
Move
|
||||
};
|
||||
RigRole _state = RigRole::Idle;
|
||||
float _leftHandOverlayAlpha = 0.0f;
|
||||
float _rightHandOverlayAlpha = 0.0f;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__Rig__) */
|
||||
|
|
|
@ -56,7 +56,8 @@
|
|||
"type": "overlay",
|
||||
"data": {
|
||||
"alpha": 1.0,
|
||||
"boneSet": "rightHand"
|
||||
"boneSet": "rightHand",
|
||||
"alphaVar": "rightHandOverlayAlpha"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
|
@ -67,29 +68,49 @@
|
|||
"states": [
|
||||
{
|
||||
"id": "rightHandIdle",
|
||||
"interpTarget": 6,
|
||||
"interpDuration": 6,
|
||||
"interpTarget": 3,
|
||||
"interpDuration": 3,
|
||||
"transitions": [
|
||||
{ "var": "isRightHandPoint", "state": "rightHandPoint" },
|
||||
{ "var": "isRightHandClose", "state": "rightHandClose" }
|
||||
{ "var": "isRightHandPoint", "state": "rightHandPointIntro" },
|
||||
{ "var": "isRightHandGrab", "state": "rightHandGrab" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "rightHandPoint",
|
||||
"interpTarget": 6,
|
||||
"interpDuration": 6,
|
||||
"id": "rightHandPointIntro",
|
||||
"interpTarget": 3,
|
||||
"interpDuration": 3,
|
||||
"transitions": [
|
||||
{ "var": "isRightHandIdle", "state": "rightHandIdle" },
|
||||
{ "var": "isRightHandClose", "state": "rightHandClose" }
|
||||
{ "var": "isRightHandPointIntroOnDone", "state": "rightHandPointHold" },
|
||||
{ "var": "isRightHandGrab", "state": "rightHandGrab" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "rightHandClose",
|
||||
"interpTarget": 6,
|
||||
"interpDuration": 6,
|
||||
"id": "rightHandPointHold",
|
||||
"interpTarget": 3,
|
||||
"interpDuration": 3,
|
||||
"transitions": [
|
||||
{ "var": "isRightHandIdle", "state": "rightHandPointOutro" },
|
||||
{ "var": "isRightHandGrab", "state": "rightHandGrab" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "rightHandPointOutro",
|
||||
"interpTarget": 3,
|
||||
"interpDuration": 3,
|
||||
"transitions": [
|
||||
{ "var": "isRightHandPointOutroOnDone", "state": "rightHandIdle" },
|
||||
{ "var": "isRightHandGrab", "state": "rightHandGrab" },
|
||||
{ "var": "isRightHandPoint", "state": "rightHandPointHold" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "rightHandGrab",
|
||||
"interpTarget": 3,
|
||||
"interpDuration": 3,
|
||||
"transitions": [
|
||||
{ "var": "isRightHandIdle", "state": "rightHandIdle" },
|
||||
{ "var": "isRightHandPoint", "state": "rightHandPoint" }
|
||||
{ "var": "isRightHandPoint_DISABLED", "state": "rightHandPointHold" }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -99,19 +120,7 @@
|
|||
"id": "rightHandIdle",
|
||||
"type": "clip",
|
||||
"data": {
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/right_hand_anim.fbx",
|
||||
"startFrame": 30.0,
|
||||
"endFrame": 30.0,
|
||||
"timeScale": 1.0,
|
||||
"loopFlag": true
|
||||
},
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"id": "rightHandPoint",
|
||||
"type": "clip",
|
||||
"data": {
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/right_hand_anim.fbx",
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/right_hand_point.fbx",
|
||||
"startFrame": 0.0,
|
||||
"endFrame": 0.0,
|
||||
"timeScale": 1.0,
|
||||
|
@ -120,16 +129,74 @@
|
|||
"children": []
|
||||
},
|
||||
{
|
||||
"id": "rightHandClose",
|
||||
"id": "rightHandPointHold",
|
||||
"type": "clip",
|
||||
"data": {
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/right_hand_anim.fbx",
|
||||
"startFrame": 15.0,
|
||||
"endFrame": 15.0,
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/right_hand_point.fbx",
|
||||
"startFrame": 12.0,
|
||||
"endFrame": 12.0,
|
||||
"timeScale": 1.0,
|
||||
"loopFlag": true
|
||||
},
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"id": "rightHandPointIntro",
|
||||
"type": "clip",
|
||||
"data": {
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/right_hand_point.fbx",
|
||||
"startFrame": 0.0,
|
||||
"endFrame": 12.0,
|
||||
"timeScale": 1.0,
|
||||
"loopFlag": false
|
||||
},
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"id": "rightHandPointOutro",
|
||||
"type": "clip",
|
||||
"data": {
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/right_hand_point.fbx",
|
||||
"startFrame": 0.0,
|
||||
"endFrame": 65.0,
|
||||
"timeScale": 1.0,
|
||||
"loopFlag": false
|
||||
},
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"id": "rightHandGrab",
|
||||
"type": "blendLinear",
|
||||
"data": {
|
||||
"alpha": 0.0,
|
||||
"alphaVar": "rightHandGrabBlend"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "rightHandOpen",
|
||||
"type": "clip",
|
||||
"data": {
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/right_hand_point.fbx",
|
||||
"startFrame": 0.0,
|
||||
"endFrame": 0.0,
|
||||
"timeScale": 1.0,
|
||||
"loopFlag": true
|
||||
},
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"id": "rightHandClose",
|
||||
"type": "clip",
|
||||
"data": {
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/right_hand_anim.fbx",
|
||||
"startFrame": 15.0,
|
||||
"endFrame": 15.0,
|
||||
"timeScale": 1.0,
|
||||
"loopFlag": true
|
||||
},
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -138,7 +205,8 @@
|
|||
"type": "overlay",
|
||||
"data": {
|
||||
"alpha": 1.0,
|
||||
"boneSet": "leftHand"
|
||||
"boneSet": "leftHand",
|
||||
"alphaVar" : "leftHandOverlay"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
|
@ -153,7 +221,7 @@
|
|||
"interpDuration": 6,
|
||||
"transitions": [
|
||||
{ "var": "isLeftHandPoint", "state": "leftHandPoint" },
|
||||
{ "var": "isLeftHandClose", "state": "leftHandClose" }
|
||||
{ "var": "isLeftHandGrab", "state": "leftHandGrab" }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -162,11 +230,11 @@
|
|||
"interpDuration": 6,
|
||||
"transitions": [
|
||||
{ "var": "isLeftHandIdle", "state": "leftHandIdle" },
|
||||
{ "var": "isLeftHandClose", "state": "leftHandClose" }
|
||||
{ "var": "isLeftHandGrab", "state": "leftHandGrab" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "leftHandClose",
|
||||
"id": "leftHandGrab",
|
||||
"interpTarget": 6,
|
||||
"interpDuration": 6,
|
||||
"transitions": [
|
||||
|
@ -202,7 +270,7 @@
|
|||
"children": []
|
||||
},
|
||||
{
|
||||
"id": "leftHandClose",
|
||||
"id": "leftHandGrab",
|
||||
"type": "clip",
|
||||
"data": {
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/left_hand_anim.fbx",
|
||||
|
|
Loading…
Reference in a new issue