HandDevicePartManipulation.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. using SC.XR.Unity.Module_InputSystem;
  2. using SC.XR.Unity.Module_InputSystem.InputDeviceHand;
  3. using System;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using UnityEngine;
  8. public class HandDevicePartManipulation : AbstractDevicePartManipulation
  9. {
  10. //for one hand
  11. private Quaternion startRotation;
  12. private Quaternion localRotationInHand;
  13. private SCPose oneHandPose = new SCPose(Vector3.zero, Quaternion.identity);
  14. private Vector3 oneHandGrabPosition;
  15. private Transform oneHandJointFour;
  16. private HandDetector handDetector;
  17. private SCPointEventData onHandPointEventData;
  18. public override void OneDevicePartInit(ManipulationHandler manipulationHandler, Dictionary<InputDevicePartType, SCPointEventData> eventDataDic, Transform targetTransform, MoveLogic moveLogic, RotateLogic rotateLogic, ScaleLogic scaleLogic)
  19. {
  20. base.OneDevicePartInit(manipulationHandler, eventDataDic, targetTransform, moveLogic, rotateLogic, scaleLogic);
  21. startRotation = targetTransform.rotation;
  22. onHandPointEventData = eventDataDic.Values.ToArray()[0];
  23. InputDeviceHandPart inputDeviceHandPart = onHandPointEventData.inputDevicePartBase as InputDeviceHandPart;
  24. ModelHand modelHand = inputDeviceHandPart.inputDeviceHandPartUI.modelHand;
  25. oneHandJointFour = modelHand.ActiveHandModel.GetJointTransform(FINGER.forefinger, JOINT.Four).transform;
  26. localRotationInHand = Quaternion.Inverse(oneHandJointFour.rotation) * startRotation;
  27. handDetector = inputDeviceHandPart.detectorBase as HandDetector;
  28. oneHandPose.position = onHandPointEventData.Position3D;
  29. oneHandPose.rotation = startRotation;
  30. oneHandGrabPosition = onHandPointEventData.Position3D;
  31. moveLogic.Setup(oneHandPose, oneHandGrabPosition, targetTransform, targetTransform.localScale);
  32. }
  33. public override Tuple<Vector3, Quaternion, Vector3> OneDevicePartUpdate()
  34. {
  35. Quaternion rotation = targetTransform.rotation;
  36. if (handDetector.currentPointer is INearPointer && manipulationHandler.canOneHandRotate)
  37. {
  38. rotation = oneHandJointFour.rotation * localRotationInHand;
  39. }
  40. oneHandPose.position = onHandPointEventData.Position3D;
  41. oneHandPose.rotation = startRotation;
  42. Vector3 position = moveLogic.Update(oneHandPose, rotation, targetTransform.localScale, true);
  43. return new Tuple<Vector3, Quaternion, Vector3>(position, rotation, targetTransform.localScale);
  44. }
  45. ///for two hand
  46. private Dictionary<InputDevicePartType, Transform> handTipTransformDic;
  47. private Dictionary<InputDevicePartType, Vector3> position3DDic;
  48. private SCPose[] position3DPoses = new SCPose[2];
  49. private Transform[] handTipTransformArray;
  50. public override void TwoDevicePartInit(ManipulationHandler manipulationHandler, Dictionary<InputDevicePartType, SCPointEventData> eventDataDic, Transform targetTransform, MoveLogic moveLogic, RotateLogic rotateLogic, ScaleLogic scaleLogic)
  51. {
  52. base.TwoDevicePartInit(manipulationHandler, eventDataDic, targetTransform, moveLogic, rotateLogic, scaleLogic);
  53. if (handTipTransformDic == null)
  54. {
  55. handTipTransformDic = new Dictionary<InputDevicePartType, Transform>();
  56. }
  57. handTipTransformDic.Clear();
  58. if (position3DDic == null)
  59. {
  60. position3DDic = new Dictionary<InputDevicePartType, Vector3>();
  61. }
  62. position3DDic.Clear();
  63. foreach (var eventData in eventDataDic)
  64. {
  65. InputDeviceHandPart inputDeviceHandPart = eventData.Value.inputDevicePartBase as InputDeviceHandPart;
  66. ModelHand modelHand = inputDeviceHandPart.inputDeviceHandPartUI.modelHand;
  67. Transform tipTransform = modelHand.ActiveHandModel.GetJointTransform(FINGER.forefinger, JOINT.One).transform;
  68. handTipTransformDic.Add(eventData.Key, tipTransform);
  69. position3DDic.Add(eventData.Key, eventData.Value.Position3D);
  70. }
  71. handTipTransformArray = handTipTransformDic.Values.ToArray();
  72. if (manipulationHandler.canTwoHandScale)
  73. {
  74. scaleLogic.Setup(handTipTransformArray, targetTransform);
  75. }
  76. if (manipulationHandler.canTwoHandRotate)
  77. {
  78. rotateLogic.Setup(handTipTransformArray, targetTransform);
  79. }
  80. int count = 0;
  81. foreach (SCPointEventData eventDataItem in eventDataDic.Values)
  82. {
  83. position3DPoses[count] = new SCPose(eventDataItem.Position3D, handTipTransformArray[count].rotation);
  84. count++;
  85. }
  86. SCPose pointerCentroidPose = GetHandTipPointCentroid(position3DPoses);
  87. Vector3 grabCentroid = GetRaycastPointCentroid(position3DDic.Values.ToArray());
  88. moveLogic.Setup(pointerCentroidPose, grabCentroid, targetTransform, targetTransform.localScale);
  89. }
  90. public override Tuple<Vector3, Quaternion, Vector3> TwoDevicePartUpdate(Func<Vector3, Vector3> scaleConstraint)
  91. {
  92. Vector3 scale = targetTransform.localScale;
  93. if (manipulationHandler.canTwoHandScale)
  94. {
  95. scale = scaleLogic.UpdateMap(handTipTransformArray);
  96. }
  97. scale = scaleConstraint(scale);
  98. Quaternion rotation = targetTransform.rotation;
  99. if (manipulationHandler.canTwoHandRotate)
  100. {
  101. rotation = rotateLogic.Update(handTipTransformArray, rotation);
  102. }
  103. int count = 0;
  104. foreach (SCPointEventData eventDataItem in eventDataDic.Values)
  105. {
  106. position3DPoses[count].position = eventDataItem.Position3D;
  107. position3DPoses[count].rotation = handTipTransformArray[count].rotation;
  108. count++;
  109. }
  110. SCPose pointerCentroidPose = GetHandTipPointCentroid(position3DPoses);
  111. Vector3 position = moveLogic.Update(pointerCentroidPose, rotation, scale, true);
  112. return new Tuple<Vector3, Quaternion, Vector3>(position, rotation, scale);
  113. }
  114. private SCPose GetHandTipPointCentroid(SCPose[] tipPoints)
  115. {
  116. Vector3 sumPos = Vector3.zero;
  117. Vector3 sumDir = Vector3.zero;
  118. int count = tipPoints.Length;
  119. for (int i = 0; i < count; i++)
  120. {
  121. sumPos += tipPoints[i].position;
  122. sumDir += tipPoints[i].rotation * Vector3.forward;
  123. }
  124. Vector3 resultPos = sumPos / Math.Max(1, count);
  125. Quaternion resultRot = Quaternion.LookRotation(sumDir / Math.Max(1, count));
  126. return new SCPose(resultPos, resultRot);
  127. }
  128. private Vector3 GetRaycastPointCentroid(Vector3[] raycastPoints)
  129. {
  130. Vector3 sum = Vector3.zero;
  131. int count = raycastPoints.Length;
  132. for (int i = 0; i < count; i++)
  133. {
  134. sum += raycastPoints[i];
  135. }
  136. return sum / Math.Max(1, count);
  137. }
  138. }