view Orchestland/Assets/LeapMotion/Scripts/Hands/HandModel.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 source

/******************************************************************************\
* 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 hand models, both graphics and physics.
* 
* This class serves as the interface between the HandController object
* and the concrete hand object containing the graphics and physics of a hand.
*
* Subclasses of HandModel must implement InitHand() and UpdateHand(). The UpdateHand()
* function is called in the Unity Update() phase for graphics HandModel instances;
* and in the Unity FixedUpdate() phase for physics objects. InitHand() is called once,
* when the hand is created and is followed by a call to UpdateHand().
*/
public abstract class HandModel : MonoBehaviour {

  /** The number of fingers on a hand.*/
  public const int NUM_FINGERS = 5;

  /** The model width of the hand in meters. This value is used with the measured value 
  * of the user's hand to scale the model proportionally.
  */
  public float handModelPalmWidth = 0.085f;
  /** The array of finger objects for this hand. The array is ordered from thumb (element 0) to pinky (element 4).*/
  public FingerModel[] fingers = new FingerModel[NUM_FINGERS];

  // Unity references
  public Transform palm;
  public Transform forearm;
  public Transform wristJoint;
  public Transform elbowJoint;
  
  // Leap references
  /** The Leap Hand object this hand model represents. */
  protected Hand hand_;
  /** The parent HandController object for this hand. */
  protected HandController controller_;

  /** Whether the parent HandController instance has been set to mirror across the z axis.*/
  protected bool mirror_z_axis_ = false;

  /** 
  * Calculates the offset between the wrist position and the controller based
  * on the HandController.handMovementScale property and the Leap hand wrist position.
  */
  public Vector3 GetHandOffset() {
    if (controller_ == null || hand_ == null)
      return Vector3.zero;

    Vector3 additional_movement = controller_.handMovementScale - Vector3.one;
    Vector3 scaled_wrist_position = Vector3.Scale(additional_movement, hand_.WristPosition.ToUnityScaled(mirror_z_axis_));

    return controller_.transform.TransformPoint(scaled_wrist_position) -
           controller_.transform.position;
  }

  /** Calculates the position of the palm relative to the controller.
  * @returns A Vector3 containing the Unity coordinates of the palm position.
  */
  public Vector3 GetPalmPosition() {
    if (controller_ != null && hand_ != null) {
      return controller_.transform.TransformPoint (hand_.PalmPosition.ToUnityScaled (mirror_z_axis_)) + GetHandOffset ();
    }
    if (palm) {
      return palm.position;
    }
    return Vector3.zero;
  }

  /** Calculates the rotation of the hand relative to the controller.
  * @returns A Quaternion representing the rotation of the hand relative to the controller. 
  */
  public Quaternion GetPalmRotation() {
    if (controller_ != null && hand_ != null) {
      return controller_.transform.rotation * hand_.Basis.Rotation(mirror_z_axis_);
    }
    if (palm) {
      return palm.rotation;
    }
    return Quaternion.identity;
  }

  /** Calculates the direction vector of the hand relative to the controller.
  * @returns A Vector3 representing the direction of the hand relative to the controller.
  */
  public Vector3 GetPalmDirection() {
    if (controller_ != null && hand_ != null) {
      return controller_.transform.TransformDirection(hand_.Direction.ToUnity(mirror_z_axis_));
    }
    if (palm) {
      return palm.forward;
    }
    return Vector3.forward;
  }

  /** Calculates the normal vector projecting from the hand relative to the controller.
  * @returns A Vector3 representing the vector perpendicular to the palm.
  */
  public Vector3 GetPalmNormal() {
    if (controller_ != null && hand_ != null) {
      return controller_.transform.TransformDirection(hand_.PalmNormal.ToUnity(mirror_z_axis_));
    }
    if (palm) {
      return -palm.up;
    }
    return -Vector3.up;
  }

  /** Calculates the direction vector of the forearm relative to the controller.
  * @returns A Vector3 representing the direction of the forearm (pointing from elbow to wrist).
  */
  public Vector3 GetArmDirection() {
    if (controller_ != null && hand_ != null) {
      return controller_.transform.TransformDirection(hand_.Arm.Direction.ToUnity(mirror_z_axis_));
    }
    if (forearm) {
      return forearm.forward;
    }
    return Vector3.forward;
  }

  /** Calculates the center of the forearm relative to the controller.
  * @returns A Vector3 containing the Unity coordinates of the center of the forearm.
  */
  public Vector3 GetArmCenter() {
    if (controller_ != null && hand_ != null) {
      Vector leap_center = 0.5f * (hand_.Arm.WristPosition + hand_.Arm.ElbowPosition);
      return controller_.transform.TransformPoint (leap_center.ToUnityScaled (mirror_z_axis_)) + GetHandOffset ();
    }
    if (forearm) {
      return forearm.position;
    }
    return Vector3.zero;
  }

  /** Returns the measured length of the forearm in meters.*/
  public float GetArmLength() {
    return (hand_.Arm.WristPosition - hand_.Arm.ElbowPosition).Magnitude * UnityVectorExtension.INPUT_SCALE;
  }
  
  /** Returns the measured width of the forearm in meters.*/
  public float GetArmWidth() {
    return hand_.Arm.Width * UnityVectorExtension.INPUT_SCALE;
  }

  /** Calculates the position of the elbow relative to the controller.
  * @returns A Vector3 containing the Unity coordinates of the elbow.
  */
  public Vector3 GetElbowPosition() {
    if (controller_ != null && hand_ != null) {
      Vector3 local_position = hand_.Arm.ElbowPosition.ToUnityScaled (mirror_z_axis_);
      return controller_.transform.TransformPoint (local_position) + GetHandOffset ();
    }
    if (elbowJoint) {
      return elbowJoint.position;
    }
    return Vector3.zero;
  }

  /** Calculates the position of the wrist relative to the controller.
  * @returns A Vector3 containing the Unity coordinates of the wrist.
  */
  public Vector3 GetWristPosition() {
    if (controller_ != null && hand_ != null) {
      Vector3 local_position = hand_.Arm.WristPosition.ToUnityScaled (mirror_z_axis_);
      return controller_.transform.TransformPoint (local_position) + GetHandOffset ();
    }
    if (wristJoint) {
      return wristJoint.position;
    }
    return Vector3.zero;
  }

  /** Calculates the rotation of the forearm relative to the controller.
  * @returns A Quaternion representing the rotation of the arm relative to the controller. 
  */
  public Quaternion GetArmRotation() {
    if (controller_ != null && hand_ != null) {
      Quaternion local_rotation = hand_.Arm.Basis.Rotation (mirror_z_axis_);
      return controller_.transform.rotation * local_rotation;
    }
    if (forearm) {
      return forearm.rotation;
    }
    return Quaternion.identity;
  }

  /** 
  * Returns the Leap Hand object represented by this HandModel.
  * Note that any physical quantities and directions obtained from the
  * Leap Hand object are relative to the Leap Motion coordinate system,
  * which uses a right-handed axes and units of millimeters.
  */
  public Hand GetLeapHand() {
    return hand_;
  }

  /**
  * Assigns a Leap Hand object to this hand model.
  * Note that the Leap Hand objects are recreated every frame. The parent 
  * HandController calls this method to set or update the underlying hand.
  */
  public void SetLeapHand(Hand hand) {
    hand_ = hand;
    for (int i = 0; i < fingers.Length; ++i) {
      if (fingers[i] != null) {
        fingers[i].SetLeapHand(hand_);
        fingers[i].SetOffset(GetHandOffset());
      }
    }
  }

  /** 
  * Sets the mirror z-axis flag for this Hand Model and its fingers.
  * 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;
    for (int i = 0; i < fingers.Length; ++i) {
      if (fingers[i] != null)
        fingers[i].MirrorZAxis(mirror);
    }
  }

  /** Whether this hand is currently mirrored.*/
  public bool IsMirrored() {
    return mirror_z_axis_;
  }

  /** The parent HandController object of this hand.*/
  public HandController GetController() {
    return controller_;
  }

  /** Sets the parent HandController object. */
  public void SetController(HandController controller) {
    controller_ = controller;
    for (int i = 0; i < fingers.Length; ++i) {
      if (fingers[i] != null)
        fingers[i].SetController(controller_);
    }
  }

  /** 
  * Implement this function to initialise this hand after it is created.
  * This function is called by the HandController during the Unity Update() phase when a new hand is detected
  * by the Leap Motion device.
  */
  public virtual void InitHand() {
    for (int f = 0; f < fingers.Length; ++f) {
      if (fingers[f] != null) {
        fingers[f].fingerType = (Finger.FingerType)f;
        fingers[f].InitFinger();
      }
    }

    UpdateHand ();
  }

  /** 
  * Implement this function to update this hand once every game loop.
  * For HandModel instances assigned to the HandController graphics hand list, the HandController calls this 
  * function during the Unity Update() phase. For HandModel instances in the physics hand list, the HandController
  * calls this function in the FixedUpdate() phase.
  */
  public abstract void UpdateHand();
}