From 21c457a8689b56e6192b2fcf801ad03b21b7f8d2 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Wed, 11 Oct 2023 18:31:20 +0900 Subject: [PATCH 1/3] Fix incorrect eye direction control at VRM 1.0 --- .../Components/LookAt/LookAtEyeDirection.cs | 11 +++++- .../LookAtEyeDirectionApplicableToBone.cs | 36 +++++++++++-------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirection.cs b/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirection.cs index 2f36fe60b..5aa6c250a 100644 --- a/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirection.cs +++ b/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirection.cs @@ -2,10 +2,19 @@ { public readonly struct LookAtEyeDirection { + /// + /// Positive is right. + /// Negative is left. + /// + /// public float Yaw { get; } /// - /// Pitch of LeftEye + /// Positive is upper. + /// Negative is lower. + /// + /// Usually in z-forward y-up left coordinates, positive is lower. + /// This is inverted because of following the vrm-1.0 specification. /// public float Pitch { get; } diff --git a/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs b/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs index 89e483c67..619d04928 100644 --- a/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs +++ b/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs @@ -3,13 +3,18 @@ using UnityEngine; namespace UniVRM10 { + /// + /// Apply eye direction to bone transforms. + /// internal sealed class LookAtEyeDirectionApplicableToBone : ILookAtEyeDirectionApplicable { private readonly Transform _leftEye; - private readonly Matrix4x4 _leftInit; + private readonly Quaternion _leftEyePreMultiplyRotation; + private readonly Quaternion _leftEyePostMultiplyRotation; private readonly Transform _rightEye; - private readonly Matrix4x4 _rightInit; + private readonly Quaternion _rightEyePreMultiplyRotation; + private readonly Quaternion _rightEyePostMultiplyRotation; private readonly CurveMapper _horizontalOuter; private readonly CurveMapper _horizontalInner; @@ -20,18 +25,21 @@ namespace UniVRM10 CurveMapper horizontalOuter, CurveMapper horizontalInner, CurveMapper verticalDown, CurveMapper verticalUp) { _leftEye = leftEye; - _leftInit = Matrix4x4.Rotate(leftEye.localRotation); + var leftEyeRotation = _leftEye.rotation; + _leftEyePreMultiplyRotation = _leftEye.localRotation * Quaternion.Inverse(leftEyeRotation); + _leftEyePostMultiplyRotation = leftEyeRotation; + _rightEye = rightEye; - _rightInit = Matrix4x4.Rotate(rightEye.localRotation); + var rightEyeRotation = _rightEye.rotation; + _rightEyePreMultiplyRotation = _rightEye.localRotation * Quaternion.Inverse(rightEyeRotation); + _rightEyePostMultiplyRotation = rightEyeRotation; + _horizontalOuter = horizontalOuter; _horizontalInner = horizontalInner; _verticalDown = verticalDown; _verticalUp = verticalUp; } - /// - /// LeftEyeボーンとRightEyeボーンに回転を適用する - /// public void Apply(LookAtEyeDirection eyeDirection, Dictionary actualWeights) { // FIXME @@ -61,10 +69,6 @@ namespace UniVRM10 pitch = _verticalUp.Map(pitch); } - // Apply - // 現状、右目左目を個別に動かす機能は無い。 - // 特に BlendShape 型に対して実装と、Asset のセットアップが煩雑になるので見送っている。 - // 代表して左を採用。 SetYawPitchToBones(new LookAtEyeDirection(leftYaw, pitch)); } @@ -73,12 +77,16 @@ namespace UniVRM10 SetYawPitchToBones(new LookAtEyeDirection(0, 0)); } - private void SetYawPitchToBones(LookAtEyeDirection actualEyeDirection) + private void SetYawPitchToBones(LookAtEyeDirection eyeDirection) { if (_leftEye != null && _rightEye != null) { - _leftEye.localRotation = _leftInit.rotation * Matrix4x4.identity.YawPitchRotation(actualEyeDirection.Yaw, actualEyeDirection.Pitch); - _rightEye.localRotation = _rightInit.rotation * Matrix4x4.identity.YawPitchRotation(actualEyeDirection.Yaw, actualEyeDirection.Pitch); + _leftEye.localRotation = _leftEyePreMultiplyRotation * + Quaternion.Euler(-eyeDirection.Pitch, eyeDirection.Yaw, 0) * + _leftEyePostMultiplyRotation; + _rightEye.localRotation = _rightEyePreMultiplyRotation * + Quaternion.Euler(-eyeDirection.Pitch, eyeDirection.Yaw, 0) * + _rightEyePostMultiplyRotation; } } } From a4dea7d27958474f1aa5def42245afb9aa745b1c Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Wed, 11 Oct 2023 18:38:50 +0900 Subject: [PATCH 2/3] Refactoring --- .../LookAtEyeDirectionApplicableToBone.cs | 60 +++++++++---------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs b/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs index 619d04928..8d29ecd2b 100644 --- a/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs +++ b/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs @@ -42,34 +42,7 @@ namespace UniVRM10 public void Apply(LookAtEyeDirection eyeDirection, Dictionary actualWeights) { - // FIXME - var yaw = eyeDirection.Yaw; - var pitch = eyeDirection.Pitch; - - // horizontal - float leftYaw, rightYaw; - if (yaw < 0) - { - leftYaw = -_horizontalOuter.Map(-yaw); - rightYaw = -_horizontalInner.Map(-yaw); - } - else - { - rightYaw = _horizontalOuter.Map(yaw); - leftYaw = _horizontalInner.Map(yaw); - } - - // vertical - if (pitch < 0) - { - pitch = -_verticalDown.Map(-pitch); - } - else - { - pitch = _verticalUp.Map(pitch); - } - - SetYawPitchToBones(new LookAtEyeDirection(leftYaw, pitch)); + SetYawPitchToBones(eyeDirection); } public void Restore() @@ -79,13 +52,38 @@ namespace UniVRM10 private void SetYawPitchToBones(LookAtEyeDirection eyeDirection) { - if (_leftEye != null && _rightEye != null) + float leftYaw, rightYaw; + if (eyeDirection.Yaw < 0) + { + leftYaw = -_horizontalOuter.Map(-eyeDirection.Yaw); + rightYaw = -_horizontalInner.Map(-eyeDirection.Yaw); + } + else + { + rightYaw = _horizontalOuter.Map(eyeDirection.Yaw); + leftYaw = _horizontalInner.Map(eyeDirection.Yaw); + } + + float pitch; + if (eyeDirection.Pitch < 0) + { + pitch = _verticalDown.Map(-eyeDirection.Pitch); + } + else + { + pitch = -_verticalUp.Map(eyeDirection.Pitch); + } + + if (_leftEye != null) { _leftEye.localRotation = _leftEyePreMultiplyRotation * - Quaternion.Euler(-eyeDirection.Pitch, eyeDirection.Yaw, 0) * + Quaternion.Euler(pitch, leftYaw, 0) * _leftEyePostMultiplyRotation; + } + if (_rightEye != null) + { _rightEye.localRotation = _rightEyePreMultiplyRotation * - Quaternion.Euler(-eyeDirection.Pitch, eyeDirection.Yaw, 0) * + Quaternion.Euler(pitch, leftYaw, 0) * _rightEyePostMultiplyRotation; } } From b93dac4c468019409d37f3285adc9b3d4abd4380 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Wed, 11 Oct 2023 18:40:22 +0900 Subject: [PATCH 3/3] Fix outer and inner limitation of eye direction in vrm-1.0 --- .../Components/LookAt/LookAtEyeDirectionApplicableToBone.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs b/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs index 8d29ecd2b..dee0ac4ea 100644 --- a/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs +++ b/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs @@ -60,8 +60,8 @@ namespace UniVRM10 } else { - rightYaw = _horizontalOuter.Map(eyeDirection.Yaw); leftYaw = _horizontalInner.Map(eyeDirection.Yaw); + rightYaw = _horizontalOuter.Map(eyeDirection.Yaw); } float pitch; @@ -83,7 +83,7 @@ namespace UniVRM10 if (_rightEye != null) { _rightEye.localRotation = _rightEyePreMultiplyRotation * - Quaternion.Euler(pitch, leftYaw, 0) * + Quaternion.Euler(pitch, rightYaw, 0) * _rightEyePostMultiplyRotation; } }