Fix default hand poses

This commit is contained in:
luiscuenca 2018-01-04 11:37:37 -07:00
parent 47dbb0c168
commit 28d9409bf0
5 changed files with 159 additions and 55 deletions

Binary file not shown.

View file

@ -222,7 +222,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
auto orientation = myAvatar->getLocalOrientation(); auto orientation = myAvatar->getLocalOrientation();
_rig.computeMotionAnimationState(deltaTime, position, velocity, orientation, ccState); _rig.computeMotionAnimationState(deltaTime, position, velocity, orientation, ccState);
// evaluate AnimGraph animation and update jointStates. //// evaluate AnimGraph animation and update jointStates.
Model::updateRig(deltaTime, parentTransform); Model::updateRig(deltaTime, parentTransform);
Rig::EyeParameters eyeParams; Rig::EyeParameters eyeParams;
@ -323,17 +323,22 @@ void MySkeletonModel::updateFingers() {
for (auto& link : chain) { for (auto& link : chain) {
int index = _rig.indexOfJoint(link.second); int index = _rig.indexOfJoint(link.second);
if (index >= 0) { if (index >= 0) {
if (_jointRotationFrameOffsetMap.find(index) == _jointRotationFrameOffsetMap.end()) {
_jointRotationFrameOffsetMap.insert(std::pair<int, int>(index, 0));
}
auto pose = myAvatar->getControllerPoseInSensorFrame(link.first); auto pose = myAvatar->getControllerPoseInSensorFrame(link.first);
if (pose.valid) { if (pose.valid) {
glm::quat relRot = glm::inverse(prevAbsRot) * pose.getRotation(); glm::quat relRot = glm::inverse(prevAbsRot) * pose.getRotation();
// only set the rotation for the finger joints, not the hands. // only set the rotation for the finger joints, not the hands.
if (link.first != controller::Action::LEFT_HAND && link.first != controller::Action::RIGHT_HAND) { if (link.first != controller::Action::LEFT_HAND && link.first != controller::Action::RIGHT_HAND) {
_rig.setJointRotation(index, true, relRot, CONTROLLER_PRIORITY); _rig.setJointRotation(index, true, relRot, CONTROLLER_PRIORITY);
_jointRotationFrameOffsetMap.find(index)->second = 0;
} }
prevAbsRot = pose.getRotation(); prevAbsRot = pose.getRotation();
} else { } else if (_jointRotationFrameOffsetMap.find(index)->second == 1){
// _rig.clearJointAnimationPriority(index); _rig.clearJointAnimationPriority(index);
} }
_jointRotationFrameOffsetMap.find(index)->second++;
} }
} }
} }

View file

@ -28,6 +28,8 @@ private:
AnimPose _prevHips; // sensor frame AnimPose _prevHips; // sensor frame
bool _prevHipsValid { false }; bool _prevHipsValid { false };
std::map<int, int> _jointRotationFrameOffsetMap;
}; };
#endif // hifi_MySkeletonModel_h #endif // hifi_MySkeletonModel_h

View file

@ -32,7 +32,8 @@ var DEFAULT_SCRIPTS_COMBINED = [
"system/tablet-ui/tabletUI.js" "system/tablet-ui/tabletUI.js"
]; ];
var DEFAULT_SCRIPTS_SEPARATE = [ var DEFAULT_SCRIPTS_SEPARATE = [
"system/controllers/controllerScripts.js" "system/controllers/controllerScripts.js",
"system/controllers/handTouch.js"
//"system/chat.js" //"system/chat.js"
]; ];

View file

