// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using System; using UltimateXR.Core; using UltimateXR.Core.Math; using UnityEngine; namespace UltimateXR.Avatar.Rig { /// /// Stores information of an avatar rig's finger. /// [Serializable] public class UxrAvatarFingerInfo { #region Inspector Properties/Serialized Fields [SerializeField] private UxrAvatar _avatar; [SerializeField] private UxrHandSide _side; [SerializeField] private UxrFingerType _finger; [SerializeField] private UxrAvatarFingerBoneInfo _metacarpalInfo; [SerializeField] private UxrAvatarFingerBoneInfo _proximalInfo; [SerializeField] private UxrAvatarFingerBoneInfo _intermediateInfo; [SerializeField] private UxrAvatarFingerBoneInfo _distalInfo; [SerializeField] private Vector3 _distalLocalTip; [SerializeField] private Vector3 _distalLocalFingerPrintCenter; #endregion #region Public Types & Data /// /// Gets the metacarpal bone info. /// public UxrAvatarFingerBoneInfo MetacarpalInfo => _metacarpalInfo; /// /// Gets the proximal bone info. /// public UxrAvatarFingerBoneInfo ProximalInfo => _proximalInfo; /// /// Gets the intermediate bone info. /// public UxrAvatarFingerBoneInfo IntermediateInfo => _intermediateInfo; /// /// Gets the distal bone info. /// public UxrAvatarFingerBoneInfo DistalInfo => _distalInfo; /// /// Gets the finger tip in local coordinates of the distal bone. /// public Vector3 DistalLocalTip => _distalLocalTip; /// /// Gets an approximate position of the finger print center in local coordinates of the distal bone. The position is /// computed as a position at 2/3 of the distance between the distal bone start and the tip and at the bottom part of /// the distal using the distal radius. /// public Vector3 DistalLocalFingerPrintCenter => _distalLocalFingerPrintCenter; /// /// Gets the tip position in world-space. /// public Vector3 TipPosition { get { if (_avatar) { UxrAvatarFinger avatarFinger = _avatar.GetHand(_side).GetFinger(_finger); if (avatarFinger.Distal) { return avatarFinger.Distal.TransformPoint(_distalLocalTip); } } return Vector3.zero; } } /// /// Gets the tip forward direction in world-space. /// public Vector3 TipDirection { get { if (_avatar) { UxrAvatarFinger avatarFinger = _avatar.GetHand(_side).GetFinger(_finger); if (avatarFinger.Distal) { UxrUniversalLocalAxes fingerAxes = _avatar.AvatarRigInfo.GetArmInfo(_side).FingerUniversalLocalAxes; return avatarFinger.Distal.TransformVector(fingerAxes.LocalForward); } } return Vector3.zero; } } /// /// Gets the finger print approximate position. The position is computed as a position at 2/3 of the distance between /// the distal bone start and the tip and at the bottom part of the distal using the distal radius. /// public Vector3 FingerPrintPosition { get { if (_avatar) { UxrAvatarFinger avatarFinger = _avatar.GetHand(_side).GetFinger(_finger); if (avatarFinger.Distal) { return avatarFinger.Distal.TransformPoint(_distalLocalFingerPrintCenter); } } return Vector3.zero; } } /// /// Gets the finger print direction in world-space. The direction points from the finger print center downwards. /// public Vector3 FingerPrintDirection { get { if (_avatar) { UxrAvatarFinger avatarFinger = _avatar.GetHand(_side).GetFinger(_finger); if (avatarFinger.Distal) { UxrUniversalLocalAxes fingerAxes = _avatar.AvatarRigInfo.GetArmInfo(_side).FingerUniversalLocalAxes; return -avatarFinger.Distal.TransformVector(fingerAxes.LocalUp); } } return Vector3.zero; } } #endregion #region Internal Methods /// /// Computes the finger information. /// /// Avatar whose finger information to compute /// Hand renderer /// Which hand side the finger belongs to /// Which finger to compute internal void Compute(UxrAvatar avatar, SkinnedMeshRenderer handRenderer, UxrHandSide side, UxrFingerType finger) { _avatar = avatar; _side = side; _finger = finger; UxrUniversalLocalAxes fingerAxes = avatar.AvatarRigInfo.GetArmInfo(side).FingerUniversalLocalAxes; UxrAvatarFinger avatarFinger = avatar.GetHand(side).GetFinger(finger); _metacarpalInfo = new UxrAvatarFingerBoneInfo(); _proximalInfo = new UxrAvatarFingerBoneInfo(); _intermediateInfo = new UxrAvatarFingerBoneInfo(); _distalInfo = new UxrAvatarFingerBoneInfo(); _metacarpalInfo.Compute(handRenderer, avatarFinger.Metacarpal, avatarFinger.Proximal, fingerAxes); _proximalInfo.Compute(handRenderer, avatarFinger.Proximal, avatarFinger.Intermediate, fingerAxes); _intermediateInfo.Compute(handRenderer, avatarFinger.Intermediate, avatarFinger.Distal, fingerAxes); _distalInfo.Compute(handRenderer, avatarFinger.Distal, null, fingerAxes); _distalLocalTip = fingerAxes.LocalForward * _distalInfo.Length; _distalLocalFingerPrintCenter = fingerAxes.LocalForward * (_distalInfo.Length * 0.66f) - fingerAxes.LocalUp * (_distalInfo.Radius * 0.66f); } #endregion } }