using Rokid.UXR.Utility; using UnityEngine; using UnityEngine.UI; using Rokid.UXR.Native; namespace Rokid.UXR.Interaction { /// /// Processing the pose information of the ray /// public class HandRayPose : BaseRayPose { [Tooltip("手的类型")] [SerializeField] public HandType hand; [Tooltip("肩膀位置,基于脖子空间左右对称")] [SerializeField] private Vector3 shoulder = new Vector3(-0.2f, -0.1f, 0); [Tooltip("脖子位置估算,基于相机空间计算")] [SerializeField] private Vector3 neck = new Vector3(0, -0.1f, -0.1f); [Tooltip("手掌方向对射线方向影响的强度")] [SerializeField] private float palmForwardInfluencePow = 0.7f; [SerializeField] private RayInteractor rayInteractor; [SerializeField] private RayVisual rayVisual; [SerializeField] private Text logText; [SerializeField, Tooltip("是否打印日志")] private bool log = false; private float upForwardInfluencePow = 0.06f; private Vector3 shoulderPos; private Vector3 delta = Vector3.zero; private bool rayFirstShow = true; private InteractorType interactorType = InteractorType.Far; /// /// 颈部位置的tsf /// private Transform neckTsf; private Vector3 preWirstPos = Vector3.zero; private Vector3 wristPos = Vector3.zero; private float preCamRotY = 0; protected override void Start() { base.Start(); neckTsf = new GameObject("neck").transform; neckTsf.SetParent(transform); GesEventInput.OnRayPoseUpdate += OnRayPoseUpdate; InteractorStateChange.OnInteractorTypeChange += OnInteractorTypeChange; upForwardInfluencePow = NativeInterface.NativeAPI.GetUpForwardInfluencePow(); } private void OnInteractorTypeChange(HandType hand, InteractorType interactorType) { if (this.hand == hand) { rayFirstShow = true; this.interactorType = interactorType; } } private void OnEnable() { rayFirstShow = true; } private void OnDestroy() { GesEventInput.OnRayPoseUpdate -= OnRayPoseUpdate; InteractorStateChange.OnInteractorTypeChange -= OnInteractorTypeChange; } private void OnRayPoseUpdate(HandType hand, Vector3 wrist, Vector3 handCenter, Vector3 pinchCenterOri, Vector3 pinchCenter) { if (Utils.IsUnityEditor()) return; if (this.hand == hand) { float deltaWrist = Vector3.SqrMagnitude(wrist - preWirstPos); neckTsf.position = MainCameraCache.mainCamera.transform.TransformPoint(neck); neckTsf.rotation = Quaternion.Euler(0, deltaWrist > 0.1f ? MainCameraCache.mainCamera.transform.eulerAngles.y : preCamRotY, 0); shoulderPos = neckTsf.TransformPoint(shoulder); preWirstPos = wrist; preCamRotY = MainCameraCache.mainCamera.transform.eulerAngles.y; //手势关键信息的更新 delta = rayFirstShow ? pinchCenter - pinchCenterOri : Vector3.Lerp(delta, pinchCenter - pinchCenterOri, Time.deltaTime * 3); rayFirstShow = false; //胳膊朝向 Vector3 armForward = (wrist - shoulderPos).normalized; //手腕朝向 Vector3 palmForWard = (handCenter - wrist).normalized; this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.FromToRotation(Vector3.forward, armForward + palmForWard * palmForwardInfluencePow + Vector3.up * upForwardInfluencePow), Time.deltaTime * 10); if (float.IsNaN(this.transform.position.x) || float.IsNaN(this.transform.position.y) || float.IsNaN(this.transform.position.z) || float.IsNaN(this.transform.rotation.x) || float.IsNaN(this.transform.rotation.y) || float.IsNaN(this.transform.rotation.z) || float.IsNaN(this.transform.rotation.w)) { RKLog.Error($"====HandRayPose==== Data Error {MainCameraCache.mainCamera.transform.position}cameraRot:{MainCameraCache.mainCamera.transform.rotation.eulerAngles},{wrist},{handCenter},{pinchCenterOri},{pinchCenter}"); transform.position = Vector3.zero; transform.rotation = Quaternion.identity; neckTsf.position = Vector3.zero; neckTsf.rotation = Quaternion.identity; } this.transform.position = Vector3.Lerp(this.transform.position, pinchCenterOri + delta, Time.deltaTime * 20); LogHandRayInfo(wrist, handCenter); } } #region LogHandRayInfo private float logTime = 5; private float logElapsedTime = 0; private void LogHandRayInfo(Vector3 wrist, Vector3 handCenter) { logElapsedTime += Time.deltaTime; if (logElapsedTime > logTime) { logElapsedTime = 0; string logInfo = $"====HandRayPose====\n camPos:{MainCameraCache.mainCamera.transform.position},\n camRot:{MainCameraCache.mainCamera.transform.rotation.eulerAngles}\n neckPos: {neckTsf.position}\n shoulderPos: {shoulderPos}\n wristPos:{wrist}\n wristPosInCamera:{MainCameraCache.mainCamera.transform.InverseTransformPoint(wrist)}\n handPos:{handCenter} \n rayPos:{this.transform.position} \n rayPos:{this.transform.rotation.eulerAngles} \n rayRot:{this.transform.rotation.eulerAngles} "; if (logText != null) logText.text = logInfo; RKLog.KeyInfo(logInfo); } } #endregion } }