@ -11,15 +11,36 @@
(function(){ (function(){
var animating = false;
var updateFingerWithIndex = 0; var updateFingerWithIndex = 0;
// Keys to access finger data
var dataKeys = ["pinky", "ring", "middle", "index", "thumb"]; var dataKeys = ["pinky", "ring", "middle", "index", "thumb"];
// Additionally close the hands to achieve a grabbing effect
var grabPercent = { left: 0, var grabPercent = { left: 0,
right: 0 }; right: 0 };
var isGrabbing = false; // var isGrabbing = false;
// Store which fingers are touching - if all false restate the default poses
var isTouching = {
left: {
pinky: false,
middle: false,
ring: false,
thumb: false,
index: false
}, right: {
pinky: false,
middle: false,
ring: false,
thumb: false,
index: false
}
}
// joint data for opened pose
var dataOpen = { var dataOpen = {
left: { left: {
pinky: [{x: -0.18262, y:-2.666, z:-25.11229}, {x: 1.28845, y:0, z:1.06604}, {x: -3.967, y:0, z:-0.8351} ], pinky: [{x: -0.18262, y:-2.666, z:-25.11229}, {x: 1.28845, y:0, z:1.06604}, {x: -3.967, y:0, z:-0.8351} ],
@ -35,6 +56,8 @@
index: [{x: -0.111, y: 0, z: -2.2816}, {x: 1.217, y: 0, z: -0.90168}, {x: -3.967, y: 0, z: 2.62649}] index: [{x: -0.111, y: 0, z: -2.2816}, {x: 1.217, y: 0, z: -0.90168}, {x: -3.967, y: 0, z: 2.62649}]
} }
} }
// joint data for closed hand
var dataClose = { var dataClose = {
left: { left: {
@ -52,6 +75,8 @@
} }
} }
// joint data for the current frame
var dataCurrent = { var dataCurrent = {
left:{ left:{
pinky:[{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], pinky:[{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}],
@ -68,6 +93,8 @@
index: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}] index: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}]
} }
} }
// interpolated values on joint data to smooth movement
var dataDelta = { var dataDelta = {
left:{ left:{
@ -86,16 +113,24 @@
} }
} }
// Acquire an updated value per hand every 5 frames
var animationSteps = 5; var animationSteps = 5;
// Debugging info
var showSphere = false; var showSphere = false;
var showLines = false; var showLines = false;
// store the rays for the fingers - only for debug purposes
var fingerRays = { var fingerRays = {
left:{pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}, left:{pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined},
right:{pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined} right:{pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}
}; };
// Register object with API Debugger
var varsToDebug = { var varsToDebug = {
toggleDebugSphere: function(){ toggleDebugSphere: function(){
showSphere = !showSphere; showSphere = !showSphere;
@ -105,18 +140,18 @@
}, },
fingerPercent: { fingerPercent: {
left: { left: {
pinky: 0.5, pinky: 0.75,
middle: 0.5, middle: 0.75,
ring: 0.5, ring: 0.75,
thumb: 0.5, thumb: 0.75,
index: 0.5 index: 0.75
} , } ,
right: { right: {
pinky: 0.5, pinky: 0.75,
middle: 0.5, middle: 0.75,
ring: 0.5, ring: 0.75,
thumb: 0.5, thumb: 0.75,
index: 0.5 index: 0.75
} }
}, },
triggerValues: { triggerValues: {
@ -128,6 +163,8 @@
rightSecondaryValue: 0 rightSecondaryValue: 0
} }
} }
// Add/Subtract the joint data - per finger joint
function addVals(val1, val2, sign) { function addVals(val1, val2, sign) {
var val = []; var val = [];
@ -141,6 +178,8 @@
return val; return val;
} }
// Multiply/Divide the joint data - per finger joint
function multiplyValsBy(val1, num) { function multiplyValsBy(val1, num) {
var val = []; var val = [];
for (var i = 0; i < val1.length; i++) { for (var i = 0; i < val1.length; i++) {
@ -151,6 +190,8 @@
} }
return val; return val;
} }
// Calculate the finger lengths by adding its joint lengths
function getJointDistances(jointNamesArray) { function getJointDistances(jointNamesArray) {
var result = {distances: [], totalDistance: 0} var result = {distances: [], totalDistance: 0}
@ -165,23 +206,29 @@
} }
return result; return result;
} }
// Calculate the sphere that look up for entities, the center of the palm, perpendicular vector from the palm plane and origin of the the finger rays
function estimatePalmData(side) { function estimatePalmData(side) {
var data = {position: undefined, perpendicular: undefined, distance: undefined, fingers: {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}}; // Return data object
var data = {position: undefined, perpendicular: undefined, distance: undefined, fingers: {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}};
// Calculate the finger lengths by adding its joint lengths
var jointOffset = { x: 0, y: 0, z: 0 }; var jointOffset = { x: 0, y: 0, z: 0 };
var upperSide = side[0].toUpperCase() + side.substring(1); var upperSide = side[0].toUpperCase() + side.substring(1);
var jointIndexHand = MyAvatar.getJointIndex(upperSide + "Hand"); var jointIndexHand = MyAvatar.getJointIndex(upperSide + "Hand");
// Store position of the hand joint
var worldPosHand = MyAvatar.jointToWorldPoint(jointOffset, jointIndexHand); var worldPosHand = MyAvatar.jointToWorldPoint(jointOffset, jointIndexHand);
var minusWorldPosHand = {x:-worldPosHand.x, y:-worldPosHand.y, z:-worldPosHand.z}; var minusWorldPosHand = {x:-worldPosHand.x, y:-worldPosHand.y, z:-worldPosHand.z};
// Data for finger rays
var directions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}; var directions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined};
var positions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}; var positions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined};
var sumvec = {x:0, y:0, z:0}; // Calculate palm center
sumvec = Vec3.sum(worldPosHand, sumvec); var palmCenter = {x:0, y:0, z:0};
palmCenter = Vec3.sum(worldPosHand, palmCenter);
var thumbLength = 0; var thumbLength = 0;
@ -195,15 +242,17 @@
directions[finger] = Vec3.normalize(Vec3.sum(positions[finger], minusWorldPosHand)); directions[finger] = Vec3.normalize(Vec3.sum(positions[finger], minusWorldPosHand));
data.fingers[finger] = Vec3.sum(positions[finger], Vec3.multiply(fingerLength, directions[finger])); data.fingers[finger] = Vec3.sum(positions[finger], Vec3.multiply(fingerLength, directions[finger]));
if (finger != "thumb") { if (finger != "thumb") {
sumvec = Vec3.sum(Vec3.multiply(2, positions[finger]), sumvec); palmCenter = Vec3.sum(Vec3.multiply(2, positions[finger]), palmCenter); // Hand joint + 2 * 4 fingers(no thumb) = 9
} else { } else {
thumbLength = fingerLength; thumbLength = fingerLength;
} }
} }
data.perpendicular = side == "right" ? Vec3.normalize(Vec3.cross(directions["ring"], directions["pinky"])) : Vec3.normalize(Vec3.cross(directions["pinky"],directions["ring"])); data.perpendicular = side == "right" ? Vec3.normalize(Vec3.cross(directions["ring"], directions["pinky"])) : Vec3.normalize(Vec3.cross(directions["pinky"],directions["ring"]));
data.position = Vec3.multiply(1.0/9, sumvec);
data.position = Vec3.multiply(1.0/9, palmCenter); // Hand joint + 2 * 4 fingers(no thumb) = 9
data.distance = 1.55*Vec3.distance(data.position, positions["index"]); data.distance = 1.55*Vec3.distance(data.position, positions["index"]);
// move back thumb check up origin // move back thumb check up origin
@ -213,8 +262,11 @@
return data; return data;
} }
// Register GlobalDebugger for API Debugger
Script.registerValue("GlobalDebugger", varsToDebug); Script.registerValue("GlobalDebugger", varsToDebug);
// Create debug overlays - finger rays + palm rays + spheres
for (var i = 0; i < dataKeys.length; i++) { for (var i = 0; i < dataKeys.length; i++) {
fingerRays["left"][dataKeys[i]] = Overlays.addOverlay("line3d", { fingerRays["left"][dataKeys[i]] = Overlays.addOverlay("line3d", {
color: { red: 0, green: 0, blue: 255 }, color: { red: 0, green: 0, blue: 255 },
@ -261,14 +313,18 @@
} }
function updateSphereHand(side) { function updateSphereHand(side) {
var palmData = estimatePalmData(side); var palmData = estimatePalmData(side);
var dist = 1.5*palmData.distance;
var palmPoint = palmData.position; var palmPoint = palmData.position;
var dist = 1.5*palmData.distance;
// Situate the debugging overlays
var checkOffset = { x: palmData.perpendicular.x * dist, var checkOffset = { x: palmData.perpendicular.x * dist,
y: palmData.perpendicular.y * dist, y: palmData.perpendicular.y * dist,
z: palmData.perpendicular.z * dist }; z: palmData.perpendicular.z * dist };
var spherePos = Vec3.sum(palmPoint, checkOffset); var spherePos = Vec3.sum(palmPoint, checkOffset);
var checkPoint = Vec3.sum(palmPoint, Vec3.multiply(2, checkOffset)); var checkPoint = Vec3.sum(palmPoint, Vec3.multiply(2, checkOffset));
@ -287,7 +343,7 @@
}, },
visible: showSphere visible: showSphere
}); });
var pickRays = [];
for (var i = 0; i < dataKeys.length; i++) { for (var i = 0; i < dataKeys.length; i++) {
Overlays.editOverlay(fingerRays[side][dataKeys[i]], { Overlays.editOverlay(fingerRays[side][dataKeys[i]], {
start: palmData.fingers[dataKeys[i]], start: palmData.fingers[dataKeys[i]],
@ -295,6 +351,9 @@
visible: showLines visible: showLines
}); });
} }
// Update the intersection of only one finger at a time
var finger = dataKeys[updateFingerWithIndex]; var finger = dataKeys[updateFingerWithIndex];
var grabbables = Entities.findEntities(spherePos, dist); var grabbables = Entities.findEntities(spherePos, dist);
@ -303,14 +362,19 @@
var origin = palmData.fingers[finger]; var origin = palmData.fingers[finger];
var direction = Vec3.normalize(Vec3.subtract(checkPoint, origin)); var direction = Vec3.normalize(Vec3.subtract(checkPoint, origin));
var intersection = Entities.findRayIntersection({origin: origin, direction: direction}, true, grabbables, [], true, false); var intersection = Entities.findRayIntersection({origin: origin, direction: direction}, true, grabbables, [], true, false);
var percent = 0.5; var percent = 0.75;
if (intersection.intersects && intersection.distance < 2.5*dist) { var isAbleToGrab = intersection.intersects && intersection.distance < 2.5*dist;
// Store if this finger is touching something
isTouching[side][finger] = isAbleToGrab;
if (isAbleToGrab) {
// update the open/close percentage for this finger
percent = intersection.distance/(2.5*dist); percent = intersection.distance/(2.5*dist);
var grabMultiplier = finger === "thumb" ? 0.2 : 0.05; var grabMultiplier = finger === "thumb" ? 0.2 : 0.05;
percent += grabMultiplier * grabPercent[side]; percent += grabMultiplier * grabPercent[side];
} }
varsToDebug.fingerPercent[side][finger] = percent; varsToDebug.fingerPercent[side][finger] = percent; // store the current open/close percentage
} }
// Calculate new interpolation data
var totalDistance = addVals(dataClose[side][finger], dataOpen[side][finger], -1); var totalDistance = addVals(dataClose[side][finger], dataOpen[side][finger], -1);
var percent = varsToDebug.fingerPercent[side][finger]; var percent = varsToDebug.fingerPercent[side][finger];
var newFingerData = addVals(dataOpen[side][finger], multiplyValsBy(totalDistance, percent), 1); var newFingerData = addVals(dataOpen[side][finger], multiplyValsBy(totalDistance, percent), 1);
@ -319,6 +383,7 @@
dataDelta[side][finger] = multiplyValsBy(addVals(newFingerData, dataCurrent[side][finger], -1), 1.0/animationSteps); dataDelta[side][finger] = multiplyValsBy(addVals(newFingerData, dataCurrent[side][finger], -1), 1.0/animationSteps);
} }
// Recreate the finger joint names - and how many 0 to count
function getJointNames(side, finger, count) { function getJointNames(side, finger, count) {
var names = []; var names = [];
for (var i = 1; i < count+1; i++) { for (var i = 1; i < count+1; i++) {
@ -328,8 +393,11 @@
return names; return names;
} }
// Capture the controller values
var leftTriggerPress = function (value) { var leftTriggerPress = function (value) {
varsToDebug.triggerValues.leftTriggerValue = value; varsToDebug.triggerValues.leftTriggerValue = value;
// the value for the trigger increments the hand-close percentage
grabPercent["left"] = value; grabPercent["left"] = value;
}; };
var leftTriggerClick = function (value) { var leftTriggerClick = function (value) {
@ -337,6 +405,7 @@
}; };
var rightTriggerPress = function (value) { var rightTriggerPress = function (value) {
varsToDebug.triggerValues.rightTriggerValue = value; varsToDebug.triggerValues.rightTriggerValue = value;
// the value for the trigger increments the hand-close percentage
grabPercent["right"] = value; grabPercent["right"] = value;
}; };
var rightTriggerClick = function (value) { var rightTriggerClick = function (value) {
@ -362,34 +431,61 @@
mapping.from([Controller.Standard.RightGrip]).peek().to(rightSecondaryPress); mapping.from([Controller.Standard.RightGrip]).peek().to(rightSecondaryPress);
Controller.enableMapping(MAPPING_NAME); Controller.enableMapping(MAPPING_NAME);
function getTouching(side) {
var animating = false;
for (var i = 0; i < dataKeys.length; i++) {
var finger = dataKeys[i];
animating = animating || isTouching[side][finger];
}
return animating;
}
Script.update.connect(function(){ Script.update.connect(function(){
updateFingerWithIndex = updateFingerWithIndex < dataKeys.length-1 ? updateFingerWithIndex + 1 : 0;
// iterate fingers
updateFingerWithIndex = (updateFingerWithIndex < dataKeys.length-1) ? updateFingerWithIndex + 1 : 0;
// precalculate data
updateSphereHand("right"); updateSphereHand("right");
updateSphereHand("left"); updateSphereHand("left");
for (var i = 0; i < dataKeys.length; i++) { // Assign interpolated values
var finger = dataKeys[i]; var i, j, index;
var names = getJointNames("Right", finger, 3); for (i = 0; i < dataKeys.length; i++) {
dataCurrent["right"][finger] = addVals(dataCurrent["right"][finger], dataDelta["right"][finger], 1); var finger = dataKeys[i];
for (var j = 0; j < names.length; j++) { var names = getJointNames("Right", finger, 3);
var index = MyAvatar.getJointIndex(names[j]); dataCurrent["right"][finger] = addVals(dataCurrent["right"][finger], dataDelta["right"][finger], 1);
var quatRot = Quat.fromVec3Degrees(dataCurrent["right"][finger][j]); for (j = 0; j < names.length; j++) {
MyAvatar.setJointRotation(index, quatRot); index = MyAvatar.getJointIndex(names[j]);
} // if no finger is touching restate the default poses
} if (getTouching("right")) {
var quatRot = Quat.fromVec3Degrees(dataCurrent["right"][finger][j]);
for (var i = 0; i < dataKeys.length; i++) { MyAvatar.setJointRotation(index, quatRot);
var finger = dataKeys[i]; } else {
var names = getJointNames("Left", finger, 3); MyAvatar.clearJointData(index);
dataCurrent["left"][finger] = addVals(dataCurrent["left"][finger], dataDelta["left"][finger], 1); }
for (var j = 0; j < names.length; j++) { }
var index = MyAvatar.getJointIndex(names[j]); }
var quatRot = Quat.fromVec3Degrees(dataCurrent["left"][finger][j]);
MyAvatar.setJointRotation(index, quatRot); for (i = 0; i < dataKeys.length; i++) {
} var finger = dataKeys[i];
} var names = getJointNames("Left", finger, 3);
dataCurrent["left"][finger] = addVals(dataCurrent["left"][finger], dataDelta["left"][finger], 1);
for (j = 0; j < names.length; j++) {
index = MyAvatar.getJointIndex(names[j]);
// if no finger is touching restate the default poses
if (getTouching("left")) {
var quatRot = Quat.fromVec3Degrees(dataCurrent["left"][finger][j]);
MyAvatar.setJointRotation(index, quatRot);
} else {
MyAvatar.clearJointData(index);
}
}
}
}); });
}()) }())