This commit is contained in:
SDraw 2022-08-02 11:01:57 +03:00
parent 37c4d9f1bb
commit e910401fbf
No known key found for this signature in database
GPG key ID: BB95B4DAB2BB8BB5
66 changed files with 416 additions and 12 deletions

101
ml_lme/vendor/LeapCSharp/Arm.cs vendored Normal file
View file

@ -0,0 +1,101 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The Arm class represents the forearm.
/// </summary>
[Serializable]
public class Arm : Bone, IEquatable<Arm>
{
/// <summary>
/// Constructs a default Arm object.
/// Get valid Arm objects from a Hand object.
///
/// @since 2.0.3
/// </summary>
public Arm() : base() { }
/// <summary>
/// Constructs a new Arm object.
/// @since 3.0
/// </summary>
public Arm(Vector elbow,
Vector wrist,
Vector center,
Vector direction,
float length,
float width,
LeapQuaternion rotation)
: base(elbow,
wrist,
center,
direction,
length,
width,
BoneType.TYPE_METACARPAL, //ignored for arms
rotation)
{ }
/// <summary>
/// Compare Arm object equality.
/// Two Arm objects are equal if and only if both Arm objects represent the
/// exact same physical arm in the same frame and both Arm objects are valid.
/// @since 2.0.3
/// </summary>
public bool Equals(Arm other)
{
return Equals(other as Bone);
}
/// <summary>
/// A string containing a brief, human readable description of the Arm object.
/// @since 2.0.3
/// </summary>
public override string ToString()
{
return "Arm";
}
/// <summary>
/// The position of the elbow.
/// If not in view, the elbow position is estimated based on typical human
/// anatomical proportions.
///
/// @since 2.0.3
/// </summary>
public Vector ElbowPosition
{
get
{
return base.PrevJoint;
}
}
/// <summary>
/// The position of the wrist.
///
/// Note that the wrist position is not collocated with the end of any bone in
/// the hand. There is a gap of a few centimeters since the carpal bones are
/// not included in the skeleton model.
///
/// @since 2.0.3
/// </summary>
public Vector WristPosition
{
get
{
return base.NextJoint;
}
}
}
}

183
ml_lme/vendor/LeapCSharp/Bone.cs vendored Normal file
View file

@ -0,0 +1,183 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The Bone class represents a tracked bone.
///
/// All fingers contain 4 bones that make up the anatomy of the finger.
/// Get valid Bone objects from a Finger object.
///
/// Bones are ordered from base to tip, indexed from 0 to 3. Additionally, the
/// bone's Type enum may be used to index a specific bone anatomically.
///
/// The thumb does not have a base metacarpal bone and therefore contains a valid,
/// zero length bone at that location.
/// @since 2.0
/// </summary>
[Serializable]
public class Bone : IEquatable<Bone>
{
/// <summary>
/// Constructs a default invalid Bone object.
///
/// @since 2.0
/// </summary>
public Bone()
{
Type = BoneType.TYPE_INVALID;
}
/// <summary>
/// Constructs a new Bone object.
/// @since 3.0
/// </summary>
public Bone(Vector prevJoint,
Vector nextJoint,
Vector center,
Vector direction,
float length,
float width,
Bone.BoneType type,
LeapQuaternion rotation)
{
PrevJoint = prevJoint;
NextJoint = nextJoint;
Center = center;
Direction = direction;
Rotation = rotation;
Length = length;
Width = width;
Type = type;
}
/// <summary>
/// Compare Bone object equality.
///
/// Two Bone objects are equal if and only if both Bone objects represent the
/// exact same physical bone in the same frame and both Bone objects are valid.
/// @since 2.0
/// </summary>
public bool Equals(Bone other)
{
return Center == other.Center && Direction == other.Direction && Length == other.Length;
}
/// <summary>
/// A string containing a brief, human readable description of the Bone object.
/// @since 2.0
/// </summary>
public override string ToString()
{
return Enum.GetName(typeof(BoneType), this.Type) + " bone";
}
/// <summary>
/// The base of the bone, closest to the wrist.
/// In anatomical terms, this is the proximal end of the bone.
/// @since 2.0
/// </summary>
public Vector PrevJoint;
/// <summary>
/// The end of the bone, closest to the finger tip.
/// In anatomical terms, this is the distal end of the bone.
/// @since 2.0
/// </summary>
public Vector NextJoint;
/// <summary>
/// The midpoint of the bone.
/// @since 2.0
/// </summary>
public Vector Center;
/// <summary>
/// The normalized direction of the bone from base to tip.
/// @since 2.0
/// </summary>
public Vector Direction;
/// <summary>
/// The estimated length of the bone.
/// @since 2.0
/// </summary>
public float Length;
/// <summary>
/// The average width of the flesh around the bone.
/// @since 2.0
/// </summary>
public float Width;
/// <summary>
/// The type of this bone.
/// @since 2.0
/// </summary>
public BoneType Type;
/// <summary>
/// The orientation of this Bone as a Quaternion.
/// @since 2.0
/// </summary>
public LeapQuaternion Rotation;
/// <summary>
/// The orthonormal basis vectors for this Bone as a Matrix.
/// The orientation of this Bone as a Quaternion.
///
/// Basis vectors specify the orientation of a bone.
///
/// **xBasis** Perpendicular to the longitudinal axis of the
/// bone; exits the sides of the finger.
///
/// **yBasis or up vector** Perpendicular to the longitudinal
/// axis of the bone; exits the top and bottom of the finger. More positive
/// in the upward direction.
///
/// **zBasis** Aligned with the longitudinal axis of the bone.
/// More positive toward the base of the finger.
///
/// The bases provided for the right hand use the right-hand rule; those for
/// the left hand use the left-hand rule. Thus, the positive direction of the
/// x-basis is to the right for the right hand and to the left for the left
/// hand. You can change from right-hand to left-hand rule by multiplying the
/// z basis vector by -1.
///
/// You can use the basis vectors for such purposes as measuring complex
/// finger poses and skeletal animation.
///
/// Note that converting the basis vectors directly into a quaternion
/// representation is not mathematically valid. If you use quaternions,
/// create them from the derived rotation matrix not directly from the bases.
///
/// @since 2.0
/// </summary>
public LeapTransform Basis { get { return new LeapTransform(PrevJoint, Rotation); } }
/// <summary>
/// Enumerates the type of bones.
///
/// Members of this enumeration are returned by Bone.Type() to identify a
/// Bone object.
/// @since 2.0
/// </summary>
public enum BoneType
{
TYPE_INVALID = -1,
TYPE_METACARPAL = 0,
TYPE_PROXIMAL = 1,
TYPE_INTERMEDIATE = 2,
TYPE_DISTAL = 3
}
}
}

View file

@ -0,0 +1,106 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
using System;
namespace Leap
{
/// <summary>
/// Various C# extensions used by the Leap C# classes.
///
/// @since 3.0
/// </summary>
public static class CSharpExtensions
{
/// <summary>
/// Compares whether two floating point numbers are within an epsilon value of each other.
/// @since 3.0
/// </summary>
public static bool NearlyEquals(this float a, float b, float epsilon = Constants.EPSILON)
{
float absA = Math.Abs(a);
float absB = Math.Abs(b);
float diff = Math.Abs(a - b);
if (a == b)
{ // shortcut, handles infinities
return true;
}
else if (a == 0 || b == 0 || diff < float.MinValue)
{
// a or b is zero or both are extremely close to it
// relative error is less meaningful here
return diff < (epsilon * float.MinValue);
}
else
{ // use relative error
return diff / (absA + absB) < epsilon;
}
}
/// <summary>
/// Reports whether this object has the specified method.
/// @since 3.0
/// </summary>
public static bool HasMethod(this object objectToCheck, string methodName)
{
var type = objectToCheck.GetType();
return type.GetMethod(methodName) != null;
}
/// <summary>
/// Returns the ordinal index of this enumeration item.
/// @since 3.0
/// </summary>
public static int indexOf(this Enum enumItem)
{
return Array.IndexOf(Enum.GetValues(enumItem.GetType()), enumItem);
}
/// <summary>
/// Gets the item at the ordinal position in this enumeration.
/// @since 3.0
/// </summary>
public static T itemFor<T>(this int ordinal)
{
T[] values = (T[])Enum.GetValues(typeof(T));
return values[ordinal];
}
/// <summary>
/// Convenience function to consolidate event dispatching boilerplate code.
/// @since 3.0
/// </summary>
public static void Dispatch<T>(this EventHandler<T> handler,
object sender, T eventArgs) where T : EventArgs
{
if (handler != null) handler(sender, eventArgs);
}
/// <summary>
/// Convenience function to consolidate event dispatching boilerplate code.
/// Events are dispatched on the message queue of a threads' synchronization
/// context, if possible.
/// @since 3.0
/// </summary>
public static void DispatchOnContext<T>(this EventHandler<T> handler, object sender,
System.Threading.SynchronizationContext context,
T eventArgs) where T : EventArgs
{
if (handler != null)
{
if (context != null)
{
System.Threading.SendOrPostCallback evt = (spc_args) => { handler(sender, spc_args as T); };
context.Post(evt, eventArgs);
}
else
handler(sender, eventArgs);
}
}
}
}

View file

@ -0,0 +1,110 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace LeapInternal
{
//TODO add test for thread safety
/**
* A Limited capacity, circular LIFO buffer that wraps around
* when full. Supports indexing to get older items. Array-backed.
* *
* Unlike many collections, objects are never removed, just overwritten when
* the buffer cycles back to their array location.
*
* Object types used must have default parameterless constructor. It should be obvious that
* such default objects are invalid. I.e. for Leap API objects, the IsValid property should be false.
*/
public class CircularObjectBuffer<T> where T : new()
{
private T[] array;
private int current = 0;
private object locker = new object();
public int Count { get; private set; }
public int Capacity { get; private set; }
public bool IsEmpty { get; private set; }
public CircularObjectBuffer(int capacity)
{
Capacity = capacity;
array = new T[this.Capacity];
current = 0;
Count = 0;
IsEmpty = true;
}
/** Put an item at the head of the list. Once full, this will overwrite the oldest item. */
public virtual void Put(ref T item)
{
lock (locker)
{
if (!IsEmpty)
{
current++;
if (current >= Capacity)
{
current = 0;
}
}
if (Count < Capacity)
Count++;
lock (array)
{
array[current] = item;
}
IsEmpty = false;
}
}
/** Get the item indexed backward from the head of the list */
public void Get(out T t, int index = 0)
{
lock (locker)
{
if (IsEmpty || (index > Count - 1) || index < 0)
{
t = new T(); //default(T);
}
else
{
int effectiveIndex = current - index;
if (effectiveIndex < 0)
{
effectiveIndex += Capacity;
}
t = array[effectiveIndex];
}
}
}
/** Increase */
public void Resize(int newCapacity)
{
lock (locker)
{
if (newCapacity <= Capacity)
{
return;
}
T[] newArray = new T[newCapacity];
int j = 0;
for (int i = Count - 1; i >= 0; i--)
{
T t;
Get(out t, i);
newArray[j++] = t;
}
this.array = newArray;
this.Capacity = newCapacity;
}
}
}
}

195
ml_lme/vendor/LeapCSharp/Config.cs vendored Normal file
View file

@ -0,0 +1,195 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using LeapInternal;
using System;
using System.Collections.Generic;
/// <summary>
/// The Config class provides access to Leap Motion system configuration information.
///
/// @since 1.0
/// </summary>
public class Config
{
private Connection _connection;
private Dictionary<UInt32, object> _transactions = new Dictionary<UInt32, object>();
/// <summary>
/// Creates a new Config object for setting runtime configuration settings.
///
/// Note that the Controller.Config provides a properly initialized Config object already.
/// @since 3.0
/// </summary>
public Config(Connection.Key connectionKey)
{
_connection = Connection.GetConnection(connectionKey);
_connection.LeapConfigChange += handleConfigChange;
_connection.LeapConfigResponse += handleConfigResponse;
}
public Config(int connectionId) : this(new Connection.Key(connectionId)) { }
private void handleConfigChange(object sender, ConfigChangeEventArgs eventArgs)
{
object actionDelegate;
if (_transactions.TryGetValue(eventArgs.RequestId, out actionDelegate))
{
Action<bool> changeAction = actionDelegate as Action<bool>;
changeAction(eventArgs.Succeeded);
_transactions.Remove(eventArgs.RequestId);
}
}
private void handleConfigResponse(object sender, SetConfigResponseEventArgs eventArgs)
{
object actionDelegate = new object();
if (_transactions.TryGetValue(eventArgs.RequestId, out actionDelegate))
{
switch (eventArgs.DataType)
{
case ValueType.TYPE_BOOLEAN:
Action<bool> boolAction = actionDelegate as Action<bool>;
boolAction((int)eventArgs.Value != 0);
break;
case ValueType.TYPE_FLOAT:
Action<float> floatAction = actionDelegate as Action<float>;
floatAction((float)eventArgs.Value);
break;
case ValueType.TYPE_INT32:
Action<Int32> intAction = actionDelegate as Action<Int32>;
intAction((Int32)eventArgs.Value);
break;
case ValueType.TYPE_STRING:
Action<string> stringAction = actionDelegate as Action<string>;
stringAction((string)eventArgs.Value);
break;
default:
break;
}
_transactions.Remove(eventArgs.RequestId);
}
}
/// <summary>
/// Requests a configuration value.
///
/// You must provide an action to take when the Leap service returns the config value.
/// The Action delegate must take a parameter matching the config value type. The current
/// value of the setting is passed to this delegate.
///
/// @since 3.0
/// </summary>
public bool Get<T>(string key, Action<T> onResult)
{
uint requestId = _connection.GetConfigValue(key);
if (requestId > 0)
{
_transactions.Add(requestId, onResult);
return true;
}
return false;
}
/// <summary>
/// Sets a configuration value.
///
/// You must provide an action to take when the Leap service sets the config value.
/// The Action delegate must take a boolean parameter. The service calls this delegate
/// with the value true if the setting was changed successfully and false, otherwise.
///
/// @since 3.0
/// </summary>
public bool Set<T>(string key, T value, Action<bool> onResult) where T : IConvertible
{
uint requestId = _connection.SetConfigValue<T>(key, value);
if (requestId > 0)
{
_transactions.Add(requestId, onResult);
return true;
}
return false;
}
[Obsolete("Use the generic Set<T> method instead.")]
public ValueType Type(string key)
{
return ValueType.TYPE_UNKNOWN;
}
[Obsolete("Use the generic Get<T> method instead.")]
public bool GetBool(string key)
{
return false;
}
[Obsolete("Use the generic Set<T> method instead.")]
public bool SetBool(string key, bool value)
{
return false;
}
[Obsolete("Use the generic Get<T> method instead.")]
public bool GetInt32(string key)
{
return false;
}
[Obsolete("Use the generic Set<T> method instead.")]
public bool SetInt32(string key, int value)
{
return false;
}
[Obsolete("Use the generic Get<T> method instead.")]
public bool GetFloat(string key)
{
return false;
}
[Obsolete("Use the generic Set<T> method instead.")]
public bool SetFloat(string key, float value)
{
return false;
}
[Obsolete("Use the generic Get<T> method instead.")]
public bool GetString(string key)
{
return false;
}
[Obsolete("Use the generic Set<T> method instead.")]
public bool SetString(string key, string value)
{
return false;
}
[Obsolete]
public bool Save()
{
return false;
}
/// <summary>
/// Enumerates the possible data types for configuration values.
/// @since 1.0
/// </summary>
public enum ValueType
{
TYPE_UNKNOWN = 0,
TYPE_BOOLEAN = 1,
TYPE_INT32 = 2,
TYPE_FLOAT = 6,
TYPE_STRING = 8,
}
}
}

1312
ml_lme/vendor/LeapCSharp/Connection.cs vendored Normal file

File diff suppressed because it is too large Load diff

1034
ml_lme/vendor/LeapCSharp/Controller.cs vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,142 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace LeapInternal
{
using Leap;
public static class CopyFromLeapCExtensions
{
/**
* Copies the data from an internal tracking message into a frame.
*
* @param trackingMsg The internal tracking message with the data to be copied into this frame.
*/
public static Frame CopyFrom(this Frame frame, ref LEAP_TRACKING_EVENT trackingMsg)
{
frame.Id = (long)trackingMsg.info.frame_id;
frame.Timestamp = (long)trackingMsg.info.timestamp;
frame.CurrentFramesPerSecond = trackingMsg.framerate;
frame.ResizeHandList((int)trackingMsg.nHands);
for (int i = frame.Hands.Count; i-- != 0;)
{
LEAP_HAND hand;
StructMarshal<LEAP_HAND>.ArrayElementToStruct(trackingMsg.pHands, i, out hand);
frame.Hands[i].CopyFrom(ref hand, frame.Id);
}
return frame;
}
/**
* Copies the data from an internal hand definition into a hand.
*
* @param leapHand The internal hand definition to be copied into this hand.
* @param frameId The frame id of the frame this hand belongs to.
*/
public static Hand CopyFrom(this Hand hand, ref LEAP_HAND leapHand, long frameId)
{
hand.FrameId = frameId;
hand.Id = (int)leapHand.id;
hand.Arm.CopyFrom(leapHand.arm, Bone.BoneType.TYPE_INVALID);
hand.Confidence = leapHand.confidence;
hand.GrabStrength = leapHand.grab_strength;
hand.GrabAngle = leapHand.grab_angle;
hand.PinchStrength = leapHand.pinch_strength;
hand.PinchDistance = leapHand.pinch_distance;
hand.PalmWidth = leapHand.palm.width;
hand.IsLeft = leapHand.type == eLeapHandType.eLeapHandType_Left;
hand.TimeVisible = (float)(leapHand.visible_time * 1e-6);
hand.PalmPosition = leapHand.palm.position.ToLeapVector();
hand.StabilizedPalmPosition = leapHand.palm.stabilized_position.ToLeapVector();
hand.PalmVelocity = leapHand.palm.velocity.ToLeapVector();
hand.PalmNormal = leapHand.palm.normal.ToLeapVector();
hand.Rotation = leapHand.palm.orientation.ToLeapQuaternion();
hand.Direction = leapHand.palm.direction.ToLeapVector();
hand.WristPosition = hand.Arm.NextJoint;
hand.Fingers[0].CopyFrom(leapHand.thumb, Leap.Finger.FingerType.TYPE_THUMB, hand.Id, hand.TimeVisible);
hand.Fingers[1].CopyFrom(leapHand.index, Leap.Finger.FingerType.TYPE_INDEX, hand.Id, hand.TimeVisible);
hand.Fingers[2].CopyFrom(leapHand.middle, Leap.Finger.FingerType.TYPE_MIDDLE, hand.Id, hand.TimeVisible);
hand.Fingers[3].CopyFrom(leapHand.ring, Leap.Finger.FingerType.TYPE_RING, hand.Id, hand.TimeVisible);
hand.Fingers[4].CopyFrom(leapHand.pinky, Leap.Finger.FingerType.TYPE_PINKY, hand.Id, hand.TimeVisible);
return hand;
}
/**
* Copies the data from an internal finger definition into a finger.
*
* @param leapBone The internal finger definition to be copied into this finger.
* @param type The finger type of this finger.
* @param frameId The frame id of the frame this finger belongs to.
* @param handId The hand id of the hand this finger belongs to.
* @param timeVisible The time in seconds that this finger has been visible.
*/
public static Finger CopyFrom(this Finger finger, LEAP_DIGIT leapBone, Finger.FingerType type, int handId, float timeVisible)
{
finger.Id = (handId * 10) + leapBone.finger_id;
finger.HandId = handId;
finger.TimeVisible = timeVisible;
Bone metacarpal = finger.bones[0];
Bone proximal = finger.bones[1];
Bone intermediate = finger.bones[2];
Bone distal = finger.bones[3];
metacarpal.CopyFrom(leapBone.metacarpal, Leap.Bone.BoneType.TYPE_METACARPAL);
proximal.CopyFrom(leapBone.proximal, Leap.Bone.BoneType.TYPE_PROXIMAL);
intermediate.CopyFrom(leapBone.intermediate, Leap.Bone.BoneType.TYPE_INTERMEDIATE);
distal.CopyFrom(leapBone.distal, Leap.Bone.BoneType.TYPE_DISTAL);
finger.TipPosition = distal.NextJoint;
finger.Direction = intermediate.Direction;
finger.Width = intermediate.Width;
finger.Length = (leapBone.finger_id == 0 ? 0.0f : 0.5f * proximal.Length) + intermediate.Length + 0.77f * distal.Length; //The values 0.5 for proximal and 0.77 for distal are used in platform code for this calculation
finger.IsExtended = leapBone.is_extended != 0;
finger.Type = type;
return finger;
}
/**
* Copies the data from an internal bone definition into a bone.
*
* @param leapBone The internal bone definition to be copied into this bone.
* @param type The bone type of this bone.
*/
public static Bone CopyFrom(this Bone bone, LEAP_BONE leapBone, Bone.BoneType type)
{
bone.Type = type;
bone.PrevJoint = leapBone.prev_joint.ToLeapVector();
bone.NextJoint = leapBone.next_joint.ToLeapVector();
bone.Direction = (bone.NextJoint - bone.PrevJoint);
bone.Length = bone.Direction.Magnitude;
if (bone.Length < float.Epsilon)
{
bone.Direction = Vector.Zero;
}
else
{
bone.Direction /= bone.Length;
}
bone.Center = (bone.PrevJoint + bone.NextJoint) / 2.0f;
bone.Rotation = leapBone.rotation.ToLeapQuaternion();
bone.Width = leapBone.width;
return bone;
}
}
}

View file

@ -0,0 +1,120 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
public static class CopyFromOtherExtensions
{
/**
* Copies the data from a source frame into a frame. After the operation is
* complete, the frame will be identical to the source frame.
*
* @param source The source frame that is copied into a frame.
*/
public static Frame CopyFrom(this Frame frame, Frame source)
{
frame.Id = source.Id;
frame.Timestamp = source.Timestamp;
frame.CurrentFramesPerSecond = source.CurrentFramesPerSecond;
frame.DeviceID = source.DeviceID;
frame.ResizeHandList(source.Hands.Count);
for (int i = frame.Hands.Count; i-- != 0;)
{
frame.Hands[i].CopyFrom(source.Hands[i]);
}
return frame;
}
/*
* Copies the data from a source hand into a hand. After the operation is
* complete, the hand will be identical to the source hand.
*
* @param source The source hand that is copied into a hand.
*/
public static Hand CopyFrom(this Hand hand, Hand source)
{
hand.Id = source.Id;
hand.Confidence = source.Confidence;
hand.GrabStrength = source.GrabStrength;
hand.GrabAngle = source.GrabAngle;
hand.Rotation = source.Rotation;
hand.PinchStrength = source.PinchStrength;
hand.PinchDistance = source.PinchDistance;
hand.PalmWidth = source.PalmWidth;
hand.IsLeft = source.IsLeft;
hand.TimeVisible = source.TimeVisible;
hand.PalmPosition = source.PalmPosition;
hand.StabilizedPalmPosition = source.StabilizedPalmPosition;
hand.PalmVelocity = source.PalmVelocity;
hand.PalmNormal = source.PalmNormal;
hand.Direction = source.Direction;
hand.WristPosition = source.WristPosition;
hand.Arm.CopyFrom(source.Arm);
for (int i = 5; i-- != 0;)
{
hand.Fingers[i].CopyFrom(source.Fingers[i]);
}
return hand;
}
/**
* Copies the data from a source finger into a finger. After the operation is
* complete, the finger will be identical to the source finger.
*
* @param source The source finger that is copied into a finger.
*/
public static Finger CopyFrom(this Finger finger, Finger source)
{
for (int i = 4; i-- != 0;)
{
finger.bones[i].CopyFrom(source.bones[i]);
}
finger.Id = source.Id;
finger.HandId = source.HandId;
finger.TimeVisible = source.TimeVisible;
finger.TipPosition = source.TipPosition;
finger.Direction = source.Direction;
finger.Width = source.Width;
finger.Length = source.Length;
finger.IsExtended = source.IsExtended;
finger.Type = source.Type;
return finger;
}
/**
* Copies the data from a source bone into a bone. After the operation is
* complete, the bone will be identical to the source bone.
*
* @param source The source bone that is copied into a bone.
*/
public static Bone CopyFrom(this Bone bone, Bone source)
{
bone.PrevJoint = source.PrevJoint;
bone.NextJoint = source.NextJoint;
bone.Direction = source.Direction;
bone.Center = source.Center;
bone.Length = source.Length;
bone.Width = source.Width;
bone.Rotation = source.Rotation;
bone.Type = source.Type;
return bone;
}
}
}

338
ml_lme/vendor/LeapCSharp/Device.cs vendored Normal file
View file

@ -0,0 +1,338 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using LeapInternal;
using System;
/// <summary>
/// The Device class represents a physically connected device.
///
/// The Device class contains information related to a particular connected
/// device such as device id, field of view relative to the device,
/// and the position and orientation of the device in relative coordinates.
///
/// The position and orientation describe the alignment of the device relative to the user.
/// The alignment relative to the user is only descriptive. Aligning devices to users
/// provides consistency in the parameters that describe user interactions.
///
/// Note that Device objects can be invalid, which means that they do not contain
/// valid device information and do not correspond to a physical device.
/// @since 1.0
/// </summary>
public class Device :
IEquatable<Device>
{
/// <summary>
/// Constructs a default Device object.
///
/// Get valid Device objects from a DeviceList object obtained using the
/// Controller.Devices() method.
///
/// @since 1.0
/// </summary>
public Device() { }
public Device(IntPtr deviceHandle,
IntPtr internalHandle,
float horizontalViewAngle,
float verticalViewAngle,
float range,
float baseline,
DeviceType type,
bool isStreaming,
uint status,
string serialNumber,
uint deviceID)
{
Handle = deviceHandle;
InternalHandle = internalHandle;
HorizontalViewAngle = horizontalViewAngle;
VerticalViewAngle = verticalViewAngle;
Range = range;
Baseline = baseline;
Type = type;
IsStreaming = isStreaming;
SerialNumber = serialNumber;
DeviceID = deviceID;
UpdateStatus((eLeapDeviceStatus)status);
}
public Device(IntPtr deviceHandle,
IntPtr internalHandle,
float horizontalViewAngle,
float verticalViewAngle,
float range,
float baseline,
DeviceType type,
bool isStreaming,
uint status,
string serialNumber) : this(deviceHandle, internalHandle, horizontalViewAngle,
verticalViewAngle, range, baseline, type, isStreaming, status, serialNumber, 0)
{
}
/// <summary>
/// For internal use only.
/// </summary>
public void Update(
float horizontalViewAngle,
float verticalViewAngle,
float range,
float baseline,
uint status,
string serialNumber)
{
HorizontalViewAngle = horizontalViewAngle;
VerticalViewAngle = verticalViewAngle;
Range = range;
Baseline = baseline;
SerialNumber = serialNumber;
UpdateStatus((eLeapDeviceStatus)status);
}
/// <summary>
/// For internal use only.
/// </summary>
public void Update(Device updatedDevice)
{
HorizontalViewAngle = updatedDevice.HorizontalViewAngle;
VerticalViewAngle = updatedDevice.VerticalViewAngle;
Range = updatedDevice.Range;
Baseline = updatedDevice.Baseline;
IsStreaming = updatedDevice.IsStreaming;
SerialNumber = updatedDevice.SerialNumber;
}
/// <summary>
/// Updates the status fields by parsing the uint given by the event
/// </summary>
internal void UpdateStatus(eLeapDeviceStatus status)
{
if ((status & eLeapDeviceStatus.eLeapDeviceStatus_Streaming) == eLeapDeviceStatus.eLeapDeviceStatus_Streaming)
IsStreaming = true;
else
IsStreaming = false;
if ((status & eLeapDeviceStatus.eLeapDeviceStatus_Smudged) == eLeapDeviceStatus.eLeapDeviceStatus_Smudged)
IsSmudged = true;
else
IsSmudged = false;
if ((status & eLeapDeviceStatus.eLeapDeviceStatus_Robust) == eLeapDeviceStatus.eLeapDeviceStatus_Robust)
IsLightingBad = true;
else
IsLightingBad = false;
if ((status & eLeapDeviceStatus.eLeapDeviceStatus_LowResource) == eLeapDeviceStatus.eLeapDeviceStatus_LowResource)
IsLowResource = true;
else
IsLowResource = false;
}
/// <summary>
/// For internal use only.
/// </summary>
public IntPtr Handle { get; private set; }
private IntPtr InternalHandle;
public bool SetPaused(bool pause)
{
eLeapRS result = LeapC.LeapSetPause(Handle, pause);
return result == eLeapRS.eLeapRS_Success;
}
/// <summary>
/// Compare Device object equality.
///
/// Two Device objects are equal if and only if both Device objects represent the
/// exact same Device and both Devices are valid.
///
/// @since 1.0
/// </summary>
public bool Equals(Device other)
{
return SerialNumber == other.SerialNumber;
}
/// <summary>
/// A string containing a brief, human readable description of the Device object.
/// @since 1.0
/// </summary>
public override string ToString()
{
return "Device serial# " + this.SerialNumber;
}
/// <summary>
/// The angle in radians of view along the x axis of this device.
///
/// The Leap Motion controller scans a region in the shape of an inverted pyramid
/// centered at the device's center and extending upwards. The horizontalViewAngle
/// reports the view angle along the long dimension of the device.
///
/// @since 1.0
/// </summary>
public float HorizontalViewAngle { get; private set; }
/// <summary>
/// The angle in radians of view along the z axis of this device.
///
/// The Leap Motion controller scans a region in the shape of an inverted pyramid
/// centered at the device's center and extending upwards. The verticalViewAngle
/// reports the view angle along the short dimension of the device.
///
/// @since 1.0
/// </summary>
public float VerticalViewAngle { get; private set; }
/// <summary>
/// The maximum reliable tracking range from the center of this device.
///
/// The range reports the maximum recommended distance from the device center
/// for which tracking is expected to be reliable. This distance is not a hard limit.
/// Tracking may be still be functional above this distance or begin to degrade slightly
/// before this distance depending on calibration and extreme environmental conditions.
///
/// @since 1.0
/// </summary>
public float Range { get; private set; }
/// <summary>
/// The distance in mm between the center points of the stereo sensors.
///
/// The baseline value, together with the maximum resolution, influence the
/// maximum range.
///
/// @since 2.2.5
/// </summary>
public float Baseline { get; private set; }
/// <summary>
/// Reports whether this device is streaming data to your application.
///
/// Currently only one controller can provide data at a time.
/// @since 1.2
/// </summary>
public bool IsStreaming { get; internal set; }
/// <summary>
/// The device type.
///
/// Use the device type value in the (rare) circumstances that you
/// have an application feature which relies on a particular type of device.
/// Current types of device include the original Leap Motion peripheral,
/// keyboard-embedded controllers, and laptop-embedded controllers.
///
/// @since 1.2
/// </summary>
public DeviceType Type { get; private set; }
/// <summary>
/// An alphanumeric serial number unique to each device.
///
/// Consumer device serial numbers consist of 2 letters followed by 11 digits.
///
/// When using multiple devices, the serial number provides an unambiguous
/// identifier for each device.
/// @since 2.2.2
/// </summary>
public string SerialNumber { get; private set; }
/// <summary>
/// Reports the ID assoicated with the device
///
/// </summary>
public uint DeviceID { get; private set; }
/// <summary>
/// Returns the internal status field of the current device
/// </summary>
protected uint GetDeviceStatus()
{
eLeapRS result;
LEAP_DEVICE_INFO deviceInfo = new LEAP_DEVICE_INFO();
deviceInfo.serial = IntPtr.Zero;
deviceInfo.size = (uint)System.Runtime.InteropServices.Marshal.SizeOf(deviceInfo);
result = LeapC.GetDeviceInfo(InternalHandle, ref deviceInfo);
if (result != eLeapRS.eLeapRS_Success)
return 0;
uint status = deviceInfo.status;
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(deviceInfo.serial);
return status;
}
/// <summary>
/// The software has detected a possible smudge on the translucent cover
/// over the Leap Motion cameras.
/// @since 3.0
/// </summary>
public bool IsSmudged { get; internal set; }
/// <summary>
/// The software has entered low-resource mode
/// @since 3.0
/// </summary>
public bool IsLowResource { get; internal set; }
/// <summary>
/// The software has detected excessive IR illumination, which may interfere
/// with tracking. If robust mode is enabled, the system will enter robust mode when
/// isLightingBad() is true.
/// @since 3.0
/// </summary>
public bool IsLightingBad { get; internal set; }
/// <summary>
/// The available types of Leap Motion controllers.
/// </summary>
public enum DeviceType
{
TYPE_INVALID = -1,
/// <summary>
/// A standalone USB peripheral. The original Leap Motion controller device.
/// @since 1.2
/// </summary>
TYPE_PERIPHERAL = (int)eLeapDeviceType.eLeapDeviceType_Peripheral,
/// <summary>
/// Internal research product codename "Dragonfly".
/// </summary>
TYPE_DRAGONFLY = (int)eLeapDeviceType.eLeapDeviceType_Dragonfly,
/// <summary>
/// Internal research product codename "Nightcrawler".
/// </summary>
TYPE_NIGHTCRAWLER = (int)eLeapDeviceType.eLeapDeviceType_Nightcrawler,
/// <summary>
/// Research product codename "Rigel".
/// </summary>
TYPE_RIGEL = (int)eLeapDeviceType.eLeapDevicePID_Rigel,
/// <summary>
/// The Ultraleap Stereo IR 170 (SIR170) hand tracking module.
/// </summary>
TYPE_SIR170 = (int)eLeapDeviceType.eLeapDevicePID_SIR170,
/// <summary>
/// The Ultraleap 3Di hand tracking camera.
/// </summary>
TYPE_3DI = (int)eLeapDeviceType.eLeapDevicePID_3Di,
[Obsolete]
TYPE_LAPTOP,
[Obsolete]
TYPE_KEYBOARD
}
}
}

126
ml_lme/vendor/LeapCSharp/DeviceList.cs vendored Normal file
View file

@ -0,0 +1,126 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
using System.Collections.Generic;
using System.Linq;
/// <summary>
/// The DeviceList class represents a list of Device objects.
///
/// Get a DeviceList object by calling Controller.Devices().
/// @since 1.0
/// </summary>
public class DeviceList :
List<Device>
{
/// <summary>
/// Constructs an empty list of devices.
/// @since 1.0
/// </summary>
public DeviceList() { }
/// <summary>
/// For internal use only.
/// </summary>
public Device FindDeviceByHandle(IntPtr deviceHandle)
{
for (int d = 0; d < this.Count; d++)
{
if (this[d].Handle == deviceHandle)
return this[d];
}
return null;
}
/// <summary>
/// For internal use only.
/// </summary>
public Device FindDeviceByID(uint deviceID)
{
for (int d = 0; d < this.Count; d++)
{
if (this[d].DeviceID == deviceID)
return this[d];
}
return null;
}
[Obsolete("Multiple devices can now be streaming, use ActiveDevices instead.", false)]
/// <summary>
/// The device that is currently streaming tracking data.
/// If no streaming devices are found, returns null
/// </summary>
public Device ActiveDevice
{
get
{
if (Count == 1)
{
return this[0];
}
for (int d = 0; d < Count; d++)
{
this[d].UpdateStatus(LeapInternal.eLeapDeviceStatus.eLeapDeviceStatus_Streaming);
if (this[d].IsStreaming)
{
return this[d];
}
}
return null;
}
}
/// <summary>
/// The devices that are currently streaming tracking data.
/// If no streaming devices are found, returns null
/// </summary>
public IEnumerable<Device> ActiveDevices
{
get
{
for (int d = 0; d < Count; d++)
{
this[d].UpdateStatus(LeapInternal.eLeapDeviceStatus.eLeapDeviceStatus_Streaming);
}
return this.Where(d => d.IsStreaming);
}
}
/// <summary>
/// For internal use only.
/// </summary>
public void AddOrUpdate(Device device)
{
Device existingDevice = FindDeviceByHandle(device.Handle);
if (existingDevice != null)
{
existingDevice.Update(device);
}
else
{
Add(device);
}
}
/// <summary>
/// Reports whether the list is empty.
/// @since 1.0
/// </summary>
public bool IsEmpty
{
get { return Count == 0; }
}
}
}

View file

@ -0,0 +1,93 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
using System;
namespace Leap
{
/// <summary>
/// The DistortionData class contains the distortion map for correcting the
/// lens distortion of an image.
///
/// The distortion data is an array containing a 64x64 grid of floating point pairs.
/// The distortion map for both sides of an image pair are stacked in
/// the Data array -- the left map first, followed by the right map.
///
/// @since 3.0
/// </summary>
public class DistortionData
{
/// <summary>
/// Constructs an uninitialized distortion object.
/// @since 3.0
/// </summary>
public DistortionData() { }
/// <summary>
/// @since 3.0
/// </summary>
public DistortionData(UInt64 version, float width, float height, float[] data)
{
Version = version;
Width = width;
Height = height;
Data = data;
}
/// <summary>
/// An identifier assigned to the distortion map.
///
/// When the distortion map changes -- either because the devices flips the images
/// to automatically orient the hands or because a different device is plugged in,
/// the version number of the distortion data changes.
///
/// Note that the version always increases. If the images change orientation and then
/// return to their original orientation, a new version number is assigned. Thus
/// the version number can be used to detect when the data has changed, but not
/// to uniquely identify the data.
/// @since 3.0
/// </summary>
public UInt64 Version { get; set; }
/// <summary>
/// The width of the distortion map.
///
/// Currently always 64. Note that there are two floating point values for every point in the map.
/// @since 3.0
/// </summary>
public float Width { get; set; }
/// <summary>
/// The height of the distortion map.
///
/// Currently always 64.
/// @since 3.0
/// </summary>
public float Height { get; set; }
/// <summary>
/// The distortion data.
///
/// @since 3.0
/// </summary>
public float[] Data { get; set; }
/// <summary>
/// Reports whether the distortion data is internally consistent.
/// @since 3.0
/// </summary>
public bool IsValid
{
get
{
if (Data != null &&
Width == LeapInternal.LeapC.DistortionSize &&
Height == LeapInternal.LeapC.DistortionSize &&
Data.Length == Width * Height * 2)
return true;
return false;
}
}
}
}

350
ml_lme/vendor/LeapCSharp/Events.cs vendored Normal file
View file

@ -0,0 +1,350 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using LeapInternal;
using System;
/// <summary>
/// An enumeration defining the types of Leap Motion events.
/// @since 3.0
/// </summary>
public enum LeapEvent
{
EVENT_CONNECTION, //!< A connection event has occurred
EVENT_CONNECTION_LOST, //!< The connection with the service has been lost
EVENT_DEVICE, //!< A device event has occurred
EVENT_DEVICE_FAILURE, //!< A device failure event has occurred
EVENT_DEVICE_LOST, //!< Event asserted when the underlying device object has been lost
EVENT_POLICY_CHANGE, //!< A change in policy occurred
EVENT_CONFIG_RESPONSE, //!< Response to a Config value request
EVENT_CONFIG_CHANGE, //!< Success response to a Config value change
EVENT_FRAME, //!< A tracking frame has been received
EVENT_INTERNAL_FRAME, //!< An internal tracking frame has been received
EVENT_IMAGE_COMPLETE, //!< A requested image is available
EVENT_IMAGE_REQUEST_FAILED, //!< A requested image could not be provided
EVENT_DISTORTION_CHANGE, //!< The distortion matrix used for image correction has changed
EVENT_LOG_EVENT, //!< A diagnostic event has occurred
EVENT_INIT,
EVENT_DROPPED_FRAME,
EVENT_IMAGE, //!< An unrequested image is available
EVENT_POINT_MAPPING_CHANGE,
EVENT_HEAD_POSE
};
/// <summary>
/// A generic object with no arguments beyond the event type.
/// @since 3.0
/// </summary>
public class LeapEventArgs : EventArgs
{
public LeapEventArgs(LeapEvent type)
{
this.type = type;
}
public LeapEvent type { get; set; }
}
/// <summary>
/// Dispatched when a tracking frame is ready.
///
/// Provides the Frame object as an argument.
/// @since 3.0
/// </summary>
public class FrameEventArgs : LeapEventArgs
{
public FrameEventArgs(Frame frame) : base(LeapEvent.EVENT_FRAME)
{
this.frame = frame;
}
public Frame frame { get; set; }
}
public class InternalFrameEventArgs : LeapEventArgs
{
public InternalFrameEventArgs(ref LEAP_TRACKING_EVENT frame) : base(LeapEvent.EVENT_INTERNAL_FRAME)
{
this.frame = frame;
}
public LEAP_TRACKING_EVENT frame { get; set; }
}
/// <summary>
/// Dispatched when loggable events are generated by the service and the
/// service connection code.
///
/// Provides the severity rating, log text, and timestamp as arguments.
/// @since 3.0
/// </summary>
public class LogEventArgs : LeapEventArgs
{
public LogEventArgs(MessageSeverity severity, Int64 timestamp, string message) : base(LeapEvent.EVENT_LOG_EVENT)
{
this.severity = severity;
this.message = message;
this.timestamp = timestamp;
}
public MessageSeverity severity { get; set; }
public Int64 timestamp { get; set; }
public string message { get; set; }
}
/// <summary>
/// Dispatched when a policy change is complete.
///
/// Provides the current and previous policies as arguments.
///
/// @since 3.0
/// </summary>
public class PolicyEventArgs : LeapEventArgs
{
public PolicyEventArgs(UInt64 currentPolicies, UInt64 oldPolicies, bool oldPolicyIsValid, Device device) : base(LeapEvent.EVENT_POLICY_CHANGE)
{
this.currentPolicies = currentPolicies;
this.oldPolicies = oldPolicies;
this.device = device;
}
[Obsolete("Use the constructor that takes the device and oldPolicyIsValid flag")]
public PolicyEventArgs(UInt64 currentPolicies, UInt64 oldPolicies) : base(LeapEvent.EVENT_POLICY_CHANGE)
{
this.currentPolicies = currentPolicies;
this.oldPolicies = oldPolicies;
}
/// <summary>
/// Current policy flags
/// </summary>
public UInt64 currentPolicies { get; set; }
/// <summary>
/// Previous policy flags, if known
/// </summary>
public UInt64 oldPolicies { get; set; }
/// <summary>
/// Is the value for the old policy flags valid / known
/// @since 5.7.0 (plugin)
/// </summary>
public bool oldPolicyIsValid { get; set; }
/// <summary>
/// The device associated with the policy flag change
/// @since 5.7.0 (plugin)
/// </summary>
public Device device { get; set; }
}
/// <summary>
/// Dispatched when the image distortion map changes.
///
/// Provides the new distortion map as an argument.
/// @since 3.0
/// </summary>
public class DistortionEventArgs : LeapEventArgs
{
public DistortionEventArgs(DistortionData distortion, Image.CameraType camera) : base(LeapEvent.EVENT_DISTORTION_CHANGE)
{
this.distortion = distortion;
this.camera = camera;
}
public DistortionData distortion { get; protected set; }
public Image.CameraType camera { get; protected set; }
}
/// <summary>
/// Dispatched when a configuration change is completed.
///
/// Provides the configuration key, whether the change was successful, and the id of the original change request.
/// @since 3.0
/// </summary>
public class ConfigChangeEventArgs : LeapEventArgs
{
public ConfigChangeEventArgs(string config_key, bool succeeded, uint requestId) : base(LeapEvent.EVENT_CONFIG_CHANGE)
{
this.ConfigKey = config_key;
this.Succeeded = succeeded;
this.RequestId = requestId;
}
public string ConfigKey { get; set; }
public bool Succeeded { get; set; }
public uint RequestId { get; set; }
}
/// <summary>
/// Dispatched when a configuration change is completed.
///
/// Provides the configuration key, whether the change was successful, and the id of the original change request.
/// @since 3.0
/// </summary>
public class SetConfigResponseEventArgs : LeapEventArgs
{
public SetConfigResponseEventArgs(string config_key, Config.ValueType dataType, object value, uint requestId) : base(LeapEvent.EVENT_CONFIG_RESPONSE)
{
this.ConfigKey = config_key;
this.DataType = dataType;
this.Value = value;
this.RequestId = requestId;
}
public string ConfigKey { get; set; }
public Config.ValueType DataType { get; set; }
public object Value { get; set; }
public uint RequestId { get; set; }
}
/// <summary>
/// Dispatched when the connection is established.
/// @since 3.0
/// </summary>
public class ConnectionEventArgs : LeapEventArgs
{
public ConnectionEventArgs() : base(LeapEvent.EVENT_CONNECTION) { }
}
/// <summary>
/// Dispatched when the connection is lost.
/// @since 3.0
/// </summary>
public class ConnectionLostEventArgs : LeapEventArgs
{
public ConnectionLostEventArgs() : base(LeapEvent.EVENT_CONNECTION_LOST) { }
}
/// <summary>
/// Dispatched when a device is plugged in.
///
/// Provides the device as an argument.
/// @since 3.0
/// </summary>
public class DeviceEventArgs : LeapEventArgs
{
public DeviceEventArgs(Device device) : base(LeapEvent.EVENT_DEVICE)
{
this.Device = device;
}
public Device Device { get; set; }
}
/// <summary>
/// Dispatched when a device is plugged in, but fails to initialize or when
/// a working device fails in use.
///
/// Provides the failure reason and, if available, the serial number.
/// @since 3.0
/// </summary>
public class DeviceFailureEventArgs : LeapEventArgs
{
public DeviceFailureEventArgs(uint code, string message, string serial) : base(LeapEvent.EVENT_DEVICE_FAILURE)
{
ErrorCode = code;
ErrorMessage = message;
DeviceSerialNumber = serial;
}
public uint ErrorCode { get; set; }
public string ErrorMessage { get; set; }
public string DeviceSerialNumber { get; set; }
}
public class DroppedFrameEventArgs : LeapEventArgs
{
public DroppedFrameEventArgs(Int64 frame_id, eLeapDroppedFrameType type) : base(LeapEvent.EVENT_DROPPED_FRAME)
{
frameID = frame_id;
reason = type;
}
public Int64 frameID { get; set; }
public eLeapDroppedFrameType reason { get; set; }
}
/// <summary>
/// Dispatched when an unrequested Image is ready.
///
/// Provides the Image object as an argument.
/// @since 4.0
/// </summary>
public class ImageEventArgs : LeapEventArgs
{
public ImageEventArgs(Image image) : base(LeapEvent.EVENT_IMAGE)
{
this.image = image;
}
public Image image { get; set; }
}
/// <summary>
/// Dispatched when point mapping change events are generated by the service.
///
/// @since 4.0
/// </summary>
public class PointMappingChangeEventArgs : LeapEventArgs
{
public PointMappingChangeEventArgs(Int64 frame_id, Int64 timestamp, UInt32 nPoints) : base(LeapEvent.EVENT_POINT_MAPPING_CHANGE)
{
this.frameID = frame_id;
this.timestamp = timestamp;
this.nPoints = nPoints;
}
public Int64 frameID { get; set; }
public Int64 timestamp { get; set; }
public UInt32 nPoints { get; set; }
}
public class HeadPoseEventArgs : LeapEventArgs
{
public HeadPoseEventArgs(LEAP_VECTOR head_position, LEAP_QUATERNION head_orientation) : base(LeapEvent.EVENT_POINT_MAPPING_CHANGE)
{
this.headPosition = head_position;
this.headOrientation = head_orientation;
}
public LEAP_VECTOR headPosition { get; set; }
public LEAP_QUATERNION headOrientation { get; set; }
}
public struct BeginProfilingForThreadArgs
{
public string threadName;
public string[] blockNames;
public BeginProfilingForThreadArgs(string threadName, params string[] blockNames)
{
this.threadName = threadName;
this.blockNames = blockNames;
}
}
public struct EndProfilingForThreadArgs { }
public struct BeginProfilingBlockArgs
{
public string blockName;
public BeginProfilingBlockArgs(string blockName)
{
this.blockName = blockName;
}
}
public struct EndProfilingBlockArgs
{
public string blockName;
public EndProfilingBlockArgs(string blockName)
{
this.blockName = blockName;
}
}
}

View file

@ -0,0 +1,88 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The FailedDevice class provides information about Leap Motion hardware that
/// has been physically connected to the client computer, but is not operating
/// correctly.
///
/// Failed devices do not provide any tracking data and do not show up in the
/// Controller.Devices() list.
///
/// Get the list of failed devices using Controller.FailedDevices().
///
/// @since 3.0
/// </summary>
public class FailedDevice :
IEquatable<FailedDevice>
{
public FailedDevice()
{
Failure = FailureType.FAIL_UNKNOWN;
PnpId = "0";
}
/// <summary>
/// Test FailedDevice equality.
/// True if the devices are the same.
/// @since 3.0
/// </summary>
public bool Equals(FailedDevice other)
{
return PnpId == other.PnpId;
}
/// <summary>
/// The device plug-and-play id string.
/// @since 3.0
/// </summary>
public string PnpId { get; private set; }
/// <summary>
/// The reason for device failure.
/// The failure reasons are defined as members of the FailureType enumeration.
///
/// @since 3.0
/// </summary>
public FailureType Failure { get; private set; }
/// <summary>
/// The errors that can cause a device to fail to properly connect to the service.
///
/// @since 3.0
/// </summary>
public enum FailureType
{
/// <summary>
/// The cause of the error is unknown.
/// </summary>
FAIL_UNKNOWN,
/// <summary>
/// The device has a bad calibration record.
/// </summary>
FAIL_CALIBRATION,
/// <summary>
/// The device firmware is corrupt or failed to update.
/// </summary>
FAIL_FIRMWARE,
/// <summary>
/// The device is unresponsive.
/// </summary>
FAIL_TRANSPORT,
/// <summary>
/// The service cannot establish the required USB control interfaces.
/// </summary>
FAIL_CONTROl
}
}
}

View file

@ -0,0 +1,47 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System.Collections.Generic;
/// <summary>
/// The list of FailedDevice objects contains an entry for every failed Leap Motion
/// hardware device connected to the client computer. FailedDevice objects report
/// the device pnpID string and reason for failure.
///
/// Get the list of FailedDevice objects from Controller.FailedDevices().
///
/// @since 3.0
/// </summary>
public class FailedDeviceList : List<FailedDevice>
{
/// <summary>
/// Constructs an empty list.
/// </summary>
public FailedDeviceList() { }
/// <summary>
/// Appends the contents of another FailedDeviceList to this one.
/// </summary>
public FailedDeviceList Append(FailedDeviceList other)
{
AddRange(other);
return this;
}
/// <summary>
/// Reports whether the list is empty.
/// </summary>
public bool IsEmpty
{
get { return Count == 0; }
}
}
}

183
ml_lme/vendor/LeapCSharp/Finger.cs vendored Normal file
View file

@ -0,0 +1,183 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The Finger class represents a tracked finger.
///
/// Fingers are objects that the Leap Motion software has classified as a finger.
/// Get valid Finger objects from a Frame or a Hand object.
/// @since 1.0
/// </summary>
[Serializable]
public class Finger
{
public Bone[] bones = new Bone[4];
/// <summary>
/// Constructs a finger.
///
/// An uninitialized finger is considered invalid.
/// Get valid Finger objects from a Hand object.
///
/// @since 3.0
/// </summary>
public Finger()
{
bones[0] = new Bone();
bones[1] = new Bone();
bones[2] = new Bone();
bones[3] = new Bone();
}
/// <summary>
/// Constructs a finger.
///
/// Generally, you should not create your own finger objects. Such objects will not
/// have valid tracking data. Get valid finger objects from a hand in a frame
/// received from the service.
/// @since 3.0
/// </summary>
public Finger(long frameId,
int handId,
int fingerId,
float timeVisible,
Vector tipPosition,
Vector direction,
float width,
float length,
bool isExtended,
FingerType type,
Bone metacarpal,
Bone proximal,
Bone intermediate,
Bone distal)
{
Type = type;
bones[0] = metacarpal;
bones[1] = proximal;
bones[2] = intermediate;
bones[3] = distal;
Id = (handId * 10) + fingerId;
HandId = handId;
TipPosition = tipPosition;
Direction = direction;
Width = width;
Length = length;
IsExtended = isExtended;
TimeVisible = timeVisible;
}
/// <summary>
/// The bone at a given bone index on this finger.
/// @since 2.0
/// </summary>
public Bone Bone(Bone.BoneType boneIx)
{
return bones[(int)boneIx];
}
/// <summary>
/// A string containing a brief, human readable description of the Finger object.
/// @since 1.0
/// </summary>
public override string ToString()
{
return Enum.GetName(typeof(FingerType), Type) + " id:" + Id;
}
/// <summary>
/// The type of this finger.
/// @since 2.0
/// </summary>
public Finger.FingerType Type;
/// <summary>
/// A unique ID assigned to this Finger object, whose value remains the
/// same across consecutive frames while the tracked hand remains visible.
/// If tracking of the hand is lost, the Leap Motion software may assign a
/// new ID when it detects the hand in a future frame.
///
/// Use the ID value to find this Finger object in future frames.
///
/// IDs should be from 1 to 100 (inclusive). If more than 100 objects are tracked
/// an IDs of -1 will be used until an ID in the defined range is available.
///
/// @since 1.0
/// </summary>
public int Id;
/// <summary>
/// The Hand associated with a finger.
/// @since 1.0
/// </summary>
public int HandId;
/// <summary>
/// The tip position of this Finger.
/// @since 1.0
/// </summary>
public Vector TipPosition;
/// <summary>
/// The direction in which this finger or tool is pointing. The direction is expressed
/// as a unit vector pointing in the same direction as the tip.
/// @since 1.0
/// </summary>
public Vector Direction;
/// <summary>
/// The estimated width of the finger.
/// @since 1.0
/// </summary>
public float Width;
/// <summary>
/// The estimated length of the finger.
/// @since 1.0
/// </summary>
public float Length;
/// <summary>
/// Whether or not this Finger is in an extended posture.
///
/// A finger is considered extended if it is extended straight from the hand as if
/// pointing. A finger is not extended when it is bent down and curled towards the
/// palm.
///
/// @since 2.0
/// </summary>
public bool IsExtended;
/// <summary>
/// The duration of time this Finger has been visible to the Leap Motion Controller.
/// @since 1.0
/// </summary>
public float TimeVisible;
/// <summary>
/// Enumerates the names of the fingers.
///
/// Members of this enumeration are returned by Finger.Type() to identify a
/// Finger object.
/// @since 2.0
/// </summary>
public enum FingerType
{
TYPE_THUMB = 0,
TYPE_INDEX = 1,
TYPE_MIDDLE = 2,
TYPE_RING = 3,
TYPE_PINKY = 4,
TYPE_UNKNOWN = -1
}
}
}

221
ml_lme/vendor/LeapCSharp/Frame.cs vendored Normal file
View file

@ -0,0 +1,221 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
using System.Collections.Generic;
/// <summary>
/// The Frame class represents a set of hand and finger tracking data detected
/// in a single frame.
///
/// The Leap Motion software detects hands, fingers and tools within the tracking area, reporting
/// their positions, orientations, gestures, and motions in frames at the Leap Motion frame rate.
///
/// Access Frame objects through an instance of the Controller class.
/// @since 1.0
/// </summary>
[Serializable]
public class Frame : IEquatable<Frame>
{
[ThreadStatic]
private static Queue<Hand> _handPool;
/// <summary>
/// Constructs a Frame object.
///
/// Frame instances created with this constructor are invalid.
/// Get valid Frame objects by calling the Controller.Frame() function.
///
/// The only time you should use this constructor is before deserializing
/// serialized frame data, or if you are going to be passing this Frame
/// to a method that fills it with valid data.
///
/// @since 1.0
/// </summary>
public Frame(UInt32 DeviceID = 1)
{
Hands = new List<Hand>();
this.DeviceID = DeviceID;
}
/// <summary>
/// Constructs a new Frame.
/// @since 3.0
/// </summary>
public Frame(long id, long timestamp, float fps, List<Hand> hands)
{
Id = id;
Timestamp = timestamp;
CurrentFramesPerSecond = fps;
Hands = hands;
DeviceID = 1;
}
/// <summary>
/// The Device ID that this frame was seen from.
///
/// 1-Indexed; Non-Deterministic order
///
/// Only valid when `supportsMultipleDevices` is true on the LeapProvider.
///
/// @since 4.1
/// </summary>
public UInt32 DeviceID;
[Obsolete]
public int SerializeLength
{
get
{
throw new NotImplementedException();
}
}
[Obsolete]
public byte[] Serialize
{
get
{
throw new NotImplementedException();
}
}
[Obsolete]
public void Deserialize(byte[] arg)
{
throw new NotImplementedException();
}
/// <summary>
/// The Hand object with the specified ID in this frame, or null if none
/// exists.
///
/// Use the Frame.Hand() function to retrieve the Hand object from
/// this frame using an ID value obtained from a previous frame.
/// This function always returns a Hand object, but if no hand
/// with the specified ID is present, an invalid Hand object is returned.
///
/// Note that ID values persist across frames, but only until tracking of a
/// particular object is lost. If tracking of a hand is lost and subsequently
/// regained, the new Hand object representing that physical hand may have
/// a different ID than that representing the physical hand in an earlier frame.
/// @since 1.0 </summary>
public Hand Hand(int id)
{
for (int i = Hands.Count; i-- != 0;)
{
if (Hands[i].Id == id)
{
return Hands[i];
}
}
return null;
}
/// <summary>
/// Compare Frame object equality.
///
/// Two Frame objects are equal if and only if both Frame objects represent
/// the exact same frame of tracking data and both Frame objects are valid.
/// @since 1.0
/// </summary>
public bool Equals(Frame other)
{
return Id == other.Id && Timestamp == other.Timestamp;
}
/// <summary>
/// A string containing a brief, human readable description of the Frame object.
/// @since 1.0
/// </summary>
public override string ToString()
{
return "Frame id: " + this.Id + " timestamp: " + this.Timestamp;
}
/// <summary>
/// A unique ID for this Frame.
///
/// Consecutive frames processed by the Leap Motion software have consecutive
/// increasing values. You can use the frame ID to avoid processing the same
/// Frame object twice, as well as to make sure that your application processes
/// every frame.
///
/// @since 1.0
/// </summary>
public long Id;
/// <summary>
/// The frame capture time in microseconds elapsed since an arbitrary point in
/// time in the past.
///
/// You can use Controller.Now() to calculate the age of the frame.
///
/// @since 1.0
/// </summary>
public long Timestamp;
/// <summary>
/// The instantaneous framerate.
///
/// The rate at which the Leap Motion software is providing frames of data
/// (in frames per second). The framerate can fluctuate depending on available computing
/// resources, activity within the device field of view, software tracking settings,
/// and other factors.
///
/// @since 1.0
/// </summary>
public float CurrentFramesPerSecond;
/// <summary>
/// The list of Hand objects detected in this frame, given in arbitrary order.
/// The list can be empty if no hands are detected.
///
/// @since 1.0
/// </summary>
public List<Hand> Hands;
/// <summary>
/// Resizes the Hand list to have a specific size. If the size is decreased,
/// the removed hands are placed into the hand pool. If the size is increased, the
/// new spaces are filled with hands taken from the hand pool. If the pool is
/// empty, new hands are constructed instead.
/// </summary>
public void ResizeHandList(int count)
{
if (_handPool == null)
{
_handPool = new Queue<Hand>();
}
while (Hands.Count < count)
{
Hand newHand;
if (_handPool.Count > 0)
{
newHand = _handPool.Dequeue();
}
else
{
newHand = new Hand();
}
Hands.Add(newHand);
}
while (Hands.Count > count)
{
Hand lastHand = Hands[Hands.Count - 1];
Hands.RemoveAt(Hands.Count - 1);
_handPool.Enqueue(lastHand);
}
}
}
}

322
ml_lme/vendor/LeapCSharp/Hand.cs vendored Normal file
View file

@ -0,0 +1,322 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
using System.Collections.Generic;
/// <summary>
/// The Hand class reports the physical characteristics of a detected hand.
///
/// Hand tracking data includes a palm position and velocity; vectors for
/// the palm normal and direction to the fingers; and lists of the attached fingers.
///
/// Note that Hand objects can be invalid, which means that they do not contain
/// valid tracking data and do not correspond to a physical entity. Invalid Hand
/// objects can be the result of using the default constructor, or modifying the
/// hand data in an incorrect way.
/// @since 1.0
/// </summary>
[Serializable]
public class Hand : IEquatable<Hand>
{
/// <summary>
/// Constructs a Hand object.
///
/// An uninitialized hand is considered invalid.
/// Get valid Hand objects from a Frame object.
///
/// @since 1.0
/// </summary>
public Hand()
{
Arm = new Arm();
Fingers = new List<Finger>(5);
Fingers.Add(new Finger());
Fingers.Add(new Finger());
Fingers.Add(new Finger());
Fingers.Add(new Finger());
Fingers.Add(new Finger());
}
/// <summary>
/// Constructs a hand.
///
/// Generally, you should not create your own Hand objects. Such objects will not
/// have valid tracking data. Get valid Hand objects from a frame
/// received from the service.
/// @since 3.0
/// </summary>
public Hand(long frameID,
int id,
float confidence,
float grabStrength,
float grabAngle,
float pinchStrength,
float pinchDistance,
float palmWidth,
bool isLeft,
float timeVisible,
Arm arm,
List<Finger> fingers,
Vector palmPosition,
Vector stabilizedPalmPosition,
Vector palmVelocity,
Vector palmNormal,
LeapQuaternion palmOrientation,
Vector direction,
Vector wristPosition)
{
FrameId = frameID;
Id = id;
Confidence = confidence;
GrabStrength = grabStrength;
GrabAngle = grabAngle;
PinchStrength = pinchStrength;
PinchDistance = pinchDistance;
PalmWidth = palmWidth;
IsLeft = isLeft;
TimeVisible = timeVisible;
Arm = arm;
Fingers = fingers;
PalmPosition = palmPosition;
StabilizedPalmPosition = stabilizedPalmPosition;
PalmVelocity = palmVelocity;
PalmNormal = palmNormal;
Rotation = palmOrientation;
Direction = direction;
WristPosition = wristPosition;
}
/// <summary>
/// The Finger object with the specified ID attached to this hand.
///
/// Use the Hand.Finger() function to retrieve a Finger object attached to
/// this hand using an ID value obtained from a previous frame.
///
/// Note that ID values persist across frames, but only until tracking of a
/// particular object is lost. If tracking of a hand is lost and subsequently
/// regained, the new Finger object representing that finger may have a
/// different ID than that representing the finger in an earlier frame.
///
/// @since 1.0
/// </summary>
public Finger Finger(int id)
{
for (int i = Fingers.Count; i-- != 0;)
{
if (Fingers[i].Id == id)
{
return Fingers[i];
}
}
return null;
}
/// <summary>
/// Compare Hand object equality.
///
/// Two Hand objects are equal if and only if both Hand objects represent the
/// exact same physical hand in the same frame and both Hand objects are valid.
/// </summary>
public bool Equals(Hand other)
{
return Id == other.Id && FrameId == other.FrameId;
}
/// <summary>
/// A string containing a brief, human readable description of the Hand object.
/// @since 1.0
/// </summary>
public override string ToString()
{
return string.Format(
"Hand {0} {1}.",
this.Id,
this.IsLeft ? "left" : "right"
);
}
public long FrameId;
/// <summary>
/// A unique ID assigned to this Hand object, whose value remains the same
/// across consecutive frames while the tracked hand remains visible. If
/// tracking is lost (for example, when a hand is occluded by another hand
/// or when it is withdrawn from or reaches the edge of the Leap Motion Controller field of view),
/// the Leap Motion software may assign a new ID when it detects the hand in a future frame.
///
/// Use the ID value with the Frame.Hand() function to find this Hand object
/// in future frames.
///
/// @since 1.0
/// </summary>
public int Id;
/// <summary>
/// The list of Finger objects detected in this frame that are attached to
/// this hand, given in order from thumb to pinky. The list cannot be empty.
/// @since 1.0
/// </summary>
public List<Finger> Fingers;
/// <summary>
/// The center position of the palm.
/// @since 1.0
/// </summary>
public Vector PalmPosition;
/// <summary>
/// The rate of change of the palm position.
/// @since 1.0
/// </summary>
public Vector PalmVelocity;
/// <summary>
/// The normal vector to the palm. If your hand is flat, this vector will
/// point downward, or "out" of the front surface of your palm.
///
/// The direction is expressed as a unit vector pointing in the same
/// direction as the palm normal (that is, a vector orthogonal to the palm).
///
/// You can use the palm normal vector to compute the roll angle of the palm with
/// respect to the horizontal plane.
/// @since 1.0
/// </summary>
public Vector PalmNormal;
/// <summary>
/// The direction from the palm position toward the fingers.
///
/// The direction is expressed as a unit vector pointing in the same
/// direction as the directed line from the palm position to the fingers.
///
/// You can use the palm direction vector to compute the pitch and yaw angles of the palm with
/// respect to the horizontal plane.
/// @since 1.0
/// </summary>
public Vector Direction;
/// <summary>
/// The transform of the hand.
///
/// Note, in version prior to 3.1, the Basis was a Matrix object.
/// @since 3.1
/// </summary>
public LeapTransform Basis { get { return new LeapTransform(PalmPosition, Rotation); } }
/// <summary>
/// The rotation of the hand as a quaternion.
///
/// @since 3.1
/// </summary>
public LeapQuaternion Rotation;
/// <summary>
/// The strength of a grab hand pose.
///
/// The strength is zero for an open hand, and blends to one when a grabbing hand
/// pose is recognized.
/// @since 2.0
/// </summary>
public float GrabStrength;
/// <summary>
/// The angle between the fingers and the hand of a grab hand pose.
///
/// The angle is computed by looking at the angle between the direction of the
/// 4 fingers and the direction of the hand. Thumb is not considered when
/// computing the angle.
/// The angle is 0 radian for an open hand, and reaches pi radians when the pose
/// is a tight fist.
///
/// @since 3.0
/// </summary>
public float GrabAngle;
/// <summary>
/// The holding strength of a pinch hand pose.
///
/// The strength is zero for an open hand, and blends to one when a pinching
/// hand pose is recognized. Pinching can be done between the thumb
/// and any other finger of the same hand.
/// @since 2.0
/// </summary>
public float PinchStrength;
/// <summary>
/// The distance between the thumb and index finger of a pinch hand pose.
///
/// The distance is computed by looking at the shortest distance between
/// the last 2 phalanges of the thumb and those of the index finger.
/// This pinch measurement only takes thumb and index finger into account.
/// @since 3.0
/// </summary>
public float PinchDistance;
/// <summary>
/// The estimated width of the palm when the hand is in a flat position.
/// @since 2.0
/// </summary>
public float PalmWidth;
/// <summary>
/// The stabilized palm position of this Hand.
///
/// Smoothing and stabilization is performed in order to make
/// this value more suitable for interaction with 2D content. The stabilized
/// position lags behind the palm position by a variable amount, depending
/// primarily on the speed of movement.
/// @since 1.0
/// </summary>
public Vector StabilizedPalmPosition;
/// <summary>
/// The position of the wrist of this hand.
/// @since 2.0.3
/// </summary>
public Vector WristPosition;
/// <summary>
/// The duration of time this Hand has been visible to the Leap Motion Controller.
/// @since 1.0
/// </summary>
public float TimeVisible;
/// <summary>
/// How confident we are with a given hand pose.
/// The confidence level ranges between 0.0 and 1.0 inclusive.
///
/// @since 2.0
/// </summary>
public float Confidence;
/// <summary>
/// Identifies whether this Hand is a left hand.
/// @since 2.0
/// </summary>
public bool IsLeft;
/// <summary>
/// Identifies whether this Hand is a right hand.
/// @since 2.0
/// </summary>
public bool IsRight { get { return !IsLeft; } }
/// <summary>
/// The arm to which this hand is attached.
///
/// If the arm is not completely in view, Arm attributes are estimated based on
/// the attributes of entities that are in view combined with typical human anatomy.
/// @since 2.0.3
/// </summary>
public Arm Arm;
}
}

53
ml_lme/vendor/LeapCSharp/IController.cs vendored Normal file
View file

@ -0,0 +1,53 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
using System;
namespace Leap
{
public interface IController :
IDisposable
{
Frame Frame(int history = 0);
Frame GetTransformedFrame(LeapTransform trs, int history = 0);
Frame GetInterpolatedFrame(Int64 time);
[Obsolete]
void SetPolicy(Controller.PolicyFlag policy);
[Obsolete]
void ClearPolicy(Controller.PolicyFlag policy);
[Obsolete]
bool IsPolicySet(Controller.PolicyFlag policy);
void SetPolicy(Controller.PolicyFlag policy, Device device = null);
void ClearPolicy(Controller.PolicyFlag policy, Device device = null);
bool IsPolicySet(Controller.PolicyFlag policy, Device device = null);
long Now();
bool IsConnected { get; }
Config Config { get; }
DeviceList Devices { get; }
event EventHandler<ConnectionEventArgs> Connect;
event EventHandler<ConnectionLostEventArgs> Disconnect;
event EventHandler<FrameEventArgs> FrameReady;
event EventHandler<DeviceEventArgs> Device;
event EventHandler<DeviceEventArgs> DeviceLost;
event EventHandler<DeviceFailureEventArgs> DeviceFailure;
event EventHandler<LogEventArgs> LogMessage;
//new
event EventHandler<PolicyEventArgs> PolicyChange;
event EventHandler<ConfigChangeEventArgs> ConfigChange;
event EventHandler<DistortionEventArgs> DistortionChange;
event EventHandler<ImageEventArgs> ImageReady;
event EventHandler<PointMappingChangeEventArgs> PointMappingChange;
event EventHandler<HeadPoseEventArgs> HeadPoseChange;
}
}

456
ml_lme/vendor/LeapCSharp/Image.cs vendored Normal file
View file

@ -0,0 +1,456 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using LeapInternal;
using System;
/// <summary>
/// The Image class represents a stereo image pair from the Leap Motion device.
///
/// In addition to image data, the Image object provides a distortion map for correcting
/// lens distortion.
/// @since 2.1.0
/// </summary>
public class Image
{
private ImageData leftImage;
private ImageData rightImage;
private Int64 frameId = 0;
private Int64 timestamp = 0;
private UInt32 deviceId = 0;
public Image(Int64 frameId, Int64 timestamp, ImageData leftImage, ImageData rightImage, UInt32 deviceId = 1)
{
if (leftImage == null || rightImage == null)
{
throw new ArgumentNullException("images");
}
if (leftImage.type != rightImage.type ||
leftImage.format != rightImage.format ||
leftImage.width != rightImage.width ||
leftImage.height != rightImage.height ||
leftImage.bpp != rightImage.bpp ||
leftImage.DistortionSize != rightImage.DistortionSize)
{
throw new ArgumentException("image mismatch");
}
this.frameId = frameId;
this.timestamp = timestamp;
this.leftImage = leftImage;
this.rightImage = rightImage;
this.deviceId = deviceId;
}
private ImageData imageData(CameraType camera)
{
return camera == CameraType.LEFT ? leftImage : rightImage;
}
/// <summary>
/// The buffer containing the image data.
///
/// The image data is a set of 8-bit intensity values. The buffer is
/// image.Width * image.Height * image.BytesPerPixel bytes long.
///
/// Use the ByteOffset method to find the beginning offset
/// of the data for the specified camera.
///
/// @since 4.0
/// </summary>
public byte[] Data(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return null;
return imageData(camera).AsByteArray;
}
/// <summary>
/// Returns a convenience device ID based on which attached device sent this
/// image.
/// @since 4.5.0
/// </summary>
public UInt32 DeviceID
{
get
{
return deviceId;
}
}
public enum CalibrationType
{
INFRARED = 0,
VISIBLE = 1
};
/// <summary>
/// The offset, in number of bytes, from the beginning of the Data()
/// buffer to the first byte of the image data for the specified camera.
///
/// @since 4.0
/// </summary>
public UInt32 ByteOffset(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return 0;
return imageData(camera).byteOffset;
}
/// <summary>
/// The number of bytes in the Data() buffer corresponding to each
/// image. Use the ByteOffset() function to find the starting byte
/// offset for each image.
///
/// @since 4.0
/// </summary>
public UInt32 NumBytes
{
get
{
return leftImage.width * leftImage.height * leftImage.bpp;
}
}
/// <summary>
/// The distortion calibration map for this image.
///
/// The calibration map is a 64x64 grid of points. Each point is defined by
/// a pair of 32-bit floating point values. Each point in the map
/// represents a ray projected into the camera. The value of
/// a grid point defines the pixel in the image data containing the brightness
/// value produced by the light entering along the corresponding ray. By
/// interpolating between grid data points, you can find the brightness value
/// for any projected ray. Grid values that fall outside the range [0..1] do
/// not correspond to a value in the image data and those points should be ignored.
///
/// The calibration map can be used to render an undistorted image as well as to
/// find the true angle from the camera to a feature in the raw image. The
/// distortion map itself is designed to be used with GLSL shader programs.
/// In other contexts, it may be more convenient to use the Image Rectify()
/// and Warp() functions.
///
/// Distortion is caused by the lens geometry as well as imperfections in the
/// lens and sensor window. The calibration map is created by the calibration
/// process run for each device at the factory (and which can be rerun by the
/// user).
///
/// @since 2.1.0
/// </summary>
public float[] Distortion(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return null;
return imageData(camera).DistortionData.Data;
}
/// <summary>
/// Provides the corrected camera ray intercepting the specified point on the image.
///
/// Given a point on the image, PixelToRectilinear() corrects for camera distortion
/// and returns the true direction from the camera to the source of that image point
/// within the Leap Motion field of view.
///
/// This direction vector has an x and y component [x, y, 1], with the third element
/// always one. Note that this vector uses the 2D camera coordinate system
/// where the x-axis parallels the longer (typically horizontal) dimension and
/// the y-axis parallels the shorter (vertical) dimension. The camera coordinate
/// system does not correlate to the 3D Leap Motion coordinate system.
///
/// **Note:** This function should be called immediately after an image is obtained. Incorrect
/// results will be returned if the image orientation has changed or a different device is plugged
/// in between the time the image was received and the time this function is called.
///
/// Note, this function was formerly named Rectify().
/// @since 2.1.0
/// </summary>
public Vector PixelToRectilinear(CameraType camera, Vector pixel)
{
return Connection.GetConnection().PixelToRectilinear(camera, pixel);
}
/// <summary>
/// Provides the point in the image corresponding to a ray projecting
/// from the camera.
///
/// Given a ray projected from the camera in the specified direction, RectilinearToPixel()
/// corrects for camera distortion and returns the corresponding pixel
/// coordinates in the image.
///
/// The ray direction is specified in relationship to the camera. The first
/// vector element corresponds to the "horizontal" view angle; the second
/// corresponds to the "vertical" view angle.
///
/// The RectilinearToPixel() function returns pixel coordinates outside of the image bounds
/// if you project a ray toward a point for which there is no recorded data.
///
/// RectilinearToPixel() is typically not fast enough for realtime distortion correction.
/// For better performance, use a shader program executed on a GPU.
///
/// **Note:** This function should be called immediately after an image is obtained. Incorrect
/// results will be returned if the image orientation has changed or a different device is plugged
/// in between the time the image was received and the time this function is called.
///
/// Note, this function was formerly named Warp().
/// @since 2.1.0
/// </summary>
public Vector RectilinearToPixel(CameraType camera, Vector ray)
{
return Connection.GetConnection().RectilinearToPixel(camera, ray);
}
/// <summary>
/// Compare Image object equality.
///
/// Two Image objects are equal if and only if both Image objects represent the
/// exact same Image and both Images are valid.
/// @since 2.1.0
/// </summary>
public bool Equals(Image other)
{
return
this.frameId == other.frameId &&
this.Type == other.Type &&
this.Timestamp == other.Timestamp;
}
/// <summary>
/// A string containing a brief, human readable description of the Image object.
/// @since 2.1.0
/// </summary>
public override string ToString()
{
return "Image sequence" + this.frameId + ", format: " + this.Format + ", type: " + this.Type;
}
/// <summary>
/// The image sequence ID.
/// @since 2.2.1
/// </summary>
public Int64 SequenceId
{
get
{
return frameId;
}
}
/// <summary>
/// The image width.
/// @since 2.1.0
/// </summary>
public int Width
{
get
{
return (int)leftImage.width;
}
}
/// <summary>
/// The image height.
/// @since 2.1.0
/// </summary>
public int Height
{
get
{
return (int)leftImage.height;
}
}
/// <summary>
/// The number of bytes per pixel.
///
/// Use this value along with Image.Width() and Image.Height()
/// to calculate the size of the data buffer.
///
/// @since 2.2.0
/// </summary>
public int BytesPerPixel
{
get
{
return (int)leftImage.bpp;
}
}
/// <summary>
/// The image format.
/// @since 2.2.0
/// </summary>
public FormatType Format
{
get
{
switch (leftImage.format)
{
case eLeapImageFormat.eLeapImageType_IR:
return FormatType.INFRARED;
case eLeapImageFormat.eLeapImageType_RGBIr_Bayer:
return FormatType.IBRG;
default:
return FormatType.INFRARED;
}
}
}
public ImageType Type
{
get
{
switch (leftImage.type)
{
case eLeapImageType.eLeapImageType_Default:
return ImageType.DEFAULT;
case eLeapImageType.eLeapImageType_Raw:
return ImageType.RAW;
default:
return ImageType.DEFAULT;
}
}
}
/// <summary>
/// The stride of the distortion map.
///
/// Since each point on the 64x64 element distortion map has two values in the
/// buffer, the stride is 2 times the size of the grid. (Stride is currently fixed
/// at 2 * 64 = 128).
///
/// @since 2.1.0
/// </summary>
public int DistortionWidth
{
get
{
return leftImage.DistortionSize * 2;
}
}
/// <summary>
/// The distortion map height.
/// Currently fixed at 64.
///
/// @since 2.1.0
/// </summary>
public int DistortionHeight
{
get
{
return leftImage.DistortionSize;
}
}
/// <summary>
/// The horizontal ray offset for a particular camera.
///
/// Used to convert between normalized coordinates in the range [0..1] and the
/// ray slope range [-4..4].
///
/// @since 4.0
/// </summary>
public float RayOffsetX(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return 0;
return imageData(camera).RayOffsetX;
}
/// <summary>
/// The vertical ray offset for a particular camera.
///
/// Used to convert between normalized coordinates in the range [0..1] and the
/// ray slope range [-4..4].
///
/// @since 2.1.0
/// </summary>
public float RayOffsetY(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return 0;
return imageData(camera).RayOffsetY;
}
/// <summary>
/// The horizontal ray scale factor for a particular camera.
///
/// Used to convert between normalized coordinates in the range [0..1] and the
/// ray slope range [-4..4].
///
/// @since 2.1.0
/// </summary>
public float RayScaleX(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return 0;
return imageData(camera).RayScaleX;
}
/// <summary>
/// The vertical ray scale factor for a particular camera.
///
/// Used to convert between normalized coordinates in the range [0..1] and the
/// ray slope range [-4..4].
///
/// @since 2.1.0
/// </summary>
public float RayScaleY(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return 0;
return imageData(camera).RayScaleY;
}
/// <summary>
/// Returns a timestamp indicating when this frame began being captured on the device.
/// @since 2.2.7
/// </summary>
public Int64 Timestamp
{
get
{
return timestamp;
}
}
/// <summary>
/// Enumerates the possible image formats.
///
/// The Image.Format() function returns an item from the FormatType enumeration.
/// @since 2.2.0
/// </summary>
public enum FormatType
{
INFRARED = 0,
IBRG = 1
}
public enum ImageType
{
DEFAULT,
RAW
}
public enum CameraType
{
LEFT = 0,
RIGHT = 1
};
}
}

47
ml_lme/vendor/LeapCSharp/ImageData.cs vendored Normal file
View file

@ -0,0 +1,47 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace LeapInternal
{
using Leap;
using System;
public class ImageData
{
private LEAP_IMAGE_PROPERTIES _properties;
private object _object;
public Image.CameraType camera { get; protected set; }
public eLeapImageType type { get { return _properties.type; } }
public eLeapImageFormat format { get { return _properties.format; } }
public UInt32 bpp { get { return _properties.bpp; } }
public UInt32 width { get { return _properties.width; } }
public UInt32 height { get { return _properties.height; } }
public float RayScaleX { get { return _properties.x_scale; } }
public float RayScaleY { get { return _properties.y_scale; } }
public float RayOffsetX { get { return _properties.x_offset; } }
public float RayOffsetY { get { return _properties.y_offset; } }
public byte[] AsByteArray { get { return _object as byte[]; } }
public float[] AsFloatArray { get { return _object as float[]; } }
public UInt32 byteOffset { get; protected set; }
public int DistortionSize { get { return LeapC.DistortionSize; } }
public UInt64 DistortionMatrixKey { get; protected set; }
public DistortionData DistortionData { get; protected set; }
public ImageData(Image.CameraType camera, LEAP_IMAGE image, DistortionData distortionData)
{
this.camera = camera;
this._properties = image.properties;
this.DistortionMatrixKey = image.matrix_version;
this.DistortionData = distortionData;
this._object = MemoryManager.GetPinnedObject(image.data);
this.byteOffset = image.offset;
}
}
}

1228
ml_lme/vendor/LeapCSharp/LeapC.cs vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,171 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The LeapQuaternion struct represents a rotation in three-dimensional space.
/// @since 3.1.2
/// </summary>
[Serializable]
public struct LeapQuaternion :
IEquatable<LeapQuaternion>
{
/// <summary>
/// Creates a new LeapQuaternion with the specified component values.
/// @since 3.1.2
/// </summary>
public LeapQuaternion(float x, float y, float z, float w) :
this()
{
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
/// <summary>
/// Copies the specified LeapQuaternion.
/// @since 3.1.2
/// </summary>
public LeapQuaternion(LeapQuaternion quaternion) :
this()
{
x = quaternion.x;
y = quaternion.y;
z = quaternion.z;
w = quaternion.w;
}
/// <summary>
/// Copies the specified LEAP_QUATERNION.
/// @since 3.1.2
/// </summary>
public LeapQuaternion(LeapInternal.LEAP_QUATERNION quaternion) :
this()
{
x = quaternion.x;
y = quaternion.y;
z = quaternion.z;
w = quaternion.w;
}
/// <summary>
/// Returns a string containing this quaternion in a human readable format: (x, y, z).
/// @since 3.1.2
/// </summary>
public override string ToString()
{
return "(" + x + ", " + y + ", " + z + ", " + w + ")";
}
/// <summary>
/// Compare LeapQuaternion equality component-wise.
/// @since 3.1.2
/// </summary>
public bool Equals(LeapQuaternion v)
{
return x.NearlyEquals(v.x) && y.NearlyEquals(v.y) && z.NearlyEquals(v.z) && w.NearlyEquals(v.w);
}
public override bool Equals(Object obj)
{
return obj is LeapQuaternion && Equals((LeapQuaternion)obj);
}
/// <summary>
/// Returns true if all of the quaternion's components are finite. If any
/// component is NaN or infinite, then this returns false.
/// @since 3.1.2
/// </summary>
public bool IsValid()
{
return !(float.IsNaN(x) || float.IsInfinity(x) ||
float.IsNaN(y) || float.IsInfinity(y) ||
float.IsNaN(z) || float.IsInfinity(z) ||
float.IsNaN(w) || float.IsInfinity(w));
}
public float x;
public float y;
public float z;
public float w;
/// <summary>
/// The magnitude, or length, of this quaternion.
/// @since 3.1.2
/// </summary>
public float Magnitude
{
get { return (float)Math.Sqrt(x * x + y * y + z * z + w * w); }
}
/// <summary>
/// The square of the magnitude, or length, of this quaternion.
/// @since 3.1.2
/// </summary>
public float MagnitudeSquared
{
get { return x * x + y * y + z * z + w * w; }
}
/// <summary>
/// A normalized copy of this quaternion.
/// @since 3.1.2
/// </summary>
public LeapQuaternion Normalized
{
get
{
float denom = MagnitudeSquared;
if (denom <= Constants.EPSILON)
{
return Identity;
}
denom = 1.0f / (float)Math.Sqrt(denom);
return new LeapQuaternion(x * denom, y * denom, z * denom, w * denom);
}
}
/// <summary>
/// Concatenates the rotation described by this quaternion with the one provided
/// and returns the result.
/// @since 3.1.2
/// </summary>
public LeapQuaternion Multiply(LeapQuaternion rhs)
{
return new LeapQuaternion(
w * rhs.x + x * rhs.w + y * rhs.z - z * rhs.y,
w * rhs.y + y * rhs.w + z * rhs.x - x * rhs.z,
w * rhs.z + z * rhs.w + x * rhs.y - y * rhs.x,
w * rhs.w - x * rhs.x - y * rhs.y - z * rhs.z);
}
/// <summary>
/// The identity quaternion.
/// @since 3.1.2
/// </summary>
public static readonly LeapQuaternion Identity = new LeapQuaternion(0, 0, 0, 1);
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 23 + x.GetHashCode();
hash = hash * 23 + y.GetHashCode();
hash = hash * 23 + z.GetHashCode();
hash = hash * 23 + w.GetHashCode();
return hash;
}
}
}
}

View file

@ -0,0 +1,277 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The LeapTransform class represents a transform in three dimensional space.
///
/// Note that the LeapTransform class replaces the Leap.Matrix class.
/// @since 3.1.2
/// </summary>
public struct LeapTransform
{
/// <summary>
/// Constructs a new transform from the specified translation and rotation.
/// @since 3.1.2
/// </summary>
public LeapTransform(Vector translation, LeapQuaternion rotation) :
this(translation, rotation, Vector.Ones)
{
}
/// <summary>
/// Constructs a new transform from the specified translation, rotation and scale.
/// @since 3.1.2
/// </summary>
public LeapTransform(Vector translation, LeapQuaternion rotation, Vector scale) :
this()
{
_scale = scale;
// these are non-trival setters.
this.translation = translation;
this.rotation = rotation; // Calls validateBasis
}
/// <summary>
/// Transforms the specified position vector, applying translation, rotation and scale.
/// @since 3.1.2
/// </summary>
public Vector TransformPoint(Vector point)
{
return _xBasisScaled * point.x + _yBasisScaled * point.y + _zBasisScaled * point.z + translation;
}
/// <summary>
/// Transforms the specified direction vector, applying rotation only.
/// @since 3.1.2
/// </summary>
public Vector TransformDirection(Vector direction)
{
return _xBasis * direction.x + _yBasis * direction.y + _zBasis * direction.z;
}
/// <summary>
/// Transforms the specified velocity vector, applying rotation and scale.
/// @since 3.1.2
/// </summary>
public Vector TransformVelocity(Vector velocity)
{
return _xBasisScaled * velocity.x + _yBasisScaled * velocity.y + _zBasisScaled * velocity.z;
}
/// <summary>
/// Transforms the specified quaternion.
/// Multiplies the quaternion representing the rotational part of this transform by the specified
/// quaternion.
///
/// **Important:** Modifying the basis vectors of this transform directly leaves the underlying quaternion in
/// an indeterminate state. Neither this function nor the LeapTransform.rotation quaternion can be used after
/// the basis vectors are set.
///
/// @since 3.1.2
/// </summary>
public LeapQuaternion TransformQuaternion(LeapQuaternion rhs)
{
if (_quaternionDirty)
throw new InvalidOperationException("Calling TransformQuaternion after Basis vectors have been modified.");
if (_flip)
{
// Mirror the axis of rotation across the flip axis.
rhs.x *= _flipAxes.x;
rhs.y *= _flipAxes.y;
rhs.z *= _flipAxes.z;
}
LeapQuaternion t = _quaternion.Multiply(rhs);
return t;
}
/// <summary>
/// Mirrors this transform's rotation and scale across the x-axis. Translation is not affected.
/// @since 3.1.2
/// </summary>
public void MirrorX()
{
_xBasis = -_xBasis;
_xBasisScaled = -_xBasisScaled;
_flip = true;
_flipAxes.y = -_flipAxes.y;
_flipAxes.z = -_flipAxes.z;
}
/// <summary>
/// Mirrors this transform's rotation and scale across the z-axis. Translation is not affected.
/// @since 3.1.2
/// </summary>
public void MirrorZ()
{
_zBasis = -_zBasis;
_zBasisScaled = -_zBasisScaled;
_flip = true;
_flipAxes.x = -_flipAxes.x;
_flipAxes.y = -_flipAxes.y;
}
/// <summary>
/// The x-basis of the transform.
///
/// **Important:** Modifying the basis vectors of this transform directly leaves the underlying quaternion in
/// an indeterminate state. Neither the TransformQuaternion() function nor the LeapTransform.rotation quaternion
/// can be used after the basis vectors are set.
///
/// @since 3.1.2
/// </summary>
public Vector xBasis
{
get { return _xBasis; }
set
{
_xBasis = value;
_xBasisScaled = value * scale.x;
_quaternionDirty = true;
}
}
/// <summary>
/// The y-basis of the transform.
///
/// **Important:** Modifying the basis vectors of this transform directly leaves the underlying quaternion in
/// an indeterminate state. Neither the TransformQuaternion() function nor the LeapTransform.rotation quaternion
/// can be used after the basis vectors are set.
///
/// @since 3.1.2
/// </summary>
public Vector yBasis
{
get { return _yBasis; }
set
{
_yBasis = value;
_yBasisScaled = value * scale.y;
_quaternionDirty = true;
}
}
/// <summary>
/// The z-basis of the transform.
///
/// **Important:** Modifying the basis vectors of this transform directly leaves the underlying quaternion in
/// an indeterminate state. Neither the TransformQuaternion() function nor the LeapTransform.rotation quaternion
/// can be used after the basis vectors are set.
///
/// @since 3.1.2
/// </summary>
public Vector zBasis
{
get { return _zBasis; }
set
{
_zBasis = value;
_zBasisScaled = value * scale.z;
_quaternionDirty = true;
}
}
/// <summary>
/// The translation component of the transform.
/// @since 3.1.2
/// </summary>
public Vector translation
{
get { return _translation; }
set
{
_translation = value;
}
}
/// <summary>
/// The scale factors of the transform.
/// Scale is kept separate from translation.
/// @since 3.1.2
/// </summary>
public Vector scale
{
get { return _scale; }
set
{
_scale = value;
_xBasisScaled = _xBasis * scale.x;
_yBasisScaled = _yBasis * scale.y;
_zBasisScaled = _zBasis * scale.z;
}
}
/// <summary>
/// The rotational component of the transform.
///
/// **Important:** Modifying the basis vectors of this transform directly leaves the underlying quaternion in
/// an indeterminate state. This rotation quaternion cannot be accessed after
/// the basis vectors are modified directly.
///
/// @since 3.1.2
/// </summary>
public LeapQuaternion rotation
{
get
{
if (_quaternionDirty)
throw new InvalidOperationException("Requesting rotation after Basis vectors have been modified.");
return _quaternion;
}
set
{
_quaternion = value;
float d = value.MagnitudeSquared;
float s = 2.0f / d;
float xs = value.x * s, ys = value.y * s, zs = value.z * s;
float wx = value.w * xs, wy = value.w * ys, wz = value.w * zs;
float xx = value.x * xs, xy = value.x * ys, xz = value.x * zs;
float yy = value.y * ys, yz = value.y * zs, zz = value.z * zs;
_xBasis = new Vector(1.0f - (yy + zz), xy + wz, xz - wy);
_yBasis = new Vector(xy - wz, 1.0f - (xx + zz), yz + wx);
_zBasis = new Vector(xz + wy, yz - wx, 1.0f - (xx + yy));
_xBasisScaled = _xBasis * scale.x;
_yBasisScaled = _yBasis * scale.y;
_zBasisScaled = _zBasis * scale.z;
_quaternionDirty = false;
_flip = false;
_flipAxes = new Vector(1.0f, 1.0f, 1.0f);
}
}
/// <summary>
/// The identity transform.
/// @since 3.1.2
/// </summary>
public static readonly LeapTransform Identity = new LeapTransform(Vector.Zero, LeapQuaternion.Identity, Vector.Ones);
private Vector _translation;
private Vector _scale;
private LeapQuaternion _quaternion;
private bool _quaternionDirty;
private bool _flip;
private Vector _flipAxes;
private Vector _xBasis;
private Vector _yBasis;
private Vector _zBasis;
private Vector _xBasisScaled;
private Vector _yBasisScaled;
private Vector _zBasisScaled;
}
}

55
ml_lme/vendor/LeapCSharp/Logger.cs vendored Normal file
View file

@ -0,0 +1,55 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
using System;
using System.Reflection;
namespace LeapInternal
{
public static class Logger
{
/// <summary>
/// Logs message to the a Console.
/// </summary>
public static void Log(object message)
{
UnityEngine.Debug.Log(message);
}
public static void LogStruct(object thisObject, string title = "")
{
try
{
if (!thisObject.GetType().IsValueType)
{
Log(title + " ---- Trying to log non-struct with struct logger");
return;
}
Log(title + " ---- " + thisObject.GetType().ToString());
FieldInfo[] fieldInfos;
fieldInfos = thisObject.GetType().GetFields(
BindingFlags.Public | BindingFlags.NonPublic // Get public and non-public
| BindingFlags.Static | BindingFlags.Instance // Get instance + static
| BindingFlags.FlattenHierarchy); // Search up the hierarchy
// write member names
foreach (FieldInfo fieldInfo in fieldInfos)
{
object obj = fieldInfo.GetValue(thisObject);
string value = obj == null ? "null" : obj.ToString();
Log(" -------- Name: " + fieldInfo.Name + ", Value = " + value);
}
}
catch (Exception exception)
{
Log(exception.Message);
}
}
}
}

