Mercurial > hg > Game > Games
diff Orchestland/Assets/LeapMotion/Scripts/Utils/MagneticPinch.cs @ 1:f7675884f2a1
Add Orchestland project
author | Daiki OYAKAWA <e135764@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2015 23:09:20 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Orchestland/Assets/LeapMotion/Scripts/Utils/MagneticPinch.cs Fri Jul 17 23:09:20 2015 +0900 @@ -0,0 +1,99 @@ +/******************************************************************************\ +* Copyright (C) Leap Motion, Inc. 2011-2014. * +* Leap Motion proprietary. Licensed under Apache 2.0 * +* Available at http://www.apache.org/licenses/LICENSE-2.0.html * +\******************************************************************************/ + +using UnityEngine; +using System.Collections; +using Leap; + +/** + * Detects pinches and grabs the closest rigidbody if it's within a given range. + * + * Attach this script to the physics hand object assinged to the HandController in a scene. + */ +public class MagneticPinch : MonoBehaviour { + + public const float TRIGGER_DISTANCE_RATIO = 0.7f; + + /** The stiffness of the spring force used to move the object toward the hand. */ + public float forceSpringConstant = 100.0f; + /** The maximum range at which an object can be picked up.*/ + public float magnetDistance = 2.0f; + + protected bool pinching_; + protected Collider grabbed_; + + void Start() { + pinching_ = false; + grabbed_ = null; + } + + /** Finds an object to grab and grabs it. */ + void OnPinch(Vector3 pinch_position) { + pinching_ = true; + + // Check if we pinched a movable object and grab the closest one that's not part of the hand. + Collider[] close_things = Physics.OverlapSphere(pinch_position, magnetDistance); + Vector3 distance = new Vector3(magnetDistance, 0.0f, 0.0f); + + for (int j = 0; j < close_things.Length; ++j) { + Vector3 new_distance = pinch_position - close_things[j].transform.position; + if (close_things[j].GetComponent<Rigidbody>() != null && new_distance.magnitude < distance.magnitude && + !close_things[j].transform.IsChildOf(transform)) { + grabbed_ = close_things[j]; + distance = new_distance; + } + } + } + + /** Clears the pinch state. */ + void OnRelease() { + grabbed_ = null; + pinching_ = false; + } + + /** + * Checks whether the hand is pinching and updates the position of the pinched object. + */ + void Update() { + bool trigger_pinch = false; + HandModel hand_model = GetComponent<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 < HandModel.NUM_FINGERS && !trigger_pinch; ++i) { + Finger finger = leap_hand.Fingers[i]; + + for (int j = 0; j < 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); + } + } +}