diff --git a/Assets/VRM10/Editor/EditorTool/VRM10LookAtEditorTool.cs b/Assets/VRM10/Editor/EditorTool/VRM10LookAtEditorTool.cs index 854f6845b..596bbb4f5 100644 --- a/Assets/VRM10/Editor/EditorTool/VRM10LookAtEditorTool.cs +++ b/Assets/VRM10/Editor/EditorTool/VRM10LookAtEditorTool.cs @@ -82,7 +82,7 @@ namespace UniVRM10 if (Application.isPlaying) { - OnSceneGUILookAt(root.Vrm.LookAt, head, root.LookAtTargetType, root.Gaze); + OnSceneGUILookAt(root.Vrm.LookAt, root.Runtime.LookAt, head, root.LookAtTargetType, root.Gaze); } else { @@ -121,7 +121,7 @@ namespace UniVRM10 const float RADIUS = 0.5f; - static void OnSceneGUILookAt(VRM10ObjectLookAt lookAt, Transform head, VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform gaze) + static void OnSceneGUILookAt(VRM10ObjectLookAt lookAt, Vrm10RuntimeLookAt runtime, Transform head, VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform gaze) { if (head == null) return; @@ -138,11 +138,11 @@ namespace UniVRM10 } Handles.color = new Color(1, 1, 1, 0.6f); - Handles.DrawDottedLine(lookAt.GetLookAtOrigin(head).position, gaze.position, 4.0f); + Handles.DrawDottedLine(runtime.GetLookAtOrigin(head).position, gaze.position, 4.0f); } - var (yaw, pitch) = lookAt.GetLookAtYawPitch(head, lookAtTargetType, gaze); - var lookAtOriginMatrix = lookAt.GetLookAtOrigin(head).localToWorldMatrix; + var (yaw, pitch) = runtime.GetLookAtYawPitch(head, lookAtTargetType, gaze); + var lookAtOriginMatrix = runtime.GetLookAtOrigin(head).localToWorldMatrix; Handles.matrix = lookAtOriginMatrix; var p = lookAt.OffsetFromHead; Handles.Label(Vector3.zero, diff --git a/Assets/VRM10/Runtime/Components/VRM10Object/VRM10ObjectLookAt.cs b/Assets/VRM10/Runtime/Components/VRM10Object/VRM10ObjectLookAt.cs index 0c3682256..1077211b1 100644 --- a/Assets/VRM10/Runtime/Components/VRM10Object/VRM10ObjectLookAt.cs +++ b/Assets/VRM10/Runtime/Components/VRM10Object/VRM10ObjectLookAt.cs @@ -8,7 +8,7 @@ using UnityEditor; namespace UniVRM10 { [Serializable] - public class VRM10ObjectLookAt : ILookAtEyeDirectionProvider + public class VRM10ObjectLookAt { public enum LookAtTargetTypes { @@ -33,117 +33,5 @@ namespace UniVRM10 [SerializeField] public CurveMapper VerticalUp = new CurveMapper(90.0f, 10.0f); - - private Transform m_head; - private Transform m_leftEye; - private Transform m_rightEye; - private ILookAtEyeDirectionApplicable _eyeDirectionApplicable; - - internal ILookAtEyeDirectionApplicable EyeDirectionApplicable => _eyeDirectionApplicable; - - public LookAtEyeDirection EyeDirection { get; private set; } - - #region LookAtTargetTypes.CalcYawPitchToGaze - // 座標計算用のempty - Transform m_lookAtOrigin; - public Transform GetLookAtOrigin(Transform head) - { - if (!Application.isPlaying) - { - return null; - } - if (m_lookAtOrigin == null) - { - m_lookAtOrigin = new GameObject("_lookat_origin_").transform; - m_lookAtOrigin.SetParent(head); - } - return m_lookAtOrigin; - } - - /// - /// Headローカルの注視点からYaw, Pitch角を計算する - /// - (float, float) CalcLookAtYawPitch(Vector3 targetWorldPosition, Transform head) - { - GetLookAtOrigin(head).localPosition = OffsetFromHead; - - var localPosition = m_lookAtOrigin.worldToLocalMatrix.MultiplyPoint(targetWorldPosition); - float yaw, pitch; - Matrix4x4.identity.CalcYawPitch(localPosition, out yaw, out pitch); - return (yaw, pitch); - } - #endregion - - #region LookAtTargetTypes.SetYawPitch - float m_yaw; - float m_pitch; - - /// - /// LookAtTargetTypes.SetYawPitch時の視線の角度を指定する - /// - /// Headボーンのforwardに対するyaw角(度) - /// Headボーンのforwardに対するpitch角(度) - public void SetLookAtYawPitch(float yaw, float pitch) - { - m_yaw = yaw; - m_pitch = pitch; - } - #endregion - - /// - /// LookAtTargetType に応じた yaw, pitch を得る - /// - /// Headボーンのforwardに対するyaw角(度), pitch角(度) - public (float, float) GetLookAtYawPitch(Transform head, LookAtTargetTypes lookAtTargetType, Transform gaze) - { - switch (lookAtTargetType) - { - case LookAtTargetTypes.CalcYawPitchToGaze: - // Gaze(Transform)のワールド位置に対して計算する - return CalcLookAtYawPitch(gaze.position, head); - - case LookAtTargetTypes.SetYawPitch: - // 事前にSetYawPitchした値を使う - return (m_yaw, m_pitch); - } - - throw new NotImplementedException(); - } - - internal void Setup(Animator animator, Transform head, LookAtTargetTypes lookAtTargetType, Transform gaze) - { - m_head = head; - m_leftEye = animator.GetBoneTransform(HumanBodyBones.LeftEye); - m_rightEye = animator.GetBoneTransform(HumanBodyBones.RightEye); - - var isRuntimeAsset = true; -#if UNITY_EDITOR - isRuntimeAsset = Application.isPlaying && !PrefabUtility.IsPartOfAnyPrefab(m_head); -#endif - if (isRuntimeAsset && lookAtTargetType == LookAtTargetTypes.CalcYawPitchToGaze && gaze == null) - { - gaze = new GameObject().transform; - gaze.name = "__LOOKAT_GAZE__"; - gaze.SetParent(m_head); - gaze.localPosition = Vector3.forward; - } - switch (LookAtType) - { - case LookAtType.bone: - _eyeDirectionApplicable = new LookAtEyeDirectionApplicableToBone(m_leftEye, m_rightEye, HorizontalOuter, HorizontalInner, VerticalDown, VerticalUp); - break; - case LookAtType.expression: - _eyeDirectionApplicable = new LookAtEyeDirectionApplicableToExpression(HorizontalOuter, HorizontalInner, VerticalDown, VerticalUp); - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - - public void Process(LookAtTargetTypes lookAtTargetType, Transform gaze) - { - var (yaw, pitch) = GetLookAtYawPitch(m_head, lookAtTargetType, gaze); - EyeDirection = new LookAtEyeDirection(yaw, pitch, 0, 0); - } } } diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs index 3335207b6..7bcad98b1 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs @@ -19,9 +19,11 @@ namespace UniVRM10 private FastSpringBoneBuffer m_fastSpringBoneBuffer; private Vrm10RuntimeExpression m_expression; - public Vrm10RuntimeExpression Expression => m_expression; + private Vrm10RuntimeLookAt m_lookat; + public Vrm10RuntimeLookAt LookAt => m_lookat; + public Vrm10Runtime(Vrm10Instance target) { m_target = target; @@ -32,8 +34,8 @@ namespace UniVRM10 } m_head = animator.GetBoneTransform(HumanBodyBones.Head); - target.Vrm.LookAt.Setup(animator, m_head, target.LookAtTargetType, target.Gaze); - m_expression = new Vrm10RuntimeExpression(target, target.Vrm.LookAt, target.Vrm.LookAt.EyeDirectionApplicable); + m_lookat = new Vrm10RuntimeLookAt(target.Vrm.LookAt, animator, m_head, target.LookAtTargetType, target.Gaze); + m_expression = new Vrm10RuntimeExpression(target, m_lookat, m_lookat.EyeDirectionApplicable); if (m_constraints == null) { @@ -135,7 +137,7 @@ namespace UniVRM10 // // gaze control // - m_target.Vrm.LookAt.Process(m_target.LookAtTargetType, m_target.Gaze); + m_target.Runtime.LookAt.Process(m_target.LookAtTargetType, m_target.Gaze); // // expression diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs new file mode 100644 index 000000000..c23e9d14b --- /dev/null +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs @@ -0,0 +1,127 @@ +using System; +using UniGLTF.Extensions.VRMC_vrm; +using UnityEditor; +using UnityEngine; + +namespace UniVRM10 +{ + public class Vrm10RuntimeLookAt: ILookAtEyeDirectionProvider + { + VRM10ObjectLookAt m_lookat; + + private Transform m_head; + private Transform m_leftEye; + private Transform m_rightEye; + private ILookAtEyeDirectionApplicable _eyeDirectionApplicable; + + internal ILookAtEyeDirectionApplicable EyeDirectionApplicable => _eyeDirectionApplicable; + + public LookAtEyeDirection EyeDirection { get; private set; } + + #region LookAtTargetTypes.CalcYawPitchToGaze + // 座標計算用のempty + Transform m_lookAtOrigin; + public Transform GetLookAtOrigin(Transform head) + { + if (!Application.isPlaying) + { + return null; + } + if (m_lookAtOrigin == null) + { + m_lookAtOrigin = new GameObject("_lookat_origin_").transform; + m_lookAtOrigin.SetParent(head); + } + return m_lookAtOrigin; + } + + /// + /// Headローカルの注視点からYaw, Pitch角を計算する + /// + (float, float) CalcLookAtYawPitch(Vector3 targetWorldPosition, Transform head) + { + GetLookAtOrigin(head).localPosition = m_lookat.OffsetFromHead; + + var localPosition = m_lookAtOrigin.worldToLocalMatrix.MultiplyPoint(targetWorldPosition); + float yaw, pitch; + Matrix4x4.identity.CalcYawPitch(localPosition, out yaw, out pitch); + return (yaw, pitch); + } + #endregion + + #region LookAtTargetTypes.SetYawPitch + float m_yaw; + float m_pitch; + + /// + /// LookAtTargetTypes.SetYawPitch時の視線の角度を指定する + /// + /// Headボーンのforwardに対するyaw角(度) + /// Headボーンのforwardに対するpitch角(度) + public void SetLookAtYawPitch(float yaw, float pitch) + { + m_yaw = yaw; + m_pitch = pitch; + } + #endregion + + /// + /// LookAtTargetType に応じた yaw, pitch を得る + /// + /// Headボーンのforwardに対するyaw角(度), pitch角(度) + public (float, float) GetLookAtYawPitch(Transform head, VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform gaze) + { + switch (lookAtTargetType) + { + case VRM10ObjectLookAt.LookAtTargetTypes.CalcYawPitchToGaze: + // Gaze(Transform)のワールド位置に対して計算する + return CalcLookAtYawPitch(gaze.position, head); + + case VRM10ObjectLookAt.LookAtTargetTypes.SetYawPitch: + // 事前にSetYawPitchした値を使う + return (m_yaw, m_pitch); + } + + throw new NotImplementedException(); + } + + internal Vrm10RuntimeLookAt(VRM10ObjectLookAt lookat, Animator animator, Transform head, VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform gaze) + { + m_lookat = lookat; + + m_head = head; + m_leftEye = animator.GetBoneTransform(HumanBodyBones.LeftEye); + m_rightEye = animator.GetBoneTransform(HumanBodyBones.RightEye); + + var isRuntimeAsset = true; +#if UNITY_EDITOR + isRuntimeAsset = Application.isPlaying && !PrefabUtility.IsPartOfAnyPrefab(m_head); +#endif + if (isRuntimeAsset && lookAtTargetType == VRM10ObjectLookAt.LookAtTargetTypes.CalcYawPitchToGaze && gaze == null) + { + gaze = new GameObject().transform; + gaze.name = "__LOOKAT_GAZE__"; + gaze.SetParent(m_head); + gaze.localPosition = Vector3.forward; + } + switch (m_lookat.LookAtType) + { + case LookAtType.bone: + _eyeDirectionApplicable = new LookAtEyeDirectionApplicableToBone(m_leftEye, m_rightEye, m_lookat.HorizontalOuter, m_lookat.HorizontalInner, m_lookat.VerticalDown, m_lookat.VerticalUp); + break; + case LookAtType.expression: + _eyeDirectionApplicable = new LookAtEyeDirectionApplicableToExpression(m_lookat.HorizontalOuter, m_lookat.HorizontalInner, m_lookat.VerticalDown, m_lookat.VerticalUp); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + public void Process(VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform gaze) + { + var (yaw, pitch) = GetLookAtYawPitch(m_head, lookAtTargetType, gaze); + EyeDirection = new LookAtEyeDirection(yaw, pitch, 0, 0); + } + + } +} diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs.meta new file mode 100644 index 000000000..2a02c607a --- /dev/null +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 08fd3fec20846764dbb598cf75b13356 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: