protected void UpdatePalmRotation()
 {
     Leap.Unity.HandModel hand_model = GetComponent <Leap.Unity.HandModel>();
     palm_rotation_ = Quaternion.Slerp(palm_rotation_, hand_model.GetPalmRotation(),
                                       1.0f - rotationFiltering);
 }
    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_;
            }
        }
    }