void FixedUpdate() { UpdatePalmRotation(); UpdatePinchPosition(); Leap.Unity.HandModel hand_model = GetComponent <Leap.Unity.HandModel>(); Hand leap_hand = hand_model.GetLeapHand(); if (leap_hand == null) { return; } PinchState new_pinch_state = GetNewPinchState(); if (pinch_state_ == PinchState.kPinched) { if (new_pinch_state == PinchState.kReleased) { OnRelease(); } else if (active_object_ != null) { ContinueHardPinch(); } } else if (pinch_state_ == PinchState.kReleasing) { if (new_pinch_state == PinchState.kReleased) { OnRelease(); } else if (new_pinch_state == PinchState.kPinched) { StartPinch(); } else if (active_object_ != null) { ContinueSoftPinch(); } } else { if (new_pinch_state == PinchState.kPinched) { StartPinch(); } else { Hover(); } } pinch_state_ = new_pinch_state; }
/** * Checks whether the hand is pinching and updates the position of the pinched object. */ void Update() { bool trigger_pinch = false; Leap.Unity.HandModel hand_model = GetComponent <Leap.Unity.HandModel>(); Hand leap_hand = hand_model.GetLeapHand(); if (leap_hand == null) { return; } // Scale trigger distance by thumb proximal bone length. Vector leap_thumb_tip = leap_hand.Fingers[0].TipPosition; float proximal_length = leap_hand.Fingers[0].Bone(Bone.BoneType.TYPE_PROXIMAL).Length; float trigger_distance = proximal_length * TRIGGER_DISTANCE_RATIO; // Check thumb tip distance to joints on all other fingers. // If it's close enough, start pinching. for (int i = 1; i < Leap.Unity.HandModel.NUM_FINGERS && !trigger_pinch; ++i) { Finger finger = leap_hand.Fingers[i]; for (int j = 0; j < Leap.Unity.FingerModel.NUM_BONES && !trigger_pinch; ++j) { Vector leap_joint_position = finger.Bone((Bone.BoneType)j).NextJoint; if (leap_joint_position.DistanceTo(leap_thumb_tip) < trigger_distance) { trigger_pinch = true; } } } Vector3 pinch_position = hand_model.fingers[0].GetTipPosition(); // Only change state if it's different. if (trigger_pinch && !pinching_) { OnPinch(pinch_position); } else if (!trigger_pinch && pinching_) { OnRelease(); } // Accelerate what we are grabbing toward the pinch. if (grabbed_ != null) { Vector3 distance = pinch_position - grabbed_.transform.position; grabbed_.GetComponent <Rigidbody>().AddForce(forceSpringConstant * distance); } }
protected PinchState GetNewPinchState() { Leap.Unity.HandModel hand_model = GetComponent <Leap.Unity.HandModel>(); Hand leap_hand = hand_model.GetLeapHand(); Vector leap_thumb_tip = leap_hand.Fingers[0].TipPosition; float closest_distance = Mathf.Infinity; // Check thumb tip distance to joints on all other fingers. // If it's close enough, you're pinching. for (int i = 1; i < Leap.Unity.HandModel.NUM_FINGERS; ++i) { Finger finger = leap_hand.Fingers[i]; for (int j = 0; j < Leap.Unity.FingerModel.NUM_BONES; ++j) { Vector leap_joint_position = finger.Bone((Bone.BoneType)j).NextJoint; float thumb_tip_distance = leap_joint_position.DistanceTo(leap_thumb_tip); closest_distance = Mathf.Min(closest_distance, thumb_tip_distance); } } // Scale trigger distance by thumb proximal bone length. float proximal_length = leap_hand.Fingers[0].Bone(Bone.BoneType.TYPE_PROXIMAL).Length; float trigger_distance = proximal_length * grabTriggerDistance; float release_distance = proximal_length * releaseTriggerDistance; if (closest_distance <= trigger_distance) { return(PinchState.kPinched); } if (closest_distance <= release_distance && pinch_state_ != PinchState.kReleased && !ObjectReleaseBreak(current_pinch_position_)) { return(PinchState.kReleasing); } return(PinchState.kReleased); }
protected virtual float GetUnsmoothedConfidence() { return(_handModel.GetLeapHand().Confidence); }
protected void StartPinch() { // Only pinch if we're hovering over an object. if (active_object_ == null) { return; } Leap.Unity.HandModel hand_model = GetComponent <Leap.Unity.HandModel>(); Leap.Unity.Utils.IgnoreCollisions(gameObject, active_object_.gameObject, true); GrabbableObject grabbable = active_object_.GetComponent <GrabbableObject>(); // Setup initial position and rotation conditions. palm_rotation_ = hand_model.GetPalmRotation(); object_pinch_offset_ = Vector3.zero; // If we don't center the object, find the closest point in the collider for our grab point. if (grabbable == null || !grabbable.centerGrabbedObject) { Vector3 delta_position = active_object_.transform.position - current_pinch_position_; Ray pinch_ray = new Ray(current_pinch_position_, delta_position); RaycastHit pinch_hit; // If we raycast hits the object, we're outside the collider so grab the hit point. // If not, we're inside the collider so just use the pinch position. if (active_object_.Raycast(pinch_ray, out pinch_hit, grabObjectDistance)) { object_pinch_offset_ = active_object_.transform.position - pinch_hit.point; } else { object_pinch_offset_ = active_object_.transform.position - current_pinch_position_; } } filtered_pinch_position_ = active_object_.transform.position - object_pinch_offset_; object_pinch_offset_ = Quaternion.Inverse(active_object_.transform.rotation) * object_pinch_offset_; rotation_from_palm_ = Quaternion.Inverse(palm_rotation_) * active_object_.transform.rotation; // If we can rotate the object quickly, increase max angular velocity for now. if (grabbable == null || grabbable.rotateQuickly) { last_max_angular_velocity_ = active_object_.GetComponent <Rigidbody>().maxAngularVelocity; active_object_.GetComponent <Rigidbody>().maxAngularVelocity = Mathf.Infinity; } if (grabbable != null) { // Notify grabbable object that it was grabbed. grabbable.OnGrab(); if (grabbable.useAxisAlignment) { // If this option is enabled we only want to align the object axis with the palm axis // so we'll cancel out any rotation about the aligned axis. Vector3 palm_vector = grabbable.rightHandAxis; if (hand_model.GetLeapHand().IsLeft) { palm_vector = Vector3.Scale(palm_vector, new Vector3(-1, 1, 1)); } Vector3 axis_in_palm = rotation_from_palm_ * grabbable.objectAxis; Quaternion axis_correction = Quaternion.FromToRotation(axis_in_palm, palm_vector); if (Vector3.Dot(axis_in_palm, palm_vector) < 0) { axis_correction = Quaternion.FromToRotation(axis_in_palm, -palm_vector); } rotation_from_palm_ = axis_correction * rotation_from_palm_; } } }