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;
    }
Example #2
0
    /**
     * 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_;
            }
        }
    }