VR4Medical/ICI/Library/PackageCache/com.unity.xr.hands@b137b9cef9d8/Runtime/XRHandJoint.cs
2025-07-29 13:45:50 +03:00

261 lines
10 KiB
C#

using System;
using System.Runtime.InteropServices;
using UnityEngine.XR.Hands.ProviderImplementation;
namespace UnityEngine.XR.Hands
{
/// <summary>
/// Represents a joint of an <see cref="XRHand"/>.
/// </summary>
/// <remarks>
/// The term "joint" should be taken loosely in this context. In addition to the
/// anatomical finger joints, the list of joints includes the fingertips, a point on the palm
/// and a point on the wrist. See <see cref="XRHandJointID"/> for the full list of
/// joints.
///
/// Refer to [Hand data model](xref:xrhands-data-model) for a description of the joint locations
/// and the data they contain.
/// </remarks>
[StructLayout(LayoutKind.Sequential)]
public struct XRHandJoint : IEquatable<XRHandJoint>
{
/// <summary>
/// The ID of this joint.
/// </summary>
/// <value>The joint ID.</value>
public XRHandJointID id => (XRHandJointID)(m_IdAndHandedness & ~k_IsRightHandBit);
/// <summary>
/// Denotes which hand this joint is on.
/// </summary>
/// <value>Right or left.</value>
public Handedness handedness => (m_IdAndHandedness & k_IsRightHandBit) != 0 ? Handedness.Right : Handedness.Left;
/// <summary>
/// Represents which tracking data is valid.
/// </summary>
/// <value>A flag is set for each valid type of data. If the
/// The <see cref="XRHandJointTrackingState.WillNeverBeValid"/> flag is set
/// when this joind ID isn't supported by the hand data provider.</value>
public XRHandJointTrackingState trackingState => m_TrackingState;
/// <summary>
/// Retrieves the joint's radius, if available.
/// </summary>
/// <param name="radius">
/// Assigned the tracked radius of this joint, if successful.
/// Set to zero, if unsuccessful.
/// </param>
/// <returns>
/// Returns <see langword="true"/> if successful and the radius was
/// filled out with valid tracking data, returns <see langword="false"/>
/// otherwise.
/// </returns>
public bool TryGetRadius(out float radius)
{
if ((m_TrackingState & XRHandJointTrackingState.Radius) == XRHandJointTrackingState.None)
{
radius = 0.0f;
return false;
}
radius = m_Radius;
return true;
}
/// <summary>
/// Retrieves the joint's pose, if available.
/// </summary>
/// <param name="pose">
/// Assigned the tracked pose of this joint, if successful.
/// Set to <see cref="Pose.identity"/>, if unsuccessful.
/// </param>
/// <returns>
/// Returns <see langword="true"/> if successful and the joint pose was
/// filled out with valid tracking data, returns <see langword="false"/>
/// otherwise.
/// </returns>
/// <remarks>
/// Joint poses are relative to the real-world point chosen by the user's device.
///
/// To transform to world space so that the joint appears in the correct location
/// relative to the user, transform the pose based on the
/// [XROrigin](xref:Unity.XR.CoreUtils.XROrigin).
/// </remarks>
/// <example>
/// <para>
/// The following example illustrates how to transform a pose into world space using the
/// transform from the XROrigin object in a scene.
/// </para>
/// <code>
/// public Pose ToWorldPose(XRHandJoint joint, Transform origin)
/// {
/// Pose xrOriginPose = new Pose(origin.position, origin.rotation);
/// if (joint.TryGetPose(out Pose jointPose))
/// {
/// return jointPose.GetTransformedBy(xrOriginPose);
/// }
/// else
/// {
/// return Pose.identity;
/// }
/// }
/// </code>
/// </example>
public bool TryGetPose(out Pose pose)
{
if ((m_TrackingState & XRHandJointTrackingState.Pose) == XRHandJointTrackingState.None)
{
pose = Pose.identity;
return false;
}
pose = m_Pose;
return true;
}
/// <summary>
/// Retrieves the joint's linear velocity vector, if available.
/// </summary>
/// <param name="linearVelocity">
/// Assigned the tracked linear velocity of this joint, if successful.
/// Set to <see cref="Vector3.zero"/>, if unsuccessful.
/// </param>
/// <returns>
/// Returns <see langword="true"/> if successful and the velocity was
/// filled out with valid tracking data, returns <see langword="false"/>
/// otherwise.
/// </returns>
/// <remarks>
/// To transform to world space so that the vector has the correct direction
/// relative to the user, rotate this by the rotation of the
/// [XROrigin](xref:Unity.XR.CoreUtils.XROrigin).
/// </remarks>
public bool TryGetLinearVelocity(out Vector3 linearVelocity)
{
if ((m_TrackingState & XRHandJointTrackingState.LinearVelocity) == XRHandJointTrackingState.None)
{
linearVelocity = Vector3.zero;
return false;
}
linearVelocity = m_LinearVelocity;
return true;
}
/// <summary>
/// Retrieves the joint's angular velocity vector, if available
/// </summary>
/// <param name="angularVelocity">
/// Assigned the tracked angular velocity of this joint, if successful.
/// Set to <see cref="Vector3.zero"/>, if unsuccessful.
/// </param>
/// <returns>
/// Returns <see langword="true"/> if successful and the angular
/// velocity filled out with valid tracking data, returns
/// <see langword="false"/> otherwise.
/// </returns>
/// <remarks>
/// To transform to world space so that the vector has the correct direction
/// relative to the user, rotate this by the rotation of the
/// [XROrigin](xref:Unity.XR.CoreUtils.XROrigin).
/// </remarks>
public bool TryGetAngularVelocity(out Vector3 angularVelocity)
{
if ((m_TrackingState & XRHandJointTrackingState.AngularVelocity) == XRHandJointTrackingState.None)
{
angularVelocity = Vector3.zero;
return false;
}
angularVelocity = m_AngularVelocity;
return true;
}
/// <summary>
/// Returns a string representation of the XRHandJoint.
/// </summary>
/// <returns>
/// String representation of the value.
/// </returns>
public override string ToString()
{
return string.Format(
"[{0} {1}] Pose: {2} | Radius: {3} | Linear Velocity: {4} | Angular Velocity: {5} | Tracking State: {6}",
handedness, id, m_Pose.ToString("F4"), m_Radius.ToString("F4"), m_LinearVelocity.ToString("F4"), m_AngularVelocity.ToString("F4"), m_TrackingState);
}
/// <summary>
/// Tests for equality.
/// </summary>
/// <param name="other">The <see cref="XRHandJoint"/> to compare against.</param>
/// <returns>
/// Returns <see langword="true"/> if the underlying native pointers are
/// the same. Returns <see langword="false"/> otherwise.
/// </returns>
public bool Equals(XRHandJoint other)
{
return m_IdAndHandedness == other.m_IdAndHandedness &&
m_Pose == other.m_Pose &&
m_Radius == other.m_Radius &&
m_LinearVelocity == other.m_LinearVelocity &&
m_AngularVelocity == other.m_AngularVelocity &&
m_TrackingState == other.m_TrackingState;
}
/// <summary>
/// Tests for equality.
/// </summary>
/// <param name="obj">An <see cref="object"/> to compare against.</param>
/// <returns>
/// Returns <see langword="true"/> if <paramref name="obj"/> is an
/// <see cref="XRHandJoint"/> and it compares equal to this one using
/// <see cref="Equals(UnityEngine.XR.Hands.XRHandJoint)"/>.
/// </returns>
public override bool Equals(object obj) => obj is XRHandJoint other && Equals(other);
/// <summary>
/// Computes a hash code from all fields of XRHandJoint.
/// </summary>
/// <returns>Returns a hash code of this object.</returns>
public override int GetHashCode()
{
unchecked
{
int hash = m_IdAndHandedness.GetHashCode();
hash = hash * 486187739 + m_Pose.GetHashCode();
hash = hash * 486187739 + m_Radius.GetHashCode();
hash = hash * 486187739 + m_LinearVelocity.GetHashCode();
hash = hash * 486187739 + m_AngularVelocity.GetHashCode();
hash = hash * 486187739 + m_TrackingState.GetHashCode();
return hash;
}
}
/// <summary>
/// Tests for equality. Same as <see cref="Equals(UnityEngine.XR.Hands.XRHandJoint)"/>.
/// </summary>
/// <param name="lhs">The left-hand side of the comparison.</param>
/// <param name="rhs">The right-hand side of the comparison.</param>
/// <returns>Returns the same value as <see cref="Equals(UnityEngine.XR.Hands.XRHandJoint)"/>.</returns>
public static bool operator ==(XRHandJoint lhs, XRHandJoint rhs) => lhs.Equals(rhs);
/// <summary>
/// Tests for inequality. Same as !<see cref="Equals(UnityEngine.XR.Hands.XRHandJoint)"/>
/// </summary>
/// <param name="lhs">The left-hand side of the comparison.</param>
/// <param name="rhs">The right-hand side of the comparison.</param>
/// <returns>Returns the negation of <see cref="Equals(UnityEngine.XR.Hands.XRHandJoint)"/>.</returns>
public static bool operator !=(XRHandJoint lhs, XRHandJoint rhs) => !lhs.Equals(rhs);
internal int m_IdAndHandedness;
internal Pose m_Pose;
internal float m_Radius;
internal Vector3 m_LinearVelocity;
internal Vector3 m_AngularVelocity;
internal XRHandJointTrackingState m_TrackingState;
internal const int k_IsRightHandBit = 1 << 31;
}
}