VR4RoboticArm2/VR4RoboticArm/Library/PackageCache/com.meta.xr.sdk.interaction/Runtime/Scripts/Input/Hands/FingersMetadata.cs
IonutMocanu d7aba243a2 Main
2025-09-08 11:04:02 +03:00

249 lines
9.3 KiB
C#

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
namespace Oculus.Interaction.Input
{
public enum JointFreedom
{
Free,
Constrained,
Locked
}
/// <summary>
/// This class contains a series of useful fingers-related data structures
/// to be used for optimal calculations without relying in dictionaries.
///
/// Since we always assume the hand pose information to be sorted in
/// the HAND_JOINT_IDS order, we can align multiple data structures
/// that follow that convention.
/// </summary>
public class FingersMetadata
{
public static JointFreedom[] DefaultFingersFreedom()
{
return new JointFreedom[Constants.NUM_FINGERS]
{
JointFreedom.Locked,
JointFreedom.Locked,
JointFreedom.Constrained,
JointFreedom.Constrained,
JointFreedom.Free
};
}
/// <summary>
/// The index within HAND_JOINT_IDS for the given joint
/// </summary>
/// <param name="id">The HandJoint to check the id for</param>
/// <returns>An index in HAND_JOINT_IDS or -1 if invalud</returns>
public static int HandJointIdToIndex(HandJointId id)
{
return JOINT_TO_INDEX[(int)id];
}
/// <summary>
/// Valid identifiers for the i-bone of a hand.
/// </summary>
public static readonly HandJointId[] HAND_JOINT_IDS = new HandJointId[]
{
#if ISDK_OPENXR_HAND
HandJointId.HandThumb1,
HandJointId.HandThumb2,
HandJointId.HandThumb3,
HandJointId.HandIndex0,
HandJointId.HandIndex1,
HandJointId.HandIndex2,
HandJointId.HandIndex3,
HandJointId.HandMiddle0,
HandJointId.HandMiddle1,
HandJointId.HandMiddle2,
HandJointId.HandMiddle3,
HandJointId.HandRing0,
HandJointId.HandRing1,
HandJointId.HandRing2,
HandJointId.HandRing3,
HandJointId.HandPinky0,
HandJointId.HandPinky1,
HandJointId.HandPinky2,
HandJointId.HandPinky3
#else
HandJointId.HandThumb0,
HandJointId.HandThumb1,
HandJointId.HandThumb2,
HandJointId.HandThumb3,
HandJointId.HandIndex1,
HandJointId.HandIndex2,
HandJointId.HandIndex3,
HandJointId.HandMiddle1,
HandJointId.HandMiddle2,
HandJointId.HandMiddle3,
HandJointId.HandRing1,
HandJointId.HandRing2,
HandJointId.HandRing3,
HandJointId.HandPinky0,
HandJointId.HandPinky1,
HandJointId.HandPinky2,
HandJointId.HandPinky3
#endif
};
/// <summary>
/// This collection contains the joints of each finger minus the tip in ascending order
/// </summary>
public static readonly HandJointId[][] FINGER_TO_JOINTS = InitializeFingerToJoint();
/// <summary>
/// This collection is used to convert from Finger id to the list indices
/// of its joint in the HAND_JOINT_IDS list.
/// </summary>
public static readonly int[][] FINGER_TO_JOINT_INDEX = InitializeFingerToJointIndex();
/// <summary>
/// Array order following HAND_JOINT_IDS that indicates if the i joint
/// can spread (rotate around Y). Should be true for the root of the fingers
/// but Pink and Thumb are special cases
/// </summary>
public static readonly bool[] HAND_JOINT_CAN_SPREAD = InitializeCanSpread();
/// <summary>
/// Array order following HAND_JOINT_IDS that indicates if the i joint
/// can move or it is fixed to the wrist. Should be true for the Metacarpals
/// but Pink and Thumb are special cases
/// </summary>
public static readonly bool[] HAND_JOINT_CAN_MOVE = InitializeCanMove();
/// <summary>
/// Map any HandJointId to joint index of each finger, where the joint index
/// starts at 0 (toward wrist) and increments for each joint toward the fingertip.
/// </summary>
public static readonly int[] JOINT_TO_FINGER_INDEX = InitializeJointToFingerIndex();
/// <summary>
/// Map HandJointId to HandFinger
/// </summary>
[Obsolete("Use " + nameof(HandJointUtils.JointToFingerList) + " instead")]
public static readonly HandFinger[] JOINT_TO_FINGER = null;
private static int[] JOINT_TO_INDEX = InitializeHandJointIdToIndex();
#region Initializers
private static int[] InitializeHandJointIdToIndex()
{
int[] indexes = new int[(int)HandJointId.HandEnd];
for (HandJointId jointId = HandJointId.HandStart; jointId < HandJointId.HandEnd; jointId++)
{
indexes[(int)jointId] = Array.FindIndex(HAND_JOINT_IDS, (HandJointId joint) => joint == jointId);
}
return indexes;
}
private static HandJointId[][] InitializeFingerToJoint()
{
HandJointId[][] joints = new HandJointId[HandJointUtils.FingerToJointList.Count][];
for (int i = 0; i < HandJointUtils.FingerToJointList.Count; i++)
{
//-1 to the Length to skip the Finger tip
int fingerLength = HandJointUtils.FingerToJointList[i].Length - 1;
joints[i] = new HandJointId[fingerLength];
Array.Copy(HandJointUtils.FingerToJointList[i], joints[i], fingerLength);
}
return joints;
}
private static int[][] InitializeFingerToJointIndex()
{
HandJointId[][] fingerToJoints = InitializeFingerToJoint();
int[] jointToIndex = InitializeHandJointIdToIndex();
int[][] indexes = new int[fingerToJoints.Length][];
for (int i = 0; i < fingerToJoints.Length; i++)
{
int[] fingerJoints = new int[fingerToJoints[i].Length];
for (int j = 0; j < fingerToJoints[i].Length; j++)
{
fingerJoints[j] = jointToIndex[(int)fingerToJoints[i][j]];
}
indexes[i] = fingerJoints;
}
return indexes;
}
private static int[] InitializeJointToFingerIndex()
{
int[] fingerIndexes = new int[(int)HandJointId.HandEnd];
for (HandJointId jointId = HandJointId.HandStart; jointId < HandJointId.HandEnd; jointId++)
{
//Count the amount of joints in the hierarchy until it exits the finger
int fingerIndex = -1;
for (HandJointId i = jointId;
HandJointUtils.JointToFingerList[(int)i] != HandFinger.Invalid;
i = HandJointUtils.JointParentList[(int)i])
{
fingerIndex++;
}
fingerIndexes[(int)jointId] = fingerIndex;
}
return fingerIndexes;
}
private static bool[] InitializeCanSpread()
{
int[] jointToFingerIndex = InitializeJointToFingerIndex();
bool[] canSpread = new bool[HAND_JOINT_IDS.Length];
for (int i = 0; i < HAND_JOINT_IDS.Length; i++)
{
HandJointId jointId = HAND_JOINT_IDS[i];
int fingerIndex = jointToFingerIndex[(int)jointId];
#if ISDK_OPENXR_HAND
canSpread[i] = fingerIndex <= 1 //most fingers start in the metacarpal
&& jointId != HandJointId.HandThumb2;
#else
canSpread[i] = fingerIndex == 0 //most fingers start in the proximal
|| jointId == HandJointId.HandThumb1 //thumb starts in the metacarpal
|| jointId == HandJointId.HandPinky1; //pinky starts in the metacarpal
#endif
}
return canSpread;
}
private static bool[] InitializeCanMove()
{
bool[] canMove = new bool[HAND_JOINT_IDS.Length];
#if ISDK_OPENXR_HAND
for (int i = 0; i < HAND_JOINT_IDS.Length; i++)
{
HandJointId jointId = HAND_JOINT_IDS[i];
canMove[i] = jointId != HandJointId.HandIndex0
&& jointId != HandJointId.HandMiddle0
&& jointId != HandJointId.HandRing0;
}
#else
Array.Fill(canMove, true);
#endif
return canMove;
}
#endregion
}
}