using System; using Rokid.UXR.Utility; using UnityEngine; using UnityEngine.EventSystems; namespace Rokid.UXR.Interaction { /// /// Processing the pose information of the ray /// public class HeadHandRayPose : BaseRayPose, IHeadHandDriver { private RayInteractor rayInteractor; [SerializeField] private HandType handType; [SerializeField, Tooltip("Shoulder position, symmetrically based on neck space")] private Vector3 shoulder = new Vector3(-0.2f, -0.1f, 0); [SerializeField, Tooltip("Neck position estimation, calculated based on camera space.")] private Vector3 neck = new Vector3(0, -0.1f, -0.1f); [SerializeField, Tooltip("The strength of the influence of palm direction on the ray direction.")] private float palmForwardInfluencePow = 0f; [SerializeField, Tooltip("The intensity of ray upward bending.")] private float upForwardInfluencePow = 0.0f; 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 float preCamRotY = 0; private Transform rayOrigin; private Vector3 startRayPos; private Vector3 startRayForward; private Vector3 preRayPos; private Vector3 preRayForward; private Vector3 deltaRayPos; private Vector3 deltaRayForward; private Vector3 allDeltaRayPos; private Vector3 allDeltaRayForward; private int handFrame = 0; private int headFrame = 0; private float noHoverCursorDistance; protected override void Start() { base.Start(); if (rayInteractor == null) { rayInteractor = GetComponent(); } GesEventInput.OnRayPoseUpdate += OnRayPoseUpdate; neckTsf = new GameObject("neck").transform; neckTsf.SetParent(transform); rayOrigin = rayInteractor.GetRayOriginTsf(); noHoverCursorDistance = rayInteractor.NoHoverCursorDistance; } private void OnDestroy() { GesEventInput.OnRayPoseUpdate -= OnRayPoseUpdate; } public void OnChangeHoldHandType(HandType hand) { if (hand != HandType.None) { handType = hand; shoulder = handType == HandType.RightHand ? new Vector3(0.2f, -0.1f, 0) : new Vector3(-0.2f, 0.1f, 0); startRayPos = rayOrigin.position; startRayForward = rayOrigin.forward; } } public void OnHandPress(HandType hand) { if (handFrame > 10) { allDeltaRayPos += deltaRayPos; allDeltaRayForward += deltaRayForward; rayOrigin.rotation = Quaternion.Slerp(rayOrigin.rotation, Quaternion.FromToRotation(Vector3.forward, startRayForward + allDeltaRayForward), Time.deltaTime * 10); rayOrigin.position = Vector3.Lerp(rayOrigin.position, startRayPos + allDeltaRayPos, Time.deltaTime * 30); } } public void OnHandRelease() { headFrame++; if (Utils.IsAndroidPlatfrom() && headFrame > 1) { rayOrigin.SetPositionAndRotation(MainCameraCache.mainCamera.transform.position + new Vector3(0, 0.05f, 0), Quaternion.FromToRotation(Vector3.forward, MainCameraCache.mainCamera.transform.forward + new Vector3(0, 0.05f, 0))); } } private void OnRayPoseUpdate(HandType hand, Vector3 wrist, Vector3 handCenter, Vector3 pinchCenterOri, Vector3 pinchCenter) { if (Utils.IsUnityEditor()) return; if (hand == handType) { float deltaWrist = Vector3.SqrMagnitude(wrist - preWirstPos); float deltaCamPos = Vector3.SqrMagnitude(MainCameraCache.mainCamera.transform.position - 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; //胳膊朝向 Vector3 armForward = (wrist - shoulderPos).normalized; //手腕朝向 Vector3 palmForWard = (handCenter - wrist).normalized; Vector3 curForward = armForward + palmForWard * palmForwardInfluencePow + Vector3.up * upForwardInfluencePow; Vector3 curPos = pinchCenterOri; deltaRayForward = curForward - preRayForward; deltaRayPos = curPos - preRayPos; preRayForward = curForward; preRayPos = curPos; handFrame++; } } public void OnBeforeChangeHoldHandType(HandType hand) { if (hand == HandType.None) { rayInteractor.NoHoverCursorDistance = noHoverCursorDistance; handType = HandType.None; allDeltaRayForward = Vector3.zero; allDeltaRayPos = Vector3.zero; handFrame = 0; headFrame = 0; } } } }