362
ml_lme/vendor/LeapCSharp/Matrix.cs vendored Normal file
View file

@ -0,0 +1,362 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The Matrix struct represents a transformation matrix.
///
/// To use this struct to transform a Vector, construct a matrix containing the
/// desired transformation and then use the Matrix::transformPoint() or
/// Matrix.TransformDirection() functions to apply the transform.
///
/// Transforms can be combined by multiplying two or more transform matrices using
/// the * operator.
/// @since 1.0
/// </summary>
public struct Matrix
{
/// <summary>
/// Multiply two matrices.
/// </summary>
public static Matrix operator *(Matrix m1, Matrix m2)
{
return m1._operator_mul(m2);
}
/// <summary>
/// Copy this matrix to the specified array of 9 float values in row-major order.
/// </summary>
public float[] ToArray3x3(float[] output)
{
output[0] = xBasis.x;
output[1] = xBasis.y;
output[2] = xBasis.z;
output[3] = yBasis.x;
output[4] = yBasis.y;
output[5] = yBasis.z;
output[6] = zBasis.x;
output[7] = zBasis.y;
output[8] = zBasis.z;
return output;
}
/// <summary>
/// Copy this matrix to the specified array containing 9 double values in row-major order.
/// </summary>
public double[] ToArray3x3(double[] output)
{
output[0] = xBasis.x;
output[1] = xBasis.y;
output[2] = xBasis.z;
output[3] = yBasis.x;
output[4] = yBasis.y;
output[5] = yBasis.z;
output[6] = zBasis.x;
output[7] = zBasis.y;
output[8] = zBasis.z;
return output;
}
/// <summary>
/// Convert this matrix to an array containing 9 float values in row-major order.
/// </summary>
public float[] ToArray3x3()
{
return ToArray3x3(new float[9]);
}
/// <summary>
/// Copy this matrix to the specified array of 16 float values in row-major order.
/// </summary>
public float[] ToArray4x4(float[] output)
{
output[0] = xBasis.x;
output[1] = xBasis.y;
output[2] = xBasis.z;
output[3] = 0.0f;
output[4] = yBasis.x;
output[5] = yBasis.y;
output[6] = yBasis.z;
output[7] = 0.0f;
output[8] = zBasis.x;
output[9] = zBasis.y;
output[10] = zBasis.z;
output[11] = 0.0f;
output[12] = origin.x;
output[13] = origin.y;
output[14] = origin.z;
output[15] = 1.0f;
return output;
}
/// <summary>
/// Copy this matrix to the specified array of 16 double values in row-major order.
/// </summary>
public double[] ToArray4x4(double[] output)
{
output[0] = xBasis.x;
output[1] = xBasis.y;
output[2] = xBasis.z;
output[3] = 0.0f;
output[4] = yBasis.x;
output[5] = yBasis.y;
output[6] = yBasis.z;
output[7] = 0.0f;
output[8] = zBasis.x;
output[9] = zBasis.y;
output[10] = zBasis.z;
output[11] = 0.0f;
output[12] = origin.x;
output[13] = origin.y;
output[14] = origin.z;
output[15] = 1.0f;
return output;
}
/// <summary>
/// Convert this matrix to an array containing 16 float values in row-major order.
/// </summary>
public float[] ToArray4x4()
{
return ToArray4x4(new float[16]);
}
/// <summary>
/// Constructs a copy of the specified Matrix object.
/// @since 1.0
/// </summary>
public Matrix(Matrix other) :
this()
{
xBasis = other.xBasis;
yBasis = other.yBasis;
zBasis = other.zBasis;
origin = other.origin;
}
/// <summary>
/// Constructs a transformation matrix from the specified basis vectors.
/// @since 1.0
/// </summary>
public Matrix(Vector xBasis, Vector yBasis, Vector zBasis) :
this()
{
this.xBasis = xBasis;
this.yBasis = yBasis;
this.zBasis = zBasis;
this.origin = Vector.Zero;
}
/// <summary>
/// Constructs a transformation matrix from the specified basis and translation vectors.
/// @since 1.0
/// </summary>
public Matrix(Vector xBasis, Vector yBasis, Vector zBasis, Vector origin) :
this()
{
this.xBasis = xBasis;
this.yBasis = yBasis;
this.zBasis = zBasis;
this.origin = origin;
}
/// <summary>
/// Constructs a transformation matrix specifying a rotation around the specified vector.
/// @since 1.0
/// </summary>
public Matrix(Vector axis, float angleRadians) :
this()
{
xBasis = Vector.XAxis;
yBasis = Vector.YAxis;
zBasis = Vector.ZAxis;
origin = Vector.Zero;
SetRotation(axis, angleRadians);
}
/// <summary>
/// Constructs a transformation matrix specifying a rotation around the specified vector
/// and a translation by the specified vector.
/// @since 1.0
/// </summary>
public Matrix(Vector axis, float angleRadians, Vector translation) :
this()
{
xBasis = Vector.XAxis;
yBasis = Vector.YAxis;
zBasis = Vector.ZAxis;
origin = translation;
this.SetRotation(axis, angleRadians);
}
public Matrix(float m00,
float m01,
float m02,
float m10,
float m11,
float m12,
float m20,
float m21,
float m22) :
this()
{
xBasis = new Vector(m00, m01, m02);
yBasis = new Vector(m10, m11, m12);
zBasis = new Vector(m20, m21, m22);
origin = Vector.Zero;
}
public Matrix(float m00,
float m01,
float m02,
float m10,
float m11,
float m12,
float m20,
float m21,
float m22,
float m30,
float m31,
float m32) :
this()
{
xBasis = new Vector(m00, m01, m02);
yBasis = new Vector(m10, m11, m12);
zBasis = new Vector(m20, m21, m22);
origin = new Vector(m30, m31, m32);
}
/// <summary>
/// Sets this transformation matrix to represent a rotation around the specified vector.
///
/// This function erases any previous rotation and scale transforms applied
/// to this matrix, but does not affect translation.
///
/// @since 1.0
/// </summary>
public void SetRotation(Vector axis, float angleRadians)
{
Vector n = axis.Normalized;
float s = (float)Math.Sin(angleRadians);
float c = (float)Math.Cos(angleRadians);
float C = (1 - c);
xBasis = new Vector(n[0] * n[0] * C + c, n[0] * n[1] * C - n[2] * s, n[0] * n[2] * C + n[1] * s);
yBasis = new Vector(n[1] * n[0] * C + n[2] * s, n[1] * n[1] * C + c, n[1] * n[2] * C - n[0] * s);
zBasis = new Vector(n[2] * n[0] * C - n[1] * s, n[2] * n[1] * C + n[0] * s, n[2] * n[2] * C + c);
}
/// <summary>
/// Transforms a vector with this matrix by transforming its rotation,
/// scale, and translation.
///
/// Translation is applied after rotation and scale.
///
/// @since 1.0
/// </summary>
public Vector TransformPoint(Vector point)
{
return xBasis * point.x + yBasis * point.y + zBasis * point.z + origin;
}
/// <summary>
/// Transforms a vector with this matrix by transforming its rotation and
/// scale only.
/// @since 1.0
/// </summary>
public Vector TransformDirection(Vector direction)
{
return xBasis * direction.x + yBasis * direction.y + zBasis * direction.z;
}
/// <summary>
/// Performs a matrix inverse if the matrix consists entirely of rigid
/// transformations (translations and rotations). If the matrix is not rigid,
/// this operation will not represent an inverse.
///
/// Note that all matrices that are directly returned by the API are rigid.
///
/// @since 1.0
/// </summary>
public Matrix RigidInverse()
{
Matrix rotInverse = new Matrix(new Vector(xBasis[0], yBasis[0], zBasis[0]),
new Vector(xBasis[1], yBasis[1], zBasis[1]),
new Vector(xBasis[2], yBasis[2], zBasis[2]));
rotInverse.origin = rotInverse.TransformDirection(-origin);
return rotInverse;
}
/// <summary>
/// Multiply transform matrices.
/// Combines two transformations into a single equivalent transformation.
/// @since 1.0
/// </summary>
private Matrix _operator_mul(Matrix other)
{
return new Matrix(TransformDirection(other.xBasis),
TransformDirection(other.yBasis),
TransformDirection(other.zBasis),
TransformPoint(other.origin));
}
/// <summary>
/// Compare Matrix equality component-wise.
/// @since 1.0
/// </summary>
public bool Equals(Matrix other)
{
return xBasis == other.xBasis &&
yBasis == other.yBasis &&
zBasis == other.zBasis &&
origin == other.origin;
}
/// <summary>
/// Write the matrix to a string in a human readable format.
/// </summary>
public override string ToString()
{
return string.Format("xBasis: {0} yBasis: {1} zBasis: {2} origin: {3}", xBasis, yBasis, zBasis, origin);
}
/// <summary>
/// The basis vector for the x-axis.
/// @since 1.0
/// </summary>
public Vector xBasis { get; set; }
/// <summary>
/// The basis vector for the y-axis.
/// @since 1.0
/// </summary>
public Vector yBasis { get; set; }
/// <summary>
/// The basis vector for the z-axis.
/// @since 1.0
/// </summary>
public Vector zBasis { get; set; }
/// <summary>
/// The translation factors for all three axes.
/// @since 1.0
/// </summary>
public Vector origin { get; set; }
/// <summary>
/// Returns the identity matrix specifying no translation, rotation, and scale.
/// @since 1.0
/// </summary>
public static readonly Matrix Identity = new Matrix(Vector.XAxis, Vector.YAxis, Vector.ZAxis, Vector.Zero);
}
}

View file

@ -0,0 +1,190 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
using AOT;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace LeapInternal
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr Allocate(UInt32 size, eLeapAllocatorType typeHint, IntPtr state);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void Deallocate(IntPtr buffer, IntPtr state);
public static class MemoryManager
{
/// <summary>
/// Specifies whether or not a pooling strategy should be used for the
/// internal MemoryManager. If enabled, memory will be periodically
/// recycled to be used again instead of being deallocated.
///
/// An object may be reclaimed from the pool at any time on the
/// worker thread. If you are running into issues where an object
/// you are working with is being overwritten, consider making a copy,
/// or turning up the MinPoolSize.
/// </summary>
public static bool EnablePooling = true;
/// <summary>
/// Specifies how many objects of a specific type need to be in the pool
/// before they will start to be recycled. Turning this number up can
/// help prevent issues where objects you are working with are being
/// overwritten with new objects. Turning this number down can reduce
/// the total memory footprint used by the memory manager.
/// </summary>
public static uint MinPoolSize = 64;
private static ConcurrentDictionary<IntPtr, ActiveMemoryInfo> _activeMemory =
new ConcurrentDictionary<IntPtr, ActiveMemoryInfo>();
private static ConcurrentDictionary<PoolKey, ConcurrentQueue<object>> _pooledMemory =
new ConcurrentDictionary<PoolKey, ConcurrentQueue<object>>();
[MonoPInvokeCallback(typeof(Allocate))]
public static IntPtr Pin(UInt32 size, eLeapAllocatorType typeHint, IntPtr state)
{
try
{
//Construct a key to identify the desired allocation
PoolKey key = new PoolKey()
{
type = typeHint,
size = size
};
//Attempt to find the pool that holds this type of allocation
ConcurrentQueue<object> pool;
if (!_pooledMemory.TryGetValue(key, out pool))
{
//Construct a new pool if none exists yet
pool = new ConcurrentQueue<object>();
_pooledMemory[key] = pool;
}
//Attempt to get an object from the pool
object memory;
if (EnablePooling && pool.Count > MinPoolSize)
{
pool.TryDequeue(out memory);
}
else
{
//If the pool is empty, we need to construct a new object
switch (typeHint)
{
default:
case eLeapAllocatorType.eLeapAllocatorType_Uint8:
memory = new byte[size];
break;
case eLeapAllocatorType.eLeapAllocatorType_Float:
memory = new float[(size + sizeof(float) - 1) / sizeof(float)];
break;
}
}
//Pin the object so its address will not change
GCHandle handle = GCHandle.Alloc(memory, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();
//Put the information about the newly pinned allocation into the
//active memory map so it can be retrieved and freed layer.
_activeMemory.TryAdd(ptr, new ActiveMemoryInfo()
{
handle = handle,
key = key
});
return ptr;
}
catch (Exception e)
{
UnityEngine.Debug.LogException(e);
}
return IntPtr.Zero;
}
[MonoPInvokeCallback(typeof(Deallocate))]
public static void Unpin(IntPtr ptr, IntPtr state)
{
try
{
//Grab the info for the given pointer
ActiveMemoryInfo info = _activeMemory[ptr];
//First we return the object back to its pool
if (EnablePooling)
{
_pooledMemory[info.key].Enqueue(info.handle.Target);
}
//Then we remove the pointer from the active memory map
ActiveMemoryInfo value;
_activeMemory.TryRemove(ptr, out value);
//Finally we unpin the memory
info.handle.Free();
}
catch (Exception e)
{
UnityEngine.Debug.LogException(e);
}
}
public static object GetPinnedObject(IntPtr ptr)
{
try
{
return _activeMemory[ptr].handle.Target;
}
catch (Exception) { }
return null;
}
private struct PoolKey : IEquatable<PoolKey>
{
public eLeapAllocatorType type;
public UInt32 size;
public override int GetHashCode()
{
return (int)type | (int)size << 4;
}
public bool Equals(PoolKey other)
{
return type == other.type &&
size == other.size;
}
public override bool Equals(object obj)
{
if (obj is PoolKey)
{
return Equals((PoolKey)obj);
}
else
{
return false;
}
}
}
private struct ActiveMemoryInfo
{
public GCHandle handle;
public PoolKey key;
}
}
}

View file

@ -0,0 +1,24 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
/// <summary>
/// Reports whether the message is for
/// a severe failure, a recoverable warning, or a status change.
/// @since 3.0
/// </summary>
public enum MessageSeverity
{
MESSAGE_UNKNOWN = 0,
MESSAGE_CRITICAL = 1,
MESSAGE_WARNING = 2,
/** A verbose, informational message */
MESSAGE_INFORMATION = 3
}
}

View file

@ -0,0 +1,19 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
public struct PointMapping
{
public long frameId;
public long timestamp;
public Vector[] points;
public uint[] ids;
}
}

View file

@ -0,0 +1,92 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
using System;
using System.Runtime.InteropServices;
namespace LeapInternal
{
/**
* A helper class to marshal between unmanaged memory and structs without creating garbage.
*/
public static class StructMarshal<T> where T : struct
{
#if !ENABLE_IL2CPP
[StructLayout(LayoutKind.Sequential)]
private class StructContainer
{
public T value;
}
[ThreadStatic]
private static StructContainer _container;
#endif
private static int _sizeofT;
static StructMarshal()
{
_sizeofT = Marshal.SizeOf(typeof(T));
}
/**
* Returns the size in bytes of the struct of type T. This call is equivalent to
* Marshal.Sizeof(typeof(T)) but caches the result for ease of access.
*/
public static int Size
{
get
{
return _sizeofT;
}
}
/**
* Converts an IntPtr to a struct of type T.
*/
public static void PtrToStruct(IntPtr ptr, out T t)
{
#if ENABLE_IL2CPP
#if UNITY_2018_1_OR_NEWER
unsafe {
Unity.Collections.LowLevel.Unsafe.UnsafeUtility.CopyPtrToStructure((void*)ptr, out t);
}
#else
#error UnityModules Only supports IL2CPP on versions of Unity 2018.1 or greater.
#endif
#else
if (_container == null)
{
_container = new StructContainer();
}
try
{
Marshal.PtrToStructure(ptr, _container);
t = _container.value;
}
catch (Exception e)
{
UnityEngine.Debug.LogException(e);
t = default(T);
}
#endif
}
/**
* Converts a single element in an array pointed to by ptr to a struct
* of type T. This method does not and cannot do any bounds checking!
* This method does not create any garbage.
*/
public static void ArrayElementToStruct(IntPtr ptr, int arrayIndex, out T t)
{
PtrToStruct(new IntPtr(ptr.ToInt64() + _sizeofT * arrayIndex), out t);
}
}
}

