diff Orchestland/Assets/LeapMotion/Scripts/Hands/FingerModel.cs @ 3:0030a1b971fb default tip

merge
author Yuta ANSE <e135745@ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2015 23:23:43 +0900
parents f7675884f2a1
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Orchestland/Assets/LeapMotion/Scripts/Hands/FingerModel.cs	Fri Jul 17 23:23:43 2015 +0900
@@ -0,0 +1,264 @@
+/******************************************************************************\
+* 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;
+
+/**
+* The base class for all fingers.
+* 
+* This class serves as the interface between the HandController object,
+* the parent Hand object and the concrete finger objects.
+*
+* Subclasses of FingerModel must implement InitFinger() and UpdateFinger(). The InitHand() function
+* is typically called by the parent HandModel InitHand() method; likewise, the UpdateFinger()
+* function is typically called by the parent HandModel UpdateHand() function.
+*/
+
+public abstract class FingerModel : MonoBehaviour {
+
+  /** The number of bones in a finger. */
+  public const int NUM_BONES = 4;
+
+  /** The number of joints in a finger. */
+  public const int NUM_JOINTS = 3;
+
+  [HideInInspector]
+  public Finger.FingerType fingerType = Finger.FingerType.TYPE_INDEX;
+
+  // Unity references
+  /** Bones positioned and rotated by FingerModel. */
+  public Transform[] bones = new Transform[NUM_BONES];
+  /** Joints positioned and rotated by FingerModel. */
+  public Transform[] joints = new Transform[NUM_BONES - 1];
+  
+  // Leap references
+  /** The Leap Hand object. */
+  protected Hand hand_;
+  /** The Leap Finger object. */
+  protected Finger finger_;
+  /** An added offset vector. */
+  protected Vector3 offset_ = Vector3.zero;
+  /** Whether this finger is mirrored. */
+  protected bool mirror_z_axis_ = false;
+
+  /** The parent HandController instance. */
+  protected HandController controller_;
+
+  /** Assigns the HandController parent for this FingerModel object. */
+  public void SetController(HandController controller) {
+    controller_ = controller;
+  }
+
+  /** The parent HandController instance. */
+  public HandController GetController() {
+    return controller_;
+  }
+
+  /** Sets the Leap Hand and Leap Finger for this finger.
+  * Note that Leap Hand and Finger objects are recreated every frame. The
+  * parent HandModel object calls this function to set or update the underlying
+  * finger. The tracking data in the Leap objects are used to update the FingerModel.
+  */ 
+  public void SetLeapHand(Hand hand) {
+    hand_ = hand;
+    if (hand_ != null)
+      finger_ = hand.Fingers[(int)fingerType];
+  }
+
+  /** Sets an offset vector to displace the finger from its normally calculated
+  * position relative to the HandController. Typically, this offset is used to
+  * give the virtual hands a larger range of motion then they would have based on their 
+  * scaled size in the Unity scene.
+  */
+  public void SetOffset(Vector3 offset) {
+    offset_ = offset;
+  }
+
+  /** 
+  * Sets the mirror z-axis flag for this Finger Model.
+  * Mirroring the z axis reverses the hand so that they face the opposite direction -- as if in a mirror.
+  * @param mirror Set true, the default value to mirror; false for normal rendering. 
+  */
+  public void MirrorZAxis(bool mirror = true) {
+    mirror_z_axis_ = mirror;
+  }
+
+  /** The Leap Hand object. */
+  public Hand GetLeapHand() { return hand_; }
+  /** The Leap Finger object. */
+  public Finger GetLeapFinger() { return finger_; }
+
+  /** 
+  * Implement this function to initialize this finger after it is created.
+  * Typically, this function is called by the parent HandModel object.
+  */
+  public virtual void InitFinger() {
+    UpdateFinger();
+  }
+
+  /** 
+  * Implement this function to update this finger once per game loop.
+  * Typically, this function is called by the parent HandModel object's
+  * UpdateHand() function, which is called in the Unity Update() phase for
+  * graphics hand models and in the FixedUpdate() phase for physics hand
+  * models.
+  */
+  public abstract void UpdateFinger();
+
+  /** Returns any additional movement the finger needs because of non-relative palm movement.*/
+  public Vector3 GetOffset() {
+    return offset_;
+  }
+
+  /** Returns the location of the tip of the finger in relation to the controller.*/
+  public Vector3 GetTipPosition() {
+    if (controller_ != null && finger_ != null) {
+      Vector3 local_tip = finger_.Bone ((Bone.BoneType.TYPE_DISTAL)).NextJoint.ToUnityScaled (mirror_z_axis_);
+      return controller_.transform.TransformPoint (local_tip) + offset_;
+    }
+    if (bones [NUM_BONES - 1] && joints [NUM_JOINTS - 2]) {
+      return 2f*bones [NUM_BONES - 1].position - joints [NUM_JOINTS - 2].position;
+    }
+    return Vector3.zero;
+  }
+
+  /** Returns the location of the given joint on the finger in relation to the controller.*/
+  public Vector3 GetJointPosition(int joint) {
+    if (joint >= NUM_BONES) {
+      return GetTipPosition ();
+    }
+    if (controller_ != null && finger_ != null) {
+      Vector3 local_position = finger_.Bone ((Bone.BoneType)(joint)).PrevJoint.ToUnityScaled (mirror_z_axis_);
+      return controller_.transform.TransformPoint (local_position) + offset_;
+    }
+    if (joints [joint]) {
+      return joints[joint].position;
+    }
+    return Vector3.zero;
+  }
+
+  /** Returns a ray from the tip of the finger in the direction it is pointing.*/
+  public Ray GetRay() {
+    Ray ray = new Ray(GetTipPosition(), GetBoneDirection(NUM_BONES - 1));
+    return ray;
+  }
+
+  /** Returns the center of the given bone on the finger in relation to the controller.*/
+  public Vector3 GetBoneCenter(int bone_type) {
+    if (controller_ != null && finger_ != null) {
+      Bone bone = finger_.Bone ((Bone.BoneType)(bone_type));
+      return controller_.transform.TransformPoint (bone.Center.ToUnityScaled (mirror_z_axis_)) + offset_;
+    }
+    if (bones [bone_type]) {
+      return bones[bone_type].position;
+    }
+    return Vector3.zero;
+  }
+
+  /** Returns the direction the given bone is facing on the finger in relation to the controller.*/
+  public Vector3 GetBoneDirection(int bone_type) {
+    if (controller_ != null && finger_ != null) {
+      Vector3 direction = GetJointPosition (bone_type + 1) - GetJointPosition (bone_type);
+      return direction.normalized;
+    }
+    if (bones[bone_type]) {
+      return bones[bone_type].forward;
+    }
+    return Vector3.forward;
+  }
+
+  /** Returns the rotation quaternion of the given bone in relation to the controller.*/
+  public Quaternion GetBoneRotation(int bone_type) {
+    if (controller_ != null && finger_ != null) {
+      Quaternion local_rotation = finger_.Bone ((Bone.BoneType)(bone_type)).Basis.Rotation (mirror_z_axis_);
+      return controller_.transform.rotation * local_rotation;
+    }
+    if (bones[bone_type]) {
+      return bones[bone_type].rotation;
+    }
+    return Quaternion.identity;
+  }
+  
+  /** Returns the length of the finger bone.*/
+  public float GetBoneLength(int bone_type) {
+    return finger_.Bone ((Bone.BoneType)(bone_type)).Length * UnityVectorExtension.INPUT_SCALE;
+  }
+  
+  /** Returns the width of the finger bone.*/
+  public float GetBoneWidth(int bone_type) {
+    return finger_.Bone((Bone.BoneType)(bone_type)).Width * UnityVectorExtension.INPUT_SCALE;
+  }
+  
+  /**
+   * Returns Mecanim stretch angle in the range (-180, +180]
+   * NOTE: Positive stretch opens the hand.
+   * For the thumb this moves it away from the palm.
+   */
+  public float GetFingerJointStretchMecanim(int joint_type) {
+    // The successive actions of local rotations on a vector yield the global rotation,
+    // so the inverse of the parent rotation appears on the left.
+    Quaternion jointRotation = Quaternion.identity;
+    if (finger_ != null) {
+      jointRotation = Quaternion.Inverse (finger_.Bone ((Bone.BoneType)(joint_type)).Basis.Rotation (mirror_z_axis_)) 
+        * finger_.Bone ((Bone.BoneType)(joint_type + 1)).Basis.Rotation (mirror_z_axis_);
+    } else if (bones [joint_type] && bones [joint_type + 1]) {
+      jointRotation = Quaternion.Inverse (GetBoneRotation (joint_type)) * GetBoneRotation (joint_type + 1);
+    }
+    // Stretch is a rotation around the X axis of the base bone
+    // Positive stretch opens joints
+    float stretchAngle = -jointRotation.eulerAngles.x;
+    if (stretchAngle <= -180f) {
+      stretchAngle += 360f;
+    }
+    // NOTE: eulerAngles range is [0, 360) so stretchAngle > +180f will not occur.
+    return stretchAngle;
+  }
+
+  /**
+   * Returns Mecanim spread angle, which only applies to joint_type = 0
+   * NOTE: Positive spread is towards thumb for index and middle,
+   * but is in the opposite direction for the ring and pinky.
+   * For the thumb negative spread rotates the thumb in to the palm.
+   * */
+  public float GetFingerJointSpreadMecanim() {
+    // The successive actions of local rotations on a vector yield the global rotation,
+    // so the inverse of the parent rotation appears on the left.
+    Quaternion jointRotation = Quaternion.identity;
+    if (finger_ != null) {
+      jointRotation = Quaternion.Inverse (finger_.Bone ((Bone.BoneType)(0)).Basis.Rotation (mirror_z_axis_)) 
+        * finger_.Bone ((Bone.BoneType)(1)).Basis.Rotation (mirror_z_axis_);
+    } else if (bones [0] && bones [1]) {
+      jointRotation = Quaternion.Inverse (GetBoneRotation (0)) * GetBoneRotation (1);
+    }
+    // Spread is a rotation around the Y axis of the base bone when joint_type = 0
+    float spreadAngle = 0f;
+    Finger.FingerType fType = fingerType;
+    if (finger_ != null) { 
+      fingerType = finger_.Type;
+    }
+
+    if (fType == Finger.FingerType.TYPE_INDEX ||
+      fType == Finger.FingerType.TYPE_MIDDLE) {
+      spreadAngle = jointRotation.eulerAngles.y;
+      if (spreadAngle > 180f) {
+        spreadAngle -= 360f;
+      }
+      // NOTE: eulerAngles range is [0, 360) so spreadAngle <= -180f will not occur.
+    }
+    if (fType == Finger.FingerType.TYPE_THUMB ||
+      fType == Finger.FingerType.TYPE_RING ||
+      fType == Finger.FingerType.TYPE_PINKY) {
+      spreadAngle = -jointRotation.eulerAngles.y;
+      if (spreadAngle <= -180f) {
+        spreadAngle += 360f;
+      }
+      // NOTE: eulerAngles range is [0, 360) so spreadAngle > +180f will not occur.
+    }
+    return spreadAngle;
+  }
+}