private void adjustFingerRootPos(GestureResult hand) { for (int i = 0; i < 5; i++) { if (IsRobotHand) { if (i != 0) { continue; } } else { if (i == 1 || i == 2) { continue; } } int startIndex = i * 4 + 1; Vector3 vec1 = hand.points[startIndex] - hand.points[0]; Vector3 vec2 = Nodes[startIndex].position - Nodes[0].position; if (Vector3.Cross(wristXDir, vec1).magnitude > epsilon) { Vector3 vec3; float angle; calculateModelPos(wristXDir, vec1, MwristXDir, vec2, out angle, out vec3); Nodes[startIndex].position = Nodes[0].position + vec3.normalized * (Nodes[startIndex].position - Nodes[0].position).magnitude; } } }
void setRotation(Vector3 vec0, Vector3 vec1, float angle0, Vector3 vec9, int joint, GestureResult hand) { Vector3 vecM0 = Vector3.zero; Vector3 vecM1 = Vector3.zero; if (joint == 1 || joint == 5 || joint == 9 || joint == 13 || joint == 17) { vecM0 = Nodes[joint].position - Nodes[0].position; } else { vecM0 = Nodes[joint].position - Nodes[joint - 1].position; } vecM1 = Nodes[joint + 1].position - Nodes[joint].position; calculateModelPos(vec0, vec1, vecM0, vecM1, out angle0, out vec9); if (joint / 4 > 0) { float TempAngle1 = Vector3.Angle(vec9, Nodes[joint - 3].position - Nodes[joint - 4].position); float TempAngle2 = Vector3.Angle(vec1, hand.points[joint - 3] - hand.points[joint - 4]); if (Mathf.Abs(TempAngle1 - TempAngle2) > 0.5f) { vec9 = Quaternion.AngleAxis(-Mathf.Abs(TempAngle1 - TempAngle2), Vector3.Cross(vec9, Nodes[joint - 3].position - Nodes[joint - 4].position)) * vec9; angle0 = SignedAngle(vecM1, vec9); } } Nodes[joint].rotation = Quaternion.AngleAxis(angle0, Vector3.Cross(vecM1, vec9)) * Nodes[joint].rotation; }
public void ClearState() { Status = GestureStatus.NotStarted; UpdatedInThisFrame = false; Error = GestureFailure.None; LeftHand = RightHand = null; }
void Update() { if (Status == GestureStatus.NotStarted || Status == GestureStatus.Error) { return; } UpdatedInThisFrame = false; IntPtr ptr; int index; var size = GestureInterface.GetGestureResult(out ptr, out index); if (index < 0) { #if VIVEHANDTRACKING_WITH_WAVEVR WaveVR_Log.Log.e("Aristo", "Gesture detection stopped"); #else Debug.LogError("Gesture detection stopped"); #endif Status = GestureStatus.Error; Error = GestureFailure.Internal; return; } else if (Status == GestureStatus.Starting && index > 0) { Status = GestureStatus.Running; } if (index <= lastIndex) { return; } lastIndex = index; UpdatedInThisFrame = true; LeftHand = RightHand = null; if (size <= 0) { return; } var structSize = Marshal.SizeOf(typeof(GestureResultRaw)); for (var i = 0; i < size; i++) { var gesture = (GestureResultRaw)Marshal.PtrToStructure(ptr, typeof(GestureResultRaw)); ptr = new IntPtr(ptr.ToInt64() + structSize); for (int j = 0; j < 21; j++) { gesture.points[j] = transform.TransformPoint(gesture.points[j]); } if (gesture.isLeft) { LeftHand = new GestureResult(gesture); } else { RightHand = new GestureResult(gesture); } } }
HandFlag GetFlag(GestureResult hand) { var flag = HandFlag.NoHand; if (hand != null) { flag = (HandFlag)(2 << (int)hand.gesture); } return(flag); }
void setAxis(GestureResult hand) { wristXDir = (-Vector3.Cross(hand.points[5] - hand.points[0], hand.points[13] - hand.points[0])).normalized; wristYDir = (Vector3.Cross(wristXDir, (hand.points[13] + hand.points[5]) / 2 - hand.points[0])).normalized; wristZDir = ((hand.points[13] + hand.points[5]) / 2 - hand.points[0]).normalized; MwristXDir = (-Vector3.Cross(Nodes[5].position - Nodes[0].position, Nodes[13].position - Nodes[0].position)).normalized; MwristYDir = (Vector3.Cross(MwristXDir, (Nodes[13].position + Nodes[5].position) / 2 - Nodes[0].position)).normalized; MwristZDir = ((Nodes[13].position + Nodes[5].position) / 2 - Nodes[0].position).normalized; }
HandFlag GetFlag(GestureResult hand) { var flag = HandFlag.NoHand; if (hand != null) { flag = (HandFlag)(2 << (int)hand.gesture); if (hand.pinch.isPinching) { flag |= HandFlag.Pinch; } } return(flag); }
void Update() { transform.position = Vector3.Lerp(transform.position, m_NewPos, Smoothness); transform.rotation = Quaternion.Slerp(transform.rotation, m_NewRot, Smoothness); if (!GestureProvider.UpdatedInThisFrame) { return; } GestureResult result = IsLeft ? GestureProvider.LeftHand : GestureProvider.RightHand; if (result == null) { Hand.SetActive(false); return; } Hand.SetActive(true); Vector3 _Wrist = result.points[0]; Vector3 _Index = result.points[5]; Vector3 _Middle = result.points[9]; Vector3 _ring = result.points[13]; Vector3 _zd = (result.points[5] + result.points[13]) / 2; m_NewPos = _Wrist; Vector3 _MidDir = _Middle - _Wrist; Vector3 _ringDir = _ring - _Wrist; Vector3 _IndexDir = _Index - _Wrist; Vector3 _zdDir = -_zd - _Wrist; Vector3 _PalmDir = Vector3.Cross(_IndexDir, _ringDir); Vector3 _UpDir = Vector3.Cross(_ringDir, _PalmDir); _MidDir = Quaternion.AngleAxis(7, _PalmDir) * _MidDir; m_NewRot = Quaternion.LookRotation(_MidDir, _UpDir); if ((result.points[13] - result.points[5]).magnitude == 0) { return; } for (int i = 0; i < 5; ++i) { SetFingerAngle(result, i); } }
private void setFingerPos(GestureResult hand) { for (int i = 0; i < 5; i++) { int startIndex = i * 4 + 1; float IdealLength = (hand.points[startIndex] - hand.points[0]).magnitude; Nodes[startIndex].position = Nodes[0].position + (Nodes[startIndex].position - Nodes[0].position).normalized * IdealLength; IdealLength = (hand.points[startIndex + 1] - hand.points[startIndex]).magnitude; Nodes[startIndex + 1].position = Nodes[startIndex].position + (Nodes[startIndex + 1].position - Nodes[startIndex].position).normalized * IdealLength; IdealLength = (hand.points[startIndex + 2] - hand.points[startIndex + 1]).magnitude; Nodes[startIndex + 2].position = Nodes[startIndex + 1].position + (Nodes[startIndex + 2].position - Nodes[startIndex + 1].position).normalized * IdealLength; IdealLength = (hand.points[startIndex + 3] - hand.points[startIndex + 2]).magnitude; Nodes[startIndex + 3].position = Nodes[startIndex + 2].position + (Nodes[startIndex + 3].position - Nodes[startIndex + 2].position).normalized * IdealLength; } }
/// fingerIndex is ranged from 0 to 4, i.e. from thumb to pinky private void SetFingerAngle(GestureResult hand, int fingerIndex) { int startIndex = fingerIndex * 4 + 1; if (fingerIndex == 0) { float toPinkyLength = (hand.points[startIndex + 2] - hand.points[17]).magnitude; float toRingLength = (hand.points[startIndex + 2] - hand.points[13]).magnitude; float toMiddleLength = (hand.points[startIndex + 2] - hand.points[9]).magnitude; float toIndexLength = (hand.points[startIndex + 2] - hand.points[5]).magnitude; if (toPinkyLength < 0.028f || toRingLength < 0.028f || toMiddleLength < 0.028f || toIndexLength < 0.028f) { return; } } Vector3 root = hand.points[startIndex]; Vector3 joint1 = hand.points[startIndex + 1]; Vector3 joint2 = hand.points[startIndex + 2]; Vector3 top = hand.points[startIndex + 3]; Vector3 vec0 = root - hand.points[0]; Vector3 vec1 = joint1 - root; Vector3 vec2 = joint2 - joint1; Vector3 vec3 = top - joint2; Nodes[startIndex].localRotation = initialRootJointQuatertion[fingerIndex]; Nodes[startIndex + 1].localRotation = initialSecondJoinQuatertion[fingerIndex]; Nodes[startIndex + 2].localRotation = initialThirdJointQuatertion[fingerIndex]; setRotation(vec0, vec1, 0.0f, Vector3.zero, startIndex, hand); setRotation(vec1, vec2, 0.0f, Vector3.zero, startIndex + 1, hand); float angle = Mathf.Clamp(Vector3.Angle(vec2, vec3), 0, 180); Nodes[startIndex + 2].localEulerAngles = new Vector3(initialThirdJointQuatertion[fingerIndex].eulerAngles.x, initialThirdJointQuatertion[fingerIndex].eulerAngles.y, -angle); ConfirmIsCoplanar(fingerIndex); }
/// fingerIndex is ranged from 0 to 4, i.e. from thumb to pinky private void SetFingerAngle(GestureResult hand, int fingerIndex) { int startIndex = fingerIndex * 4 + 1; Vector3 root = hand.points[startIndex]; Vector3 joint1 = hand.points[startIndex + 1]; Vector3 joint2 = hand.points[startIndex + 2]; Vector3 top = hand.points[startIndex + 3]; Vector3 vec0 = root - hand.points[0]; Vector3 vec1 = joint1 - root; Vector3 vec2 = joint2 - joint1; Vector3 vec3 = top - joint2; Nodes[startIndex].localRotation = initialRootJointQuatertion[fingerIndex]; Nodes[startIndex + 1].localRotation = initialSecondJoinQuatertion[fingerIndex]; Nodes[startIndex + 2].localRotation = initialThirdJointQuatertion[fingerIndex]; setRotation(vec0, vec1, startIndex); setRotation(vec1, vec2, startIndex + 1); float angle = Mathf.Clamp(Vector3.Angle(vec2, vec3), 0, 180); if (fingerIndex == 0) { Nodes[startIndex + 2].localEulerAngles = new Vector3(initialThirdJointQuatertion[fingerIndex].eulerAngles.x, initialThirdJointQuatertion[fingerIndex].eulerAngles.y, -angle); } else if (fingerIndex > 2 && !IsLeft) { Nodes[startIndex + 1].localEulerAngles = new Vector3(initialSecondJoinQuatertion[fingerIndex].eulerAngles.x, initialSecondJoinQuatertion[fingerIndex].eulerAngles.y, Nodes[startIndex + 1].localEulerAngles.z); Nodes[startIndex + 2].localEulerAngles = new Vector3(initialThirdJointQuatertion[fingerIndex].eulerAngles.x, initialThirdJointQuatertion[fingerIndex].eulerAngles.y, -angle); } else { setRotation(vec2, vec3, startIndex + 2); } }
void Update() { if (!GestureProvider.UpdatedInThisFrame) { return; } GestureResult result = IsLeft ? GestureProvider.LeftHand : GestureProvider.RightHand; if (result == null) { Hand.SetActive(false); return; } Hand.SetActive(true); transform.position = result.points[0]; transform.rotation = result.rotation * Quaternion.Euler(initialRotation); Vector3 indexDir = result.points[5] - result.points[0]; Vector3 midDir = result.points[9] - result.points[0]; Vector3 palmDir = IsLeft ? Vector3.Cross(indexDir, midDir) : Vector3.Cross(midDir, indexDir); Vector3 thumbAxis = result.points[17] - result.points[1]; int nodeIndex = 1; int vecIndex = 0; for (int i = 0; i < 5; ++i, nodeIndex += 4, vecIndex += 3) { Vector3 root = result.points[nodeIndex]; Vector3 joint1 = result.points[nodeIndex + 1]; Vector3 vec1 = (joint1 - root).normalized * modelFingerVec[vecIndex].magnitude; Vector3 joint2 = result.points[nodeIndex + 2]; Vector3 vec2 = (joint2 - joint1).normalized * modelFingerVec[vecIndex + 1].magnitude; Vector3 top = result.points[nodeIndex + 3]; Vector3 vec3 = (top - joint2).normalized * modelFingerVec[vecIndex + 2].magnitude; Vector3 fingerNormal; if (i == 0) { fingerNormal = CalculateFingerNormal(vec1, vec2, thumbAxis, IsLeft ? palmDir : -palmDir); } else { fingerNormal = CalculateFingerNormal(vec1, vec2, palmDir, Vector3.Cross(indexDir, palmDir)); } SetNodeRotation(nodeIndex, modelFingerVec[vecIndex], vec1, fingerNormal); SetNodeRotation(nodeIndex + 1, modelFingerVec[vecIndex + 1], vec2, fingerNormal); SetNodeRotation(nodeIndex + 2, modelFingerVec[vecIndex + 2], vec3, fingerNormal); } if (showConficenceAsAlpha) { var color = Hand.GetComponent <Renderer>().material.color; color.a = result.confidence > minAlpha ? result.confidence : minAlpha; Hand.GetComponent <Renderer>().material.color = color; } if (colliderType == HandColliderType.Trigger) { UpdateTigger(); } else if (colliderType == HandColliderType.Collider) { UpdateCollider(); } }
void Update() { if (Input.GetKeyDown(KeyCode.N)) { currentInstruction++; isPlaying = false; Play = true; logger.AddKeyLogs("Next"); if (this.IsLeft) { next.Play(); } } else if (Input.GetKeyDown(KeyCode.P)) { currentInstruction--; isPlaying = false; Play = true; logger.AddKeyLogs("Previous"); if (this.IsLeft) { previous.Play(); } } else if (Input.GetKeyDown(KeyCode.R)) { isPlaying = false; Play = true; logger.AddKeyLogs("Repeat"); } if (_currentRecording != null) { GestureResult frame = IsLeft ? GestureProvider.LeftHand : GestureProvider.RightHand; if (frame != null) { _currentRecording.Handframes.Add(new HandFrame(frame.isLeft, frame.points, frame.gesture, frame.position, frame.rotation)); _currentRecording.frameTimes.Add(Time.time - _beginTime); } if (Input.GetKeyDown(_endRecording)) { EndRecording(); } } else { if (Input.GetKeyDown(_startRecording)) { StartRecording(); } } if (!GestureProvider.UpdatedInThisFrame && !Play) { return; } GestureResult result = null; if (Play) { if (!isPlaying) { _playBackBeginTime = Time.time; playbackFrame = 0; isPlaying = true; //playbackFrame = GetSeekFrame(); } if (playbackFrame >= HandRecordings[currentInstruction].frameTimes.Count) { isPlaying = false; Play = false; if (this.IsLeft) { completed.Play(); } return; } if (isPlaying && (Time.time - _playBackBeginTime) < HandRecordings[currentInstruction].frameTimes[playbackFrame]) { return; } else { result = HandRecordings[currentInstruction].GRFrames[playbackFrame]; playbackFrame++; } /* if (HandRecordings[currentInstruction].frameTimes[playbackFrame] >= HandRecordings[currentInstruction].finishAtSeconds)//Limit playback to certain seconds * { * Hand.SetActive(false); * return; * }*/ } else { result = IsLeft ? GestureProvider.LeftHand : GestureProvider.RightHand; } if (result == null) { Hand.SetActive(false); return; } if (DisableLiveHands && !Play) { return; } Hand.SetActive(true); for (int i = 0; i < 5; i++) { int startIndex = i * 4 + 1; float squareLengthRoot = (result.points[startIndex] - result.points[0]).sqrMagnitude; float squareLengthFirst = (result.points[startIndex + 1] - result.points[startIndex]).sqrMagnitude; float squareLengthSecond = (result.points[startIndex + 2] - result.points[startIndex + 1]).sqrMagnitude; float squareLengthThird = (result.points[startIndex + 3] - result.points[startIndex + 2]).sqrMagnitude; if (squareLengthRoot < epsilon || squareLengthFirst < epsilon || squareLengthSecond < epsilon || squareLengthThird < epsilon) { return; } for (int j = i + 1; j < 5; j++) { int nextStartIndex = j * 4 + 1; if ((result.points[nextStartIndex] - result.points[startIndex]).sqrMagnitude == 0) { return; } } } Vector3 _Wrist = result.points[0]; Vector3 _Index = result.points[5]; Vector3 _Middle = result.points[9]; Vector3 _ring = result.points[13]; transform.position = _Wrist; Vector3 _MidDir = _Middle - _Wrist; Vector3 _ringDir = _ring - _Wrist; Vector3 _IndexDir = _Index - _Wrist; Vector3 _PalmDir = Vector3.Cross(_IndexDir, _ringDir); Vector3 _UpDir = Vector3.Cross(_ringDir, _PalmDir); _MidDir = Quaternion.AngleAxis(4.7f, _PalmDir) * _MidDir; transform.rotation = Quaternion.LookRotation(_MidDir, _UpDir); setFingerPos(result); setAxis(result); adjustFingerRootPos(result); for (int i = 0; i < 5; ++i) { SetFingerAngle(result, i); } for (int i = 0; i < 5; i++) { int startIndex = i * 4 + 1; Nodes[startIndex].position = Nodes[0].position + (Nodes[startIndex].position - Nodes[0].position).normalized * idealFingerLength[i * 3]; Nodes[startIndex + 1].position = Nodes[startIndex].position + (Nodes[startIndex + 1].position - Nodes[startIndex].position).normalized * idealFingerLength[i * 3 + 1]; Nodes[startIndex + 2].position = Nodes[startIndex + 1].position + (Nodes[startIndex + 2].position - Nodes[startIndex + 1].position).normalized * idealFingerLength[i * 3 + 2]; } }
/// fingerIndex is ranged from 0 to 4, i.e. from thumb to pinky private void SetFingerAngle(GestureResult hand, int fingerIndex) { int startIndex = fingerIndex * 4 + 1; Vector3 root = hand.points[startIndex]; Vector3 joint1 = hand.points[startIndex + 1]; Vector3 joint2 = hand.points[startIndex + 2]; Vector3 top = hand.points[startIndex + 3]; Vector3 vec0 = root - hand.points[0]; Vector3 vec1 = joint1 - root; Vector3 vec2 = joint2 - joint1; Vector3 vec3 = top - joint2; if (vec0.magnitude == 0 || vec1.magnitude == 0 || vec2.magnitude == 0 || vec3.magnitude == 0) { return; } Nodes[startIndex].localRotation = q1[fingerIndex]; Nodes[startIndex + 1].localRotation = q2[fingerIndex]; Nodes[startIndex + 2].localRotation = q3[fingerIndex]; if ((hand.points[9] - hand.points[0]).magnitude == 0) { return; } float k = (Nodes[9].position - Nodes[0].position).magnitude / (hand.points[9] - hand.points[0]).magnitude; float IdealLength = k * (hand.points[startIndex] - hand.points[0]).magnitude; Nodes[startIndex].position = Nodes[0].position + (Nodes[startIndex].position - Nodes[0].position).normalized * IdealLength; Vector3 vec5 = Nodes[startIndex].position - Nodes[0].position; Vector3 vec9 = Vector3.zero; setAxis(hand); float angle0 = 0.0f; if (fingerIndex == 0 || fingerIndex == 2 || fingerIndex == 4) { if (Vector3.Cross(wristXDir, vec0).magnitude != 0.0f) { calculateModelPos(wristXDir, vec0, MwristXDir, vec5, out angle0, out vec9); Nodes[startIndex].position = Nodes[0].position + vec9.normalized * (Nodes[startIndex].position - Nodes[0].position).magnitude; } } if (Vector3.Cross(vec0, vec1).magnitude != 0) { setRotation(vec0, vec1, angle0, vec9, startIndex, hand); if (fingerIndex != 0) { Nodes[startIndex].localEulerAngles = new Vector3(0, Nodes[startIndex].localEulerAngles.y, Nodes[startIndex].localEulerAngles.z); } } else { Nodes[startIndex].localRotation = q1[fingerIndex]; } if (Vector3.Cross(vec1, vec2).magnitude != 0) { setRotation(vec1, vec2, angle0, vec9, startIndex + 1, hand); Nodes[startIndex + 1].localEulerAngles = new Vector3(0, Nodes[startIndex + 1].localEulerAngles.y, Nodes[startIndex + 1].localEulerAngles.z); } else { Nodes[startIndex + 1].localRotation = q2[fingerIndex]; } if (Vector3.Cross(vec2, vec3).magnitude != 0) { setRotation(vec2, vec3, angle0, vec9, startIndex + 2, hand); Nodes[startIndex + 2].localEulerAngles = new Vector3(0, Nodes[startIndex + 2].localEulerAngles.y, Nodes[startIndex + 2].localEulerAngles.z); } else { Nodes[startIndex + 2].localRotation = q3[fingerIndex]; } }
IEnumerator PlaybackFunction() { float lastFrameTime = 0f; for (int x = 0; x < HandRecordings[currentInstruction].frameTimes.Count; x++) { GestureResult result = null; yield return(new WaitForSeconds(HandRecordings[currentInstruction].frameTimes[x] - lastFrameTime)); result = HandRecordings[currentInstruction].GRFrames[x]; lastFrameTime = HandRecordings[currentInstruction].frameTimes[x]; if (result == null) { Hand.SetActive(false); continue; } Hand.SetActive(true); for (int i = 0; i < 5; i++) { int startIndex = i * 4 + 1; float squareLengthRoot = (result.points[startIndex] - result.points[0]).sqrMagnitude; float squareLengthFirst = (result.points[startIndex + 1] - result.points[startIndex]).sqrMagnitude; float squareLengthSecond = (result.points[startIndex + 2] - result.points[startIndex + 1]).sqrMagnitude; float squareLengthThird = (result.points[startIndex + 3] - result.points[startIndex + 2]).sqrMagnitude; if (squareLengthRoot < epsilon || squareLengthFirst < epsilon || squareLengthSecond < epsilon || squareLengthThird < epsilon) { continue; } for (int j = i + 1; j < 5; j++) { int nextStartIndex = j * 4 + 1; if ((result.points[nextStartIndex] - result.points[startIndex]).sqrMagnitude == 0) { continue; } } } Vector3 _Wrist = result.points[0]; Vector3 _Index = result.points[5]; Vector3 _Middle = result.points[9]; Vector3 _ring = result.points[13]; transform.position = _Wrist; Vector3 _MidDir = _Middle - _Wrist; Vector3 _ringDir = _ring - _Wrist; Vector3 _IndexDir = _Index - _Wrist; Vector3 _PalmDir = Vector3.Cross(_IndexDir, _ringDir); Vector3 _UpDir = Vector3.Cross(_ringDir, _PalmDir); _MidDir = Quaternion.AngleAxis(4.7f, _PalmDir) * _MidDir; //transform.rotation = Quaternion.LookRotation(_MidDir, _UpDir); setFingerPos(result); setAxis(result); adjustFingerRootPos(result); for (int i = 0; i < 5; ++i) { SetFingerAngle(result, i); } for (int i = 0; i < 5; i++) { int startIndex = i * 4 + 1; Nodes[startIndex].position = Nodes[0].position + (Nodes[startIndex].position - Nodes[0].position).normalized * idealFingerLength[i * 3]; Nodes[startIndex + 1].position = Nodes[startIndex].position + (Nodes[startIndex + 1].position - Nodes[startIndex].position).normalized * idealFingerLength[i * 3 + 1]; Nodes[startIndex + 2].position = Nodes[startIndex + 1].position + (Nodes[startIndex + 2].position - Nodes[startIndex + 1].position).normalized * idealFingerLength[i * 3 + 2]; } } }//Not used!
void setRotation(Vector3 vec0, Vector3 vec1, float angle, Vector3 vec2, int joint, GestureResult hand) { Vector3 vecM0 = Vector3.zero; Vector3 vecM1 = Vector3.zero; if (joint % 4 == 1) { vecM0 = Nodes[joint].position - Nodes[0].position; } else { vecM0 = Nodes[joint].position - Nodes[joint - 1].position; } vecM1 = Nodes[joint + 1].position - Nodes[joint].position; calculateModelPos(vec0, vec1, vecM0, vecM1, out angle, out vec2); Nodes[joint].rotation = Quaternion.AngleAxis(angle, Vector3.Cross(vecM1, vec2)) * Nodes[joint].rotation; }
void Update() { if (!GestureProvider.UpdatedInThisFrame) { return; } GestureResult result = IsLeft ? GestureProvider.LeftHand : GestureProvider.RightHand; if (result == null) { Hand.SetActive(false); return; } Hand.SetActive(true); for (int i = 0; i < 5; i++) { int startIndex = i * 4 + 1; float squareLengthRoot = (result.points[startIndex] - result.points[0]).sqrMagnitude; float squareLengthFirst = (result.points[startIndex + 1] - result.points[startIndex]).sqrMagnitude; float squareLengthSecond = (result.points[startIndex + 2] - result.points[startIndex + 1]).sqrMagnitude; float squareLengthThird = (result.points[startIndex + 3] - result.points[startIndex + 2]).sqrMagnitude; if (squareLengthRoot < epsilon || squareLengthFirst < epsilon || squareLengthSecond < epsilon || squareLengthThird < epsilon) { return; } for (int j = i + 1; j < 5; j++) { int nextStartIndex = j * 4 + 1; if ((result.points[nextStartIndex] - result.points[startIndex]).sqrMagnitude == 0) { return; } } } Vector3 _Wrist = result.points[0]; Vector3 _Index = result.points[5]; Vector3 _Middle = result.points[9]; Vector3 _ring = result.points[13]; transform.position = _Wrist; Vector3 _MidDir = _Middle - _Wrist; Vector3 _ringDir = _ring - _Wrist; Vector3 _IndexDir = _Index - _Wrist; Vector3 _PalmDir = Vector3.Cross(_IndexDir, _ringDir); Vector3 _UpDir = Vector3.Cross(_ringDir, _PalmDir); _MidDir = Quaternion.AngleAxis(4.7f, _PalmDir) * _MidDir; transform.rotation = Quaternion.LookRotation(_MidDir, _UpDir); setFingerPos(result); setAxis(result); adjustFingerRootPos(result); for (int i = 0; i < 5; ++i) { SetFingerAngle(result, i); } for (int i = 0; i < 5; i++) { int startIndex = i * 4 + 1; Nodes[startIndex].position = Nodes[0].position + (Nodes[startIndex].position - Nodes[0].position).normalized * idealFingerLength[i * 3]; Nodes[startIndex + 1].position = Nodes[startIndex].position + (Nodes[startIndex + 1].position - Nodes[startIndex].position).normalized * idealFingerLength[i * 3 + 1]; Nodes[startIndex + 2].position = Nodes[startIndex + 1].position + (Nodes[startIndex + 2].position - Nodes[startIndex + 1].position).normalized * idealFingerLength[i * 3 + 2]; } if (colliderType == HandColliderType.Trigger) { UpdateTigger(); } else if (colliderType == HandColliderType.Collider) { UpdateCollider(); } }