View file

@ -0,0 +1,176 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
public static class TransformExtensions
{
/**
* Does an in-place rigid transformation of a Frame.
*
* @param transform A LeapTransform containing the desired translation, rotation, and scale
* to be applied to the Frame.
*/
public static Frame Transform(this Frame frame, LeapTransform transform)
{
for (int i = frame.Hands.Count; i-- != 0;)
{
frame.Hands[i].Transform(transform);
}
return frame;
}
/**
* Returns a new frame that is a copy of a frame, with an additional rigid
* transformation applied to it.
*
* @param transform The transformation to be applied to the copied frame.
*/
public static Frame TransformedCopy(this Frame frame, LeapTransform transform)
{
return new Frame().CopyFrom(frame).Transform(transform);
}
/**
* Does an in-place rigid transformation of a Hand.
*
* @param transform A LeapTransform containing the desired translation, rotation, and scale
* to be applied to the Hand.
*/
public static Hand Transform(this Hand hand, LeapTransform transform)
{
hand.PalmPosition = transform.TransformPoint(hand.PalmPosition);
hand.StabilizedPalmPosition = transform.TransformPoint(hand.StabilizedPalmPosition);
hand.PalmVelocity = transform.TransformVelocity(hand.PalmVelocity);
hand.PalmNormal = transform.TransformDirection(hand.PalmNormal);
hand.Direction = transform.TransformDirection(hand.Direction);
hand.WristPosition = transform.TransformPoint(hand.WristPosition);
hand.PalmWidth *= Math.Abs(transform.scale.x);
hand.Rotation = transform.TransformQuaternion(hand.Rotation);
hand.Arm.Transform(transform);
for (int i = 5; i-- != 0;)
{
hand.Fingers[i].Transform(transform);
}
return hand;
}
/**
* Returns a new hand that is a copy of a hand, with an additional rigid
* transformation applied to it.
*
* @param transform The transformation to be applied to the copied hand.
*/
public static Hand TransformedCopy(this Hand hand, LeapTransform transform)
{
return new Hand().CopyFrom(hand).Transform(transform);
}
/**
* Does an in-place rigid transformation of a Finger.
*
* @param transform A LeapTransform containing the desired translation, rotation, and scale
* to be applied to the Finger.
*/
public static Finger Transform(this Finger finger, LeapTransform transform)
{
Bone nextBone = finger.bones[3];
nextBone.NextJoint = transform.TransformPoint(nextBone.NextJoint);
finger.TipPosition = nextBone.NextJoint;
for (int i = 3; i-- != 0;)
{
Bone bone = finger.bones[i];
bone.NextJoint = nextBone.PrevJoint = transform.TransformPoint(bone.NextJoint);
nextBone.TransformGivenJoints(transform);
nextBone = bone;
}
nextBone.PrevJoint = transform.TransformPoint(nextBone.PrevJoint);
nextBone.TransformGivenJoints(transform);
finger.Direction = finger.bones[2].Direction;
finger.Width *= Math.Abs(transform.scale.x);
finger.Length *= Math.Abs(transform.scale.z);
return finger;
}
/**
* Returns a new finger that is a copy of a finger, with an additional rigid
* transformation applied to it.
*
* @param transform The transformation to be applied to the copied finger.
*/
public static Finger TransformedCopy(this Finger finger, LeapTransform transform)
{
return new Finger().CopyFrom(finger).Transform(transform);
}
/**
* Does an in-place rigid transformation of a Bone.
*
* @param transform A LeapTransform containing the desired translation, rotation, and scale
- * to be applied to the bone.
*/
public static Bone Transform(this Bone bone, LeapTransform transform)
{
bone.PrevJoint = transform.TransformPoint(bone.PrevJoint);
bone.NextJoint = transform.TransformPoint(bone.NextJoint);
bone.TransformGivenJoints(transform);
return bone;
}
/**
* Does an in-place rigid transformation of a Bone, assuming the joints have already been transformed.
*
* @param transform A LeapTransform containing the desired translation, rotation, and scale
- * to be applied to the bone.
*/
internal static void TransformGivenJoints(this Bone bone, LeapTransform transform)
{
bone.Length *= Math.Abs(transform.scale.z);
bone.Center = (bone.PrevJoint + bone.NextJoint) / 2.0f;
if (bone.Length < float.Epsilon)
{
bone.Direction = Vector.Zero;
}
else
{
bone.Direction = (bone.NextJoint - bone.PrevJoint) / bone.Length;
}
bone.Width *= Math.Abs(transform.scale.x);
bone.Rotation = transform.TransformQuaternion(bone.Rotation);
}
/**
* Returns a new bone that is a copy of a bone, with an additional rigid
* transformation applied to it.
*
* @param transform The transformation to be applied to the copied bone.
*/
public static Bone TransformedCopy(this Bone bone, LeapTransform transform)
{
return new Bone().CopyFrom(bone).Transform(transform);
}
}
}

425
ml_lme/vendor/LeapCSharp/Vector.cs vendored Normal file
View file

@ -0,0 +1,425 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// Constants used in Leap Motion math functions.
/// </summary>
public static class Constants
{
public const float PI = 3.1415926536f;
public const float DEG_TO_RAD = 0.0174532925f;
public const float RAD_TO_DEG = 57.295779513f;
public const float EPSILON = 1.192092896e-07f;
}
/// <summary>
/// The Vector struct represents a three-component mathematical vector or point
/// such as a direction or position in three-dimensional space.
///
/// The Leap Motion software employs a right-handed Cartesian coordinate system.
/// Values given are in units of real-world millimeters. The origin is centered
/// at the center of the Leap Motion Controller. The x- and z-axes lie in the horizontal
/// plane, with the x-axis running parallel to the long edge of the device.
/// The y-axis is vertical, with positive values increasing upwards (in contrast
/// to the downward orientation of most computer graphics coordinate systems).
/// The z-axis has positive values increasing away from the computer screen.
/// @since 1.0
/// </summary>
[Serializable]
public struct Vector : IEquatable<Vector>
{
public static Vector operator +(Vector v1, Vector v2)
{
return new Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
}
public static Vector operator -(Vector v1, Vector v2)
{
return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
}
public static Vector operator *(Vector v1, float scalar)
{
return new Vector(v1.x * scalar, v1.y * scalar, v1.z * scalar);
}
public static Vector operator *(float scalar, Vector v1)
{
return new Vector(v1.x * scalar, v1.y * scalar, v1.z * scalar);
}
public static Vector operator /(Vector v1, float scalar)
{
return new Vector(v1.x / scalar, v1.y / scalar, v1.z / scalar);
}
public static Vector operator -(Vector v1)
{
return new Vector(-v1.x, -v1.y, -v1.z);
}
public static bool operator ==(Vector v1, Vector v2)
{
return v1.Equals(v2);
}
public static bool operator !=(Vector v1, Vector v2)
{
return !v1.Equals(v2);
}
public float[] ToFloatArray()
{
return new float[] { x, y, z };
}
/// <summary>
/// Creates a new Vector with the specified component values.
/// @since 1.0
/// </summary>
public Vector(float x, float y, float z) :
this()
{
this.x = x;
this.y = y;
this.z = z;
}
/// <summary>
/// Copies the specified Vector.
/// @since 1.0
/// </summary>
public Vector(Vector vector) :
this()
{
x = vector.x;
y = vector.y;
z = vector.z;
}
/// <summary>
/// The distance between the point represented by this Vector
/// object and a point represented by the specified Vector object.
///
/// @since 1.0
/// </summary>
public float DistanceTo(Vector other)
{
return (float)Math.Sqrt((x - other.x) * (x - other.x) +
(y - other.y) * (y - other.y) +
(z - other.z) * (z - other.z));
}
/// <summary>
/// The angle between this vector and the specified vector in radians.
///
/// The angle is measured in the plane formed by the two vectors. The
/// angle returned is always the smaller of the two conjugate angles.
/// Thus A.angleTo(B) == B.angleTo(A) and is always a positive
/// value less than or equal to pi radians (180 degrees).
///
/// If either vector has zero length, then this function returns zero.
/// @since 1.0
/// </summary>
public float AngleTo(Vector other)
{
float denom = MagnitudeSquared * other.MagnitudeSquared;
if (denom <= Constants.EPSILON)
{
return 0.0f;
}
float val = Dot(other) / (float)Math.Sqrt(denom);
if (val >= 1.0f)
{
return 0.0f;
}
else if (val <= -1.0f)
{
return Constants.PI;
}
return (float)Math.Acos(val);
}
/// <summary>
/// The dot product of this vector with another vector.
///
/// The dot product is the magnitude of the projection of this vector
/// onto the specified vector.
/// @since 1.0
/// </summary>
public float Dot(Vector other)
{
return (x * other.x) + (y * other.y) + (z * other.z);
}
/// <summary>
/// The cross product of this vector and the specified vector.
///
/// The cross product is a vector orthogonal to both original vectors.
/// It has a magnitude equal to the area of a parallelogram having the
/// two vectors as sides. The direction of the returned vector is
/// determined by the right-hand rule. Thus A.cross(B) == -B.cross(A).
///
/// @since 1.0
/// </summary>
public Vector Cross(Vector other)
{
return new Vector((y * other.z) - (z * other.y),
(z * other.x) - (x * other.z),
(x * other.y) - (y * other.x));
}
/// <summary>
/// Returns a string containing this vector in a human readable format: (x, y, z).
/// @since 1.0
/// </summary>
public override string ToString()
{
return "(" + x + ", " + y + ", " + z + ")";
}
/// <summary>
/// Compare Vector equality component-wise.
/// @since 1.0
/// </summary>
public bool Equals(Vector v)
{
return x.NearlyEquals(v.x) && y.NearlyEquals(v.y) && z.NearlyEquals(v.z);
}
public override bool Equals(Object obj)
{
return obj is Vector && Equals((Vector)obj);
}
/// <summary>
/// Returns true if all of the vector's components are finite. If any
/// component is NaN or infinite, then this returns false.
/// @since 1.0
/// </summary>
public bool IsValid()
{
return !(float.IsNaN(x) || float.IsInfinity(x) ||
float.IsNaN(y) || float.IsInfinity(y) ||
float.IsNaN(z) || float.IsInfinity(z));
}
/// <summary>
/// Index vector components numerically.
/// Index 0 is x, index 1 is y, and index 2 is z.
/// @since 1.0
/// </summary>
public float this[uint index]
{
get
{
if (index == 0)
return x;
if (index == 1)
return y;
if (index == 2)
return z;
throw new IndexOutOfRangeException();
}
set
{
if (index == 0)
x = value;
if (index == 1)
y = value;
if (index == 2)
z = value;
throw new IndexOutOfRangeException();
}
}
public float x;
public float y;
public float z;
/// <summary>
/// The magnitude, or length, of this vector.
///
/// The magnitude is the L2 norm, or Euclidean distance between the origin and
/// the point represented by the (x, y, z) components of this Vector object.
/// @since 1.0
/// </summary>
public float Magnitude
{
get { return (float)Math.Sqrt(x * x + y * y + z * z); }
}
/// <summary>
/// The square of the magnitude, or length, of this vector.
/// @since 1.0
/// </summary>
public float MagnitudeSquared
{
get { return x * x + y * y + z * z; }
}
/// <summary>
/// The pitch angle in radians.
///
/// Pitch is the angle between the negative z-axis and the projection of
/// the vector onto the y-z plane. In other words, pitch represents rotation
/// around the x-axis.
/// If the vector points upward, the returned angle is between 0 and pi radians
/// (180 degrees); if it points downward, the angle is between 0 and -pi radians.
///
/// @since 1.0
/// </summary>
public float Pitch
{
get { return (float)Math.Atan2(y, -z); }
}
/// <summary>
/// The roll angle in radians.
///
/// Roll is the angle between the y-axis and the projection of
/// the vector onto the x-y plane. In other words, roll represents rotation
/// around the z-axis. If the vector points to the left of the y-axis,
/// then the returned angle is between 0 and pi radians (180 degrees);
/// if it points to the right, the angle is between 0 and -pi radians.
///
/// Use this function to get roll angle of the plane to which this vector is a
/// normal. For example, if this vector represents the normal to the palm,
/// then this function returns the tilt or roll of the palm plane compared
/// to the horizontal (x-z) plane.
///
/// @since 1.0
/// </summary>
public float Roll
{
get { return (float)Math.Atan2(x, -y); }
}
/// <summary>
/// The yaw angle in radians.
///
/// Yaw is the angle between the negative z-axis and the projection of
/// the vector onto the x-z plane. In other words, yaw represents rotation
/// around the y-axis. If the vector points to the right of the negative z-axis,
/// then the returned angle is between 0 and pi radians (180 degrees);
/// if it points to the left, the angle is between 0 and -pi radians.
///
/// @since 1.0
/// </summary>
public float Yaw
{
get { return (float)Math.Atan2(x, -z); }
}
/// <summary>
/// A normalized copy of this vector.
///
/// A normalized vector has the same direction as the original vector,
/// but with a length of one.
///
/// @since 1.0
/// </summary>
public Vector Normalized
{
get
{
float denom = MagnitudeSquared;
if (denom <= Constants.EPSILON)
{
return Zero;
}
denom = 1.0f / (float)Math.Sqrt(denom);
return new Vector(x * denom, y * denom, z * denom);
}
}
/// <summary>
/// The zero vector: (0, 0, 0)
/// </summary>
public static readonly Vector Zero = new Vector(0, 0, 0);
/// <summary>
/// The ones vector: (1, 1, 1)
/// </summary>
public static readonly Vector Ones = new Vector(1, 1, 1);
/// <summary>
/// The x-axis unit vector: (1, 0, 0)
/// </summary>
public static readonly Vector XAxis = new Vector(1, 0, 0);
/// <summary>
/// The y-axis unit vector: (0, 1, 0)
/// </summary>
public static readonly Vector YAxis = new Vector(0, 1, 0);
/// <summary>
/// The z-axis unit vector: (0, 0, 1)
/// </summary>
public static readonly Vector ZAxis = new Vector(0, 0, 1);
/// <summary>
/// The unit vector pointing forward along the negative z-axis: (0, 0, -1)
/// </summary>
public static readonly Vector Forward = new Vector(0, 0, -1);
/// <summary>
/// The unit vector pointing backward along the positive z-axis: (0, 0, 1)
/// </summary>
public static readonly Vector Backward = new Vector(0, 0, 1);
/// <summary>
/// The unit vector pointing left along the negative x-axis: (-1, 0, 0)
/// </summary>
public static readonly Vector Left = new Vector(-1, 0, 0);
/// <summary>
/// The unit vector pointing right along the positive x-axis: (1, 0, 0)
/// </summary>
public static readonly Vector Right = new Vector(1, 0, 0);
/// <summary>
/// The unit vector pointing up along the positive y-axis: (0, 1, 0)
/// </summary>
public static readonly Vector Up = new Vector(0, 1, 0);
/// <summary>
/// The unit vector pointing down along the negative y-axis: (0, -1, 0)
/// </summary>
public static readonly Vector Down = new Vector(0, -1, 0);
public static Vector Lerp(Vector a, Vector b, float t)
{
return new Vector(
a.x + t * (b.x - a.x),
a.y + t * (b.y - a.y),
a.z + t * (b.z - a.z)
);
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 23 + x.GetHashCode();
hash = hash * 23 + y.GetHashCode();
hash = hash * 23 + z.GetHashCode();
return hash;
}
}
}
}