From b26f5c5811f6e285ad15120bc132d6e2f1fba86c Mon Sep 17 00:00:00 2001
From: David Rowe <david@ctrlaltstudio.com>
Date: Fri, 23 Jun 2017 16:15:40 +1200
Subject: [PATCH] Clear finger joints when finger poses no longer being updated

---
 interface/src/Application.cpp            | 29 ++++++++++++++++--------
 interface/src/avatar/MySkeletonModel.cpp | 23 ++++++++-----------
 2 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index ace38fcc1e..38ebfe609f 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -4562,19 +4562,28 @@ void Application::update(float deltaTime) {
     auto avatarToSensorMatrix = worldToSensorMatrix * myAvatarMatrix;
     myAvatar->setHandControllerPosesInSensorFrame(leftHandPose.transform(avatarToSensorMatrix), rightHandPose.transform(avatarToSensorMatrix));
 
+    // If have previously done finger poses or there are new valid finger poses, update finger pose values. This so that if
+    // fingers are not being controlled, finger joints are not updated in MySkeletonModel.
+    // Assumption: Finger poses are either all present and valid or not present at all; thus can test just one joint.
     MyAvatar::FingerPosesMap leftHandFingerPoses;
-    for (int i = (int)controller::Action::LEFT_HAND_THUMB1; i <= (int)controller::Action::LEFT_HAND_PINKY4; i++) {
-        leftHandFingerPoses[i] = { 
-            userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix), 
-            userInputMapper->getActionName((controller::Action)i)
-        };
+    if (myAvatar->getLeftHandFingerControllerPosesInSensorFrame().size() > 0
+            || userInputMapper->getPoseState(controller::Action::LEFT_HAND_THUMB1).isValid()) {
+        for (int i = (int)controller::Action::LEFT_HAND_THUMB1; i <= (int)controller::Action::LEFT_HAND_PINKY4; i++) {
+            leftHandFingerPoses[i] = {
+                userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix),
+                userInputMapper->getActionName((controller::Action)i)
+            };
+        }
     }
     MyAvatar::FingerPosesMap rightHandFingerPoses;
-    for (int i = (int)controller::Action::RIGHT_HAND_THUMB1; i <= (int)controller::Action::RIGHT_HAND_PINKY4; i++) {
-        rightHandFingerPoses[i] = {
-            userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix),
-            userInputMapper->getActionName((controller::Action)i)
-        };
+    if (myAvatar->getRightHandFingerControllerPosesInSensorFrame().size() > 0
+        || userInputMapper->getPoseState(controller::Action::RIGHT_HAND_THUMB1).isValid()) {
+        for (int i = (int)controller::Action::RIGHT_HAND_THUMB1; i <= (int)controller::Action::RIGHT_HAND_PINKY4; i++) {
+            rightHandFingerPoses[i] = {
+                userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix),
+                userInputMapper->getActionName((controller::Action)i)
+            };
+        }
     }
     myAvatar->setFingerControllerPosesInSensorFrame(leftHandFingerPoses, rightHandFingerPoses);
 
diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp
index 54973dc5c5..ee292725e0 100644
--- a/interface/src/avatar/MySkeletonModel.cpp
+++ b/interface/src/avatar/MySkeletonModel.cpp
@@ -172,18 +172,13 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
 
     _rig.updateFromEyeParameters(eyeParams);
 
-
-    if (leftHandPose.isValid()) {
-        updateFingers(myAvatar->getLeftHandFingerControllerPosesInSensorFrame());
-    }
-    if (rightHandPose.isValid()) {
-        updateFingers(myAvatar->getRightHandFingerControllerPosesInSensorFrame());
-    }
+    updateFingers(myAvatar->getLeftHandFingerControllerPosesInSensorFrame());
+    updateFingers(myAvatar->getRightHandFingerControllerPosesInSensorFrame());
 }
 
 
 void MySkeletonModel::updateFingers(const MyAvatar::FingerPosesMap& fingerPoses) {
-    // Assumes that finger poses are kept in the poses map in order.
+    // Assumes that finger poses are kept in order in the poses map.
 
     if (fingerPoses.size() == 0) {
         return;
@@ -194,21 +189,23 @@ void MySkeletonModel::updateFingers(const MyAvatar::FingerPosesMap& fingerPoses)
     bool isLeftHand = posesMapItr->first < (int)controller::Action::RIGHT_HAND_THUMB1;
 
     MyAvatar* myAvatar = static_cast<MyAvatar*>(_owningAvatar);
-    glm::quat handJointRotation = isLeftHand
-        ? myAvatar->getLeftHandControllerPoseInSensorFrame().getRotation()
-        : myAvatar->getRightHandControllerPoseInSensorFrame().getRotation();
+    auto handPose = isLeftHand 
+        ? myAvatar->getLeftHandControllerPoseInSensorFrame() 
+        : myAvatar->getRightHandControllerPoseInSensorFrame();
+    auto handJointRotation = handPose.getRotation();
 
+    bool isHandValid = handPose.isValid();
     bool isFingerValid = false;
     glm::quat previousJointRotation;
 
     while (posesMapItr != fingerPoses.end()) {
         auto jointName = posesMapItr->second.second;
-        if (jointName.right(1) == "1") {
+        if (isHandValid && jointName.right(1) == "1") {
             isFingerValid = posesMapItr->second.first.isValid();
             previousJointRotation = handJointRotation;
         }
 
-        if (isFingerValid) {
+        if (isHandValid && isFingerValid) {
             auto thisJointRotation = posesMapItr->second.first.getRotation();
             const float CONTROLLER_PRIORITY = 2.0f;
             _rig.setJointRotation(_rig.indexOfJoint(jointName), true, glm::inverse(previousJointRotation) * thisJointRotation,