From 5fc7965042a8b7aa4a3f2e61e134431eb3362bc4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Sep 2015 13:04:58 -0700 Subject: [PATCH 1/4] Throw held objects with velocity from fingertip --- examples/controllers/handControllerGrab.js | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index a13f1de86d..975c1d2e0b 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -41,10 +41,10 @@ var LINE_LENGTH = 500; // var GRAB_RADIUS = 0.3; // if the ray misses but an object is this close, it will still be selected -var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position +var NEAR_GRABBING_ACTION_TIMEFRAME = 0.01; // how quickly objects move to their new position var NEAR_GRABBING_VELOCITY_SMOOTH_RATIO = 1.0; // adjust time-averaging of held object's velocity. 1.0 to disable. var NEAR_PICK_MAX_DISTANCE = 0.6; // max length of pick-ray for close grabbing to be selected -var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things +var RELEASE_VELOCITY_MULTIPLIER = 1.0; // affects throwing things ///////////////////////////////////////////////////////////////// // @@ -86,7 +86,7 @@ function MyController(hand, triggerAction) { this.triggerAction = triggerAction; this.palm = 2 * hand; - // this.tip = 2 * hand + 1; // unused, but I'm leaving this here for fear it will be needed + this.tip = 2 * hand + 1; this.actionID = null; // action this script created... this.grabbedEntity = null; // on this entity. @@ -343,7 +343,8 @@ function MyController(hand, triggerAction) { } - this.currentHandControllerPosition = Controller.getSpatialControlPosition(this.palm); + this.currentHandControllerTipPosition = Controller.getSpatialControlPosition(this.tip); + this.currentObjectTime = Date.now(); }; @@ -353,15 +354,21 @@ function MyController(hand, triggerAction) { return; } - // keep track of the measured velocity of the held object - var handControllerPosition = Controller.getSpatialControlPosition(this.palm); + // Keep track of the fingertip velocity to impart when we release the object + // Note that the idea of using a constant 'tip' velocity regardless of the + // object's actual held offset is an idea intended to make it easier to throw things: + // Because we might catch something or transfer it between hands without a good idea + // of it's actual offset, let's try imparting a velocity which is at a fixed radius + // from the palm. + + var handControllerPosition = Controller.getSpatialControlPosition(this.tip); var now = Date.now(); - var deltaPosition = Vec3.subtract(handControllerPosition, this.currentHandControllerPosition); // meters + var deltaPosition = Vec3.subtract(handControllerPosition, this.currentHandControllerTipPosition); // meters var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds this.computeReleaseVelocity(deltaPosition, deltaTime, true); - this.currentHandControllerPosition = handControllerPosition; + this.currentHandControllerTipPosition = handControllerPosition; this.currentObjectTime = now; Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab"); }; From 5c7cf76035271ab53cf590d353204a1cb6f4848f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Sep 2015 16:13:35 -0700 Subject: [PATCH 2/4] Distance grab works with walking and turning --- examples/controllers/handControllerGrab.js | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 975c1d2e0b..011a9d434b 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -256,6 +256,9 @@ function MyController(hand, triggerAction) { Entities.callEntityMethod(this.grabbedEntity, "startDistantGrab"); } + this.currentAvatarPosition = MyAvatar.position; + this.currentAvatarOrientation = MyAvatar.orientation; + }; this.continueDistanceHolding = function() { @@ -274,11 +277,44 @@ function MyController(hand, triggerAction) { // the action was set up on a previous call. update the targets. var radius = Math.max(Vec3.distance(this.currentObjectPosition, handControllerPosition) * DISTANCE_HOLDING_RADIUS_FACTOR, DISTANCE_HOLDING_RADIUS_FACTOR); + // how far did avatar move this timestep? + var currentPosition = MyAvatar.position; + var avatarDeltaPosition = Vec3.subtract(currentPosition, this.currentAvatarPosition); + this.currentAvatarPosition = currentPosition; + + // How far did the avatar turn this timestep? + // Note: The following code is too long because we need a Quat.quatBetween() function + // that returns the minimum quaternion between two quaternions. + var currentOrientation = MyAvatar.orientation; + if (Quat.dot(currentOrientation, this.currentAvatarOrientation) < 0.0) { + var negativeCurrentOrientation = { x: -currentOrientation.x, + y: -currentOrientation.y, + z: -currentOrientation.z, + w: -currentOrientation.w }; + var avatarDeltaOrientation = Quat.multiply(negativeCurrentOrientation, Quat.inverse(this.currentAvatarOrientation)); + } else { + var avatarDeltaOrientation = Quat.multiply(currentOrientation, Quat.inverse(this.currentAvatarOrientation)); + } + var handToAvatar = Vec3.subtract(handControllerPosition, this.currentAvatarPosition); + var objectToAvatar = Vec3.subtract(this.currentObjectPosition, this.currentAvatarPosition); + var handMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, handToAvatar), handToAvatar); + var objectMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, objectToAvatar), objectToAvatar); + this.currentAvatarOrientation = currentOrientation; + + // how far did hand move this timestep? var handMoved = Vec3.subtract(handControllerPosition, this.handPreviousPosition); this.handPreviousPosition = handControllerPosition; + + // magnify the hand movement but not the change from avatar movement & rotation + handMoved = Vec3.subtract(handMoved, avatarDeltaPosition); + handMoved = Vec3.subtract(handMoved, handMovementFromTurning); var superHandMoved = Vec3.multiply(handMoved, radius); + // Move the object by the magnified amount and then by amount from avatar movement & rotation var newObjectPosition = Vec3.sum(this.currentObjectPosition, superHandMoved); + newObjectPosition = Vec3.sum(newObjectPosition, avatarDeltaPosition); + newObjectPosition = Vec3.sum(newObjectPosition, objectMovementFromTurning); + var deltaPosition = Vec3.subtract(newObjectPosition, this.currentObjectPosition); // meters var now = Date.now(); var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds From 56a0456f705e634b6889f5b2967406aef784a8bf Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Sep 2015 16:49:55 -0700 Subject: [PATCH 3/4] Adjust force multiplier and timestep --- examples/controllers/handControllerGrab.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 011a9d434b..024b40a885 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -41,10 +41,10 @@ var LINE_LENGTH = 500; // var GRAB_RADIUS = 0.3; // if the ray misses but an object is this close, it will still be selected -var NEAR_GRABBING_ACTION_TIMEFRAME = 0.01; // how quickly objects move to their new position +var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position var NEAR_GRABBING_VELOCITY_SMOOTH_RATIO = 1.0; // adjust time-averaging of held object's velocity. 1.0 to disable. var NEAR_PICK_MAX_DISTANCE = 0.6; // max length of pick-ray for close grabbing to be selected -var RELEASE_VELOCITY_MULTIPLIER = 1.0; // affects throwing things +var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things ///////////////////////////////////////////////////////////////// // From 006650f23bba7672bbeb81063948a76280c23291 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Sep 2015 14:34:23 -0700 Subject: [PATCH 4/4] Fix for PR comments --- examples/controllers/handControllerGrab.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 024b40a885..4b1d6e9648 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -84,9 +84,11 @@ function MyController(hand, triggerAction) { this.getHandRotation = MyAvatar.getLeftPalmRotation; } + var SPATIAL_CONTROLLERS_PER_PALM = 2; + var TIP_CONTROLLER_OFFSET = 1; this.triggerAction = triggerAction; - this.palm = 2 * hand; - this.tip = 2 * hand + 1; + this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand; + this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET; this.actionID = null; // action this script created... this.grabbedEntity = null; // on this entity. @@ -287,10 +289,12 @@ function MyController(hand, triggerAction) { // that returns the minimum quaternion between two quaternions. var currentOrientation = MyAvatar.orientation; if (Quat.dot(currentOrientation, this.currentAvatarOrientation) < 0.0) { - var negativeCurrentOrientation = { x: -currentOrientation.x, - y: -currentOrientation.y, - z: -currentOrientation.z, - w: -currentOrientation.w }; + var negativeCurrentOrientation = { + x: -currentOrientation.x, + y: -currentOrientation.y, + z: -currentOrientation.z, + w: -currentOrientation.w + }; var avatarDeltaOrientation = Quat.multiply(negativeCurrentOrientation, Quat.inverse(this.currentAvatarOrientation)); } else { var avatarDeltaOrientation = Quat.multiply(currentOrientation, Quat.inverse(this.currentAvatarOrientation)); @@ -482,17 +486,14 @@ function MyController(hand, triggerAction) { }; this.startTouch = function(entityID) { - // print('START TOUCH' + entityID); Entities.callEntityMethod(entityID, "startTouch"); }; this.continueTouch = function(entityID) { - // print('CONTINUE TOUCH' + entityID); Entities.callEntityMethod(entityID, "continueTouch"); }; this.stopTouch = function(entityID) { - // print('STOP TOUCH' + entityID); Entities.callEntityMethod(entityID, "stopTouch"); };