From 90f46ba2c8bb64538270d71cf4fd6a53559b1cf6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 14 Sep 2015 18:54:12 -0700 Subject: [PATCH 1/3] Added hand state machines to AnimGraph. * Application: Forward trigger values to the MyAvatar's PalmData * SkeletonModel: Pass PalmData to Rig via updateRigFromHandData() this is more explicit then the Rig::inverseKinematics methods. * AnimNodeLoader & AnimOverlay: add support for LeftHand and RightHand bone sets * Rig::updateRigFromHandData() read the triggers and set stateMachine trigger vars * avatar.json - udpated with new hand state machine with temporary animations --- interface/src/Application.cpp | 7 +- interface/src/Application.h | 2 +- interface/src/avatar/MyAvatar.cpp | 4 +- interface/src/avatar/SkeletonModel.cpp | 79 ++- .../animation/src/AnimInverseKinematics.cpp | 2 +- libraries/animation/src/AnimNodeLoader.cpp | 13 +- libraries/animation/src/AnimOverlay.cpp | 42 +- libraries/animation/src/AnimOverlay.h | 10 +- libraries/animation/src/Rig.cpp | 56 ++ libraries/animation/src/Rig.h | 13 + tests/animation/src/data/avatar.json | 516 ++++++++++++------ 11 files changed, 525 insertions(+), 219 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 164f04f2eb..3a44562e51 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2868,8 +2868,8 @@ void Application::update(float deltaTime) { UserInputMapper::PoseValue leftHand = userInputMapper->getPoseState(UserInputMapper::LEFT_HAND); UserInputMapper::PoseValue rightHand = userInputMapper->getPoseState(UserInputMapper::RIGHT_HAND); Hand* hand = DependencyManager::get()->getMyAvatar()->getHand(); - setPalmData(hand, leftHand, deltaTime, LEFT_HAND_INDEX); - setPalmData(hand, rightHand, deltaTime, RIGHT_HAND_INDEX); + setPalmData(hand, leftHand, deltaTime, LEFT_HAND_INDEX, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK)); + setPalmData(hand, rightHand, deltaTime, RIGHT_HAND_INDEX, userInputMapper->getActionState(UserInputMapper::RIGHT_HAND_CLICK)); if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) { emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK), userInputMapper->getActionState(UserInputMapper::SHIFT), LEFT_HAND_INDEX); @@ -4970,7 +4970,7 @@ mat4 Application::getHMDSensorPose() const { return mat4(); } -void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index) { +void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index, float triggerValue) { PalmData* palm; bool foundHand = false; for (size_t j = 0; j < hand->getNumPalms(); j++) { @@ -5040,6 +5040,7 @@ void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float palm->setTipVelocity(glm::vec3(0.0f)); } palm->setTipPosition(newTipPosition); + palm->setTrigger(triggerValue); } void Application::emulateMouse(Hand* hand, float click, float shift, int index) { diff --git a/interface/src/Application.h b/interface/src/Application.h index b997fae823..6213dae4fa 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -485,7 +485,7 @@ private: void update(float deltaTime); - void setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index); + void setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index, float triggerValue); void emulateMouse(Hand* hand, float click, float shift, int index); // Various helper functions called during update() diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9496c60d26..91e7ba191f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1298,8 +1298,8 @@ void MyAvatar::initAnimGraph() { // // 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/e58e0a24cc341ad5d060/raw/8f824da2908fd89ad1befadd1d8f5d7b3b6efa66/ik-avatar.json"); _rig->initAnimGraph(graphUrl, _skeletonModel.getGeometry()->getFBXGeometry()); } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 41ca193a7a..91222ad30e 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -96,6 +96,17 @@ void SkeletonModel::initJointStates(QVector states) { emit skeletonLoaded(); } +static const PalmData* getPalmWithIndex(Hand* hand, int index) { + const PalmData* palm = nullptr; + for (size_t j = 0; j < hand->getNumPalms(); j++) { + if (hand->getPalms()[j].getSixenseID() == index) { + palm = &(hand->getPalms()[j]); + break; + } + } + return palm; +} + const float PALM_PRIORITY = DEFAULT_PRIORITY; // Called within Model::simulate call, below. void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { @@ -108,34 +119,60 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { MyAvatar* myAvatar = static_cast(_owningAvatar); const FBXGeometry& geometry = _geometry->getFBXGeometry(); - Rig::HeadParameters params; - params.modelRotation = getRotation(); - params.modelTranslation = getTranslation(); - params.enableLean = qApp->getAvatarUpdater()->isHMDMode() && !myAvatar->getStandingHMDSensorMode(); - params.leanSideways = head->getFinalLeanSideways(); - params.leanForward = head->getFinalLeanForward(); - params.torsoTwist = head->getTorsoTwist(); - params.localHeadOrientation = head->getFinalOrientationInLocalFrame(); - params.localHeadPitch = head->getFinalPitch(); - params.localHeadYaw = head->getFinalYaw(); - params.localHeadRoll = head->getFinalRoll(); - params.isInHMD = qApp->getAvatarUpdater()->isHMDMode(); + Rig::HeadParameters headParams; + headParams.modelRotation = getRotation(); + headParams.modelTranslation = getTranslation(); + headParams.enableLean = qApp->getAvatarUpdater()->isHMDMode() && !myAvatar->getStandingHMDSensorMode(); + headParams.leanSideways = head->getFinalLeanSideways(); + headParams.leanForward = head->getFinalLeanForward(); + headParams.torsoTwist = head->getTorsoTwist(); + headParams.localHeadOrientation = head->getFinalOrientationInLocalFrame(); + headParams.localHeadPitch = head->getFinalPitch(); + headParams.localHeadYaw = head->getFinalYaw(); + headParams.localHeadRoll = head->getFinalRoll(); + headParams.isInHMD = qApp->getAvatarUpdater()->isHMDMode(); // get HMD position from sensor space into world space, and back into model space glm::mat4 worldToModel = glm::inverse(createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition())); glm::vec3 yAxis(0.0f, 1.0f, 0.0f); glm::vec3 hmdPosition = glm::angleAxis((float)M_PI, yAxis) * transformPoint(worldToModel * myAvatar->getSensorToWorldMatrix(), myAvatar->getHMDSensorPosition()); - params.localHeadPosition = hmdPosition; + headParams.localHeadPosition = hmdPosition; - params.worldHeadOrientation = head->getFinalOrientationInWorldFrame(); - params.eyeLookAt = head->getLookAtPosition(); - params.eyeSaccade = head->getSaccade(); - params.leanJointIndex = geometry.leanJointIndex; - params.neckJointIndex = geometry.neckJointIndex; - params.leftEyeJointIndex = geometry.leftEyeJointIndex; - params.rightEyeJointIndex = geometry.rightEyeJointIndex; + headParams.worldHeadOrientation = head->getFinalOrientationInWorldFrame(); + headParams.eyeLookAt = head->getLookAtPosition(); + headParams.eyeSaccade = head->getSaccade(); + headParams.leanJointIndex = geometry.leanJointIndex; + headParams.neckJointIndex = geometry.neckJointIndex; + headParams.leftEyeJointIndex = geometry.leftEyeJointIndex; + headParams.rightEyeJointIndex = geometry.rightEyeJointIndex; + + _rig->updateFromHeadParameters(headParams); + + Rig::HandParameters handParams; + + // this is sooo getto + const PalmData* leftPalm = getPalmWithIndex(myAvatar->getHand(), LEFT_HAND_INDEX); + if (leftPalm && leftPalm->isActive()) { + handParams.isLeftEnabled = true; + handParams.leftPosition = leftPalm->getRawPosition(); + handParams.leftOrientation = leftPalm->getRawRotation(); + handParams.leftTrigger = leftPalm->getTrigger(); + } else { + handParams.isLeftEnabled = false; + } + + const PalmData* rightPalm = getPalmWithIndex(myAvatar->getHand(), RIGHT_HAND_INDEX); + if (rightPalm && rightPalm->isActive()) { + handParams.isRightEnabled = true; + handParams.rightPosition = rightPalm->getRawPosition(); + handParams.rightOrientation = rightPalm->getRawRotation(); + handParams.rightTrigger = rightPalm->getTrigger(); + } else { + handParams.isRightEnabled = false; + } + + _rig->updateFromHandParameters(handParams); - _rig->updateFromHeadParameters(params); } else { // This is a little more work than we really want. // diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 87eae99f5d..b2c4b6401c 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -342,7 +342,7 @@ void AnimInverseKinematics::initConstraints() { // compute corresponding absolute poses int numJoints = (int)_defaultRelativePoses.size(); AnimPoseVec absolutePoses; - absolutePoses.reserve(numJoints); + absolutePoses.resize(numJoints); for (int i = 0; i < numJoints; ++i) { int parentIndex = _skeleton->getParentIndex(i); if (parentIndex < 0) { diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index aa58845f01..9d6eb12e44 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -172,7 +172,12 @@ static AnimNode::Pointer loadNode(const QJsonObject& jsonObj, const QUrl& jsonUr qCCritical(animation) << "AnimNodeLoader, bad object in \"children\", id =" << id << ", url =" << jsonUrl.toDisplayString(); return nullptr; } - node->addChild(loadNode(childValue.toObject(), jsonUrl)); + AnimNode::Pointer child = loadNode(childValue.toObject(), jsonUrl); + if (child) { + node->addChild(child); + } else { + return nullptr; + } } if ((animNodeTypeToProcessFunc(type))(node, dataObj, id, jsonUrl)) { @@ -232,13 +237,15 @@ static const char* boneSetStrings[AnimOverlay::NumBoneSets] = { "fullBody", "upperBody", "lowerBody", - "rightArm", "leftArm", + "rightArm", "aboveTheHead", "belowTheHead", "headOnly", "spineOnly", - "empty" + "empty", + "leftHand", + "rightHand" }; static AnimOverlay::BoneSet stringToBoneSetEnum(const QString& str) { diff --git a/libraries/animation/src/AnimOverlay.cpp b/libraries/animation/src/AnimOverlay.cpp index 52026f7711..1a0a16ca8a 100644 --- a/libraries/animation/src/AnimOverlay.cpp +++ b/libraries/animation/src/AnimOverlay.cpp @@ -26,12 +26,14 @@ void AnimOverlay::buildBoneSet(BoneSet boneSet) { case FullBodyBoneSet: buildFullBodyBoneSet(); break; case UpperBodyBoneSet: buildUpperBodyBoneSet(); break; case LowerBodyBoneSet: buildLowerBodyBoneSet(); break; - case RightArmBoneSet: buildRightArmBoneSet(); break; case LeftArmBoneSet: buildLeftArmBoneSet(); break; + case RightArmBoneSet: buildRightArmBoneSet(); break; case AboveTheHeadBoneSet: buildAboveTheHeadBoneSet(); break; case BelowTheHeadBoneSet: buildBelowTheHeadBoneSet(); break; case HeadOnlyBoneSet: buildHeadOnlyBoneSet(); break; case SpineOnlyBoneSet: buildSpineOnlyBoneSet(); break; + case LeftHandBoneSet: buildLeftHandBoneSet(); break; + case RightHandBoneSet: buildRightHandBoneSet(); break; default: case EmptyBoneSet: buildEmptyBoneSet(); break; } @@ -110,15 +112,6 @@ void AnimOverlay::buildLowerBodyBoneSet() { _boneSetVec[hipsJoint] = 0.0f; } -void AnimOverlay::buildRightArmBoneSet() { - assert(_skeleton); - buildEmptyBoneSet(); - int rightShoulderJoint = _skeleton->nameToJointIndex("RightShoulder"); - for_each_child_joint(_skeleton, rightShoulderJoint, [&](int i) { - _boneSetVec[i] = 1.0f; - }); -} - void AnimOverlay::buildLeftArmBoneSet() { assert(_skeleton); buildEmptyBoneSet(); @@ -128,6 +121,15 @@ void AnimOverlay::buildLeftArmBoneSet() { }); } +void AnimOverlay::buildRightArmBoneSet() { + assert(_skeleton); + buildEmptyBoneSet(); + int rightShoulderJoint = _skeleton->nameToJointIndex("RightShoulder"); + for_each_child_joint(_skeleton, rightShoulderJoint, [&](int i) { + _boneSetVec[i] = 1.0f; + }); +} + void AnimOverlay::buildAboveTheHeadBoneSet() { assert(_skeleton); buildEmptyBoneSet(); @@ -168,13 +170,31 @@ void AnimOverlay::buildEmptyBoneSet() { } } +void AnimOverlay::buildLeftHandBoneSet() { + assert(_skeleton); + buildEmptyBoneSet(); + int headJoint = _skeleton->nameToJointIndex("LeftHand"); + for_each_child_joint(_skeleton, headJoint, [&](int i) { + _boneSetVec[i] = 1.0f; + }); +} + +void AnimOverlay::buildRightHandBoneSet() { + assert(_skeleton); + buildEmptyBoneSet(); + int headJoint = _skeleton->nameToJointIndex("RightHand"); + for_each_child_joint(_skeleton, headJoint, [&](int i) { + _boneSetVec[i] = 1.0f; + }); +} + // for AnimDebugDraw rendering const AnimPoseVec& AnimOverlay::getPosesInternal() const { return _poses; } void AnimOverlay::setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) { - _skeleton = skeleton; + AnimNode::setSkeletonInternal(skeleton); // we have to re-build the bone set when the skeleton changes. buildBoneSet(_boneSet); diff --git a/libraries/animation/src/AnimOverlay.h b/libraries/animation/src/AnimOverlay.h index de563cc403..2a87c54997 100644 --- a/libraries/animation/src/AnimOverlay.h +++ b/libraries/animation/src/AnimOverlay.h @@ -28,14 +28,16 @@ public: FullBodyBoneSet = 0, UpperBodyBoneSet, LowerBodyBoneSet, - RightArmBoneSet, LeftArmBoneSet, + RightArmBoneSet, AboveTheHeadBoneSet, BelowTheHeadBoneSet, HeadOnlyBoneSet, SpineOnlyBoneSet, EmptyBoneSet, - NumBoneSets, + LeftHandBoneSet, + RightHandBoneSet, + NumBoneSets }; AnimOverlay(const std::string& id, BoneSet boneSet, float alpha); @@ -64,13 +66,15 @@ public: void buildFullBodyBoneSet(); void buildUpperBodyBoneSet(); void buildLowerBodyBoneSet(); - void buildRightArmBoneSet(); void buildLeftArmBoneSet(); + void buildRightArmBoneSet(); void buildAboveTheHeadBoneSet(); void buildBelowTheHeadBoneSet(); void buildHeadOnlyBoneSet(); void buildSpineOnlyBoneSet(); void buildEmptyBoneSet(); + void buildLeftHandBoneSet(); + void buildRightHandBoneSet(); // no copies AnimOverlay(const AnimOverlay&) = delete; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 3729dc8ca7..6baae8fa3e 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1048,6 +1048,62 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm } } +void Rig::updateFromHandParameters(const HandParameters& params) { + + 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. + _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); + } + } else { + _animVars.set("isLeftHandIdle", true); + } + + // AJT: REMOVE for grab/point debugging. + _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); + } + } else { + _animVars.set("isRightHandIdle", true); + } + + } +} + void Rig::initAnimGraph(const QUrl& url, const FBXGeometry& fbxGeometry) { if (!_enableAnimGraph) { return; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 18e888d2b0..f57b446417 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -76,6 +76,17 @@ public: void dump() const; }; + struct HandParameters { + bool isLeftEnabled; + bool isRightEnabled; + glm::vec3 leftPosition = glm::vec3(); + glm::quat leftOrientation = glm::quat(); + glm::vec3 rightPosition = glm::vec3(); + glm::quat rightOrientation = glm::quat(); + float leftTrigger = 0.0f; + float rightTrigger = 0.0f; + }; + virtual ~Rig() {} RigPointer getRigPointer() { return shared_from_this(); } @@ -172,6 +183,8 @@ public: 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); + virtual void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, float scale, float priority) = 0; diff --git a/tests/animation/src/data/avatar.json b/tests/animation/src/data/avatar.json index 08425201b0..1348824ba0 100644 --- a/tests/animation/src/data/avatar.json +++ b/tests/animation/src/data/avatar.json @@ -52,190 +52,358 @@ "children": [] }, { - "id": "mainStateMachine", - "type": "stateMachine", + "id": "rightHandOverlay", + "type": "overlay", "data": { - "currentState": "idle", - "states": [ - { - "id": "idle", - "interpTarget": 6, - "interpDuration": 6, - "transitions": [ - { "var": "isMovingForward", "state": "walkFwd" }, - { "var": "isMovingBackward", "state": "walkBwd" }, - { "var": "isMovingRight", "state": "strafeRight" }, - { "var": "isMovingLeft", "state": "strafeLeft" }, - { "var": "isTurningRight", "state": "turnRight" }, - { "var": "isTurningLeft", "state": "turnLeft" } - ] - }, - { - "id": "walkFwd", - "interpTarget": 6, - "interpDuration": 6, - "transitions": [ - { "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" } - ] - } - ] + "alpha": 1.0, + "boneSet": "rightHand" }, "children": [ { - "id": "idle", - "type": "clip", + "id": "rightHandStateMachine", + "type": "stateMachine", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx", - "startFrame": 0.0, - "endFrame": 90.0, - "timeScale": 1.0, - "loopFlag": true + "currentState": "rightHandIdle", + "states": [ + { + "id": "rightHandIdle", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isRightHandPoint", "state": "rightHandPoint" }, + { "var": "isRightHandClose", "state": "rightHandClose" } + ] + }, + { + "id": "rightHandPoint", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isRightHandIdle", "state": "rightHandIdle" }, + { "var": "isRightHandClose", "state": "rightHandClose" } + ] + }, + { + "id": "rightHandClose", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isRightHandIdle", "state": "rightHandIdle" }, + { "var": "isRightHandPoint", "state": "rightHandPoint" } + ] + } + ] }, - "children": [] + "children": [ + { + "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", + "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": [] + } + ] }, { - "id": "walkFwd", - "type": "clip", + "id": "leftHandOverlay", + "type": "overlay", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_fwd.fbx", - "startFrame": 0.0, - "endFrame": 35.0, - "timeScale": 1.0, - "loopFlag": true, - "timeScaleVar": "walkTimeScale" + "alpha": 1.0, + "boneSet": "leftHand" }, - "children": [] - }, - { - "id": "walkBwd", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_bwd.fbx", - "startFrame": 0.0, - "endFrame": 37.0, - "timeScale": 1.0, - "loopFlag": true, - "timeScaleVar": "walkTimeScale" - }, - "children": [] - }, - { - "id": "turnLeft", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_left.fbx", - "startFrame": 0.0, - "endFrame": 28.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] - }, - { - "id": "turnRight", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_right.fbx", - "startFrame": 0.0, - "endFrame": 30.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] - }, - { - "id": "strafeLeft", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/strafe_left.fbx", - "startFrame": 0.0, - "endFrame": 31.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] - }, - { - "id": "strafeRight", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/strafe_right.fbx", - "startFrame": 0.0, - "endFrame": 31.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] + "children": [ + { + "id": "leftHandStateMachine", + "type": "stateMachine", + "data": { + "currentState": "leftHandIdle", + "states": [ + { + "id": "leftHandIdle", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isLeftHandPoint", "state": "leftHandPoint" }, + { "var": "isLeftHandClose", "state": "leftHandClose" } + ] + }, + { + "id": "leftHandPoint", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isLeftHandIdle", "state": "leftHandIdle" }, + { "var": "isLeftHandClose", "state": "leftHandClose" } + ] + }, + { + "id": "leftHandClose", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isLeftHandIdle", "state": "leftHandIdle" }, + { "var": "isLeftHandPoint", "state": "leftHandPoint" } + ] + } + ] + }, + "children": [ + { + "id": "leftHandIdle", + "type": "clip", + "data": { + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/left_hand_anim.fbx", + "startFrame": 30.0, + "endFrame": 30.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "leftHandPoint", + "type": "clip", + "data": { + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/left_hand_anim.fbx", + "startFrame": 0.0, + "endFrame": 0.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "leftHandClose", + "type": "clip", + "data": { + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/left_hand_anim.fbx", + "startFrame": 15.0, + "endFrame": 15.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + } + ] + }, + { + "id": "mainStateMachine", + "type": "stateMachine", + "data": { + "currentState": "idle", + "states": [ + { + "id": "idle", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isMovingForward", "state": "walkFwd" }, + { "var": "isMovingBackward", "state": "walkBwd" }, + { "var": "isMovingRight", "state": "strafeRight" }, + { "var": "isMovingLeft", "state": "strafeLeft" }, + { "var": "isTurningRight", "state": "turnRight" }, + { "var": "isTurningLeft", "state": "turnLeft" } + ] + }, + { + "id": "walkFwd", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "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" } + ] + } + ] + }, + "children": [ + { + "id": "idle", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx", + "startFrame": 0.0, + "endFrame": 90.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "walkFwd", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_fwd.fbx", + "startFrame": 0.0, + "endFrame": 35.0, + "timeScale": 1.0, + "loopFlag": true, + "timeScaleVar": "walkTimeScale" + }, + "children": [] + }, + { + "id": "walkBwd", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_bwd.fbx", + "startFrame": 0.0, + "endFrame": 37.0, + "timeScale": 1.0, + "loopFlag": true, + "timeScaleVar": "walkTimeScale" + }, + "children": [] + }, + { + "id": "turnLeft", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_left.fbx", + "startFrame": 0.0, + "endFrame": 28.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "turnRight", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_right.fbx", + "startFrame": 0.0, + "endFrame": 30.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "strafeLeft", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/strafe_left.fbx", + "startFrame": 0.0, + "endFrame": 31.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "strafeRight", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/strafe_right.fbx", + "startFrame": 0.0, + "endFrame": 31.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + } + ] + } + ] } ] } From 1948829ca8eb66f9851644064de0b3c5208b070c Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 15 Sep 2015 15:09:08 -0700 Subject: [PATCH 2/3] 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. --- interface/src/avatar/MyAvatar.cpp | 7 +- interface/src/avatar/SkeletonModel.cpp | 4 +- libraries/animation/src/Rig.cpp | 70 ++++++------- libraries/animation/src/Rig.h | 6 +- tests/animation/src/data/avatar.json | 138 ++++++++++++++++++------- 5 files changed, 144 insertions(+), 81 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 91e7ba191f..da2e78c5a3 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -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()); } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 91222ad30e..856bacbf5d 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -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. diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 6baae8fa3e..076baf92c5 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -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); } } diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index f57b446417..9939f383b7 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -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__) */ diff --git a/tests/animation/src/data/avatar.json b/tests/animation/src/data/avatar.json index 1348824ba0..72650893d7 100644 --- a/tests/animation/src/data/avatar.json +++ b/tests/animation/src/data/avatar.json @@ -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", From f13c839f4a5b5eb7a47058d3d9de4f5a2435af58 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 15 Sep 2015 15:19:11 -0700 Subject: [PATCH 3/3] Removed comment --- interface/src/avatar/SkeletonModel.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 856bacbf5d..3894a0ade9 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -150,7 +150,6 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Rig::HandParameters handParams; - // this is sooo getto const PalmData* leftPalm = getPalmWithIndex(myAvatar->getHand(), LEFT_HAND_INDEX); if (leftPalm && leftPalm->isActive()) { handParams.isLeftEnabled = true;