diff --git a/Assets/VRM10/Editor/EditorTool/VRM10LookAtEditorTool.cs b/Assets/VRM10/Editor/EditorTool/VRM10LookAtEditorTool.cs
index d0458b33a..b98e66db3 100644
--- a/Assets/VRM10/Editor/EditorTool/VRM10LookAtEditorTool.cs
+++ b/Assets/VRM10/Editor/EditorTool/VRM10LookAtEditorTool.cs
@@ -69,24 +69,24 @@ namespace UniVRM10
{
EditorGUI.BeginChangeCheck();
- var worldOffset = head.localToWorldMatrix.MultiplyPoint(root.Vrm.LookAt.OffsetFromHead);
- worldOffset = Handles.PositionHandle(worldOffset, head.rotation);
+ var eyeWorldPosition = head.localToWorldMatrix.MultiplyPoint(root.Vrm.LookAt.OffsetFromHead);
+ eyeWorldPosition = Handles.PositionHandle(eyeWorldPosition, head.rotation);
- Handles.DrawDottedLine(head.position, worldOffset, 5);
+ Handles.DrawDottedLine(head.position, eyeWorldPosition, 5);
Handles.SphereHandleCap(0, head.position, Quaternion.identity, 0.02f, Event.current.type);
- Handles.SphereHandleCap(0, worldOffset, Quaternion.identity, 0.02f, Event.current.type);
+ Handles.SphereHandleCap(0, eyeWorldPosition, Quaternion.identity, 0.02f, Event.current.type);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(root.Vrm, "LookAt.OffsetFromHead");
- root.Vrm.LookAt.OffsetFromHead = head.worldToLocalMatrix.MultiplyPoint(worldOffset);
+ root.Vrm.LookAt.OffsetFromHead = head.worldToLocalMatrix.MultiplyPoint(eyeWorldPosition);
}
}
if (Application.isPlaying)
{
- OnSceneGUILookAt(root.Vrm.LookAt, root.Runtime.LookAt, head, root.LookAtTargetType, root.Gaze);
+ OnSceneGUILookAt(root.Vrm.LookAt, root.Runtime.LookAt, root.LookAtTargetType, root.LookAtTarget);
}
else
{
@@ -125,28 +125,27 @@ namespace UniVRM10
const float RADIUS = 0.5f;
- static void OnSceneGUILookAt(VRM10ObjectLookAt lookAt, Vrm10RuntimeLookAt runtime, Transform head, VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform gaze)
+ static void OnSceneGUILookAt(VRM10ObjectLookAt lookAt, Vrm10RuntimeLookAt runtime, VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform lookAtTarget)
{
- if (head == null) return;
-
- if (gaze != null)
+ if (lookAtTargetType == VRM10ObjectLookAt.LookAtTargetTypes.SpecifiedTransform && lookAtTarget != null)
{
{
EditorGUI.BeginChangeCheck();
- var newTargetPosition = Handles.PositionHandle(gaze.position, Quaternion.identity);
+ var newTargetPosition = Handles.PositionHandle(lookAtTarget.position, Quaternion.identity);
if (EditorGUI.EndChangeCheck())
{
- Undo.RecordObject(gaze, "Change Look At Target Position");
- gaze.position = newTargetPosition;
+ Undo.RecordObject(lookAtTarget, "Change Look At Target Position");
+ lookAtTarget.position = newTargetPosition;
}
}
Handles.color = new Color(1, 1, 1, 0.6f);
- Handles.DrawDottedLine(runtime.GetLookAtOrigin(head).position, gaze.position, 4.0f);
+ Handles.DrawDottedLine(runtime.LookAtOriginTransform.position, lookAtTarget.position, 4.0f);
}
- var (yaw, pitch) = runtime.GetLookAtYawPitch(head, lookAtTargetType, gaze);
- var lookAtOriginMatrix = runtime.GetLookAtOrigin(head).localToWorldMatrix;
+ var yaw = runtime.Yaw;
+ var pitch = runtime.Pitch;
+ var lookAtOriginMatrix = runtime.LookAtOriginTransform.localToWorldMatrix;
Handles.matrix = lookAtOriginMatrix;
var p = lookAt.OffsetFromHead;
Handles.Label(Vector3.zero,
diff --git a/Assets/VRM10/Runtime/AssemblyInfo.cs b/Assets/VRM10/Runtime/AssemblyInfo.cs
new file mode 100644
index 000000000..cdd50e031
--- /dev/null
+++ b/Assets/VRM10/Runtime/AssemblyInfo.cs
@@ -0,0 +1,5 @@
+#if UNITY_EDITOR
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("VRM10.Tests")]
+#endif
\ No newline at end of file
diff --git a/Assets/VRM10/Runtime/AssemblyInfo.cs.meta b/Assets/VRM10/Runtime/AssemblyInfo.cs.meta
new file mode 100644
index 000000000..e78efb4ef
--- /dev/null
+++ b/Assets/VRM10/Runtime/AssemblyInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c0bb9ff90c68a3f4bb86b5fed930f30e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/VRM10/Runtime/Components/Expression/LookAtEyeDirection.cs b/Assets/VRM10/Runtime/Components/Expression/LookAtEyeDirection.cs
index e3d486f41..f4d9db503 100644
--- a/Assets/VRM10/Runtime/Components/Expression/LookAtEyeDirection.cs
+++ b/Assets/VRM10/Runtime/Components/Expression/LookAtEyeDirection.cs
@@ -13,11 +13,13 @@
public float LeftPitch { get; }
///
+ /// NOTE: 何故か使われていない
/// Yaw of RightEye
///
public float RightYaw { get; }
///
+ /// NOTE: 何故か使われていない
/// Pitch of RightEye
///
public float RightPitch { get; }
diff --git a/Assets/VRM10/Runtime/Components/VRM10Object/VRM10ObjectLookAt.cs b/Assets/VRM10/Runtime/Components/VRM10Object/VRM10ObjectLookAt.cs
index 1077211b1..01a0261c8 100644
--- a/Assets/VRM10/Runtime/Components/VRM10Object/VRM10ObjectLookAt.cs
+++ b/Assets/VRM10/Runtime/Components/VRM10Object/VRM10ObjectLookAt.cs
@@ -1,9 +1,6 @@
using System;
using UnityEngine;
using UniGLTF.Extensions.VRMC_vrm;
-#if UNITY_EDITOR
-using UnityEditor;
-#endif
namespace UniVRM10
{
@@ -12,8 +9,17 @@ namespace UniVRM10
{
public enum LookAtTargetTypes
{
- CalcYawPitchToGaze,
- SetYawPitch,
+ ///
+ /// Vrm10Instance に設定した Transform を見ます.
+ ///
+ SpecifiedTransform = 0,
+ ///
+ /// Vrm10RuntimeLookAt に設定した Yaw/Pitch 値に従います.
+ ///
+ YawPitchValue = 1,
+
+ [Obsolete] CalcYawPitchToGaze = 0,
+ [Obsolete] SetYawPitch = 1,
}
[SerializeField]
diff --git a/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs b/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs
index e3a888704..b7f42c40a 100644
--- a/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs
+++ b/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs
@@ -1,5 +1,7 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using UnityEngine;
+using UnityEngine.Serialization;
namespace UniVRM10
@@ -43,11 +45,20 @@ namespace UniVRM10
public bool DrawLookAtGizmo = true;
///
- /// LookAtTargetTypes.CalcYawPitchToGaze時の注視点
+ /// The model looks at position of the Transform specified in this field.
+ /// That behaviour is available only when LookAtTargetType is SpecifiedTransform.
+ ///
+ /// モデルはここで指定した Transform の位置の方向に目を向けます。
+ /// LookAtTargetType を SpecifiedTransform に設定したときのみ有効です。
///
- [SerializeField]
- public Transform Gaze;
+ [SerializeField, FormerlySerializedAs("Gaze")]
+ public Transform LookAtTarget;
+ ///
+ /// Specify "LookAt" behaviour at runtime.
+ ///
+ /// 実行時の目の動かし方を指定します。
+ ///
[SerializeField]
public VRM10ObjectLookAt.LookAtTargetTypes LookAtTargetType;
@@ -110,15 +121,7 @@ namespace UniVRM10
// cause new Vrm10Runtime.
// init LookAt init rotation.
- var runtime = Runtime;
-
- if (LookAtTargetType == VRM10ObjectLookAt.LookAtTargetTypes.CalcYawPitchToGaze)
- {
- if (Gaze == null)
- {
- LookAtTargetType = VRM10ObjectLookAt.LookAtTargetTypes.SetYawPitch;
- }
- }
+ var _ = Runtime;
}
private void Update()
@@ -165,6 +168,15 @@ namespace UniVRM10
return true;
}
+ #region Obsolete
+ [Obsolete]
+ public Transform Gaze
+ {
+ get => LookAtTarget;
+ set => LookAtTarget = value;
+ }
+
+ #endregion
}
}
diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs
index 0265e65b7..07e419ede 100644
--- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs
+++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs
@@ -63,7 +63,7 @@ namespace UniVRM10
ControlRig = new Vrm10RuntimeControlRig(target.Humanoid, m_target.transform, controlRigInitialRotations);
}
Constraints = target.GetComponentsInChildren();
- LookAt = new Vrm10RuntimeLookAt(target.Vrm.LookAt, target.Humanoid, m_head, target.LookAtTargetType, target.Gaze);
+ LookAt = new Vrm10RuntimeLookAt(target.Vrm.LookAt, target.Humanoid, m_head);
Expression = new Vrm10RuntimeExpression(target, LookAt, LookAt.EyeDirectionApplicable);
var instance = target.GetComponent();
@@ -191,7 +191,7 @@ namespace UniVRM10
}
// 3. Gaze control
- LookAt.Process(m_target.LookAtTargetType, m_target.Gaze);
+ LookAt.Process(m_target.LookAtTargetType, m_target.LookAtTarget);
// 4. Expression
Expression.Process();
diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs
index f01dd1e3b..fef7e15d0 100644
--- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs
+++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs
@@ -1,128 +1,139 @@
using System;
using UniGLTF.Extensions.VRMC_vrm;
-using UnityEditor;
using UnityEngine;
namespace UniVRM10
{
public sealed class Vrm10RuntimeLookAt : ILookAtEyeDirectionProvider
{
- VRM10ObjectLookAt m_lookat;
+ private readonly VRM10ObjectLookAt _lookAt;
+ private readonly Transform _head;
+ private readonly Vector3 _lookAtOriginTransformLocalPosition;
+ private readonly Quaternion _lookAtOriginTransformLocalRotation;
- private Transform m_head;
- private Transform m_leftEye;
- private Transform m_rightEye;
- private ILookAtEyeDirectionApplicable _eyeDirectionApplicable;
-
- internal ILookAtEyeDirectionApplicable EyeDirectionApplicable => _eyeDirectionApplicable;
+ internal ILookAtEyeDirectionApplicable EyeDirectionApplicable { get; }
+ public float Yaw { get; private set; }
+ public float Pitch { get; private set; }
public LookAtEyeDirection EyeDirection { get; private set; }
- #region LookAtTargetTypes.CalcYawPitchToGaze
- // 座標計算用のempty
- Transform m_lookAtSpace;
- public Transform GetLookAtOrigin(Transform head)
- {
- if (!Application.isPlaying)
- {
- return null;
- }
- if (m_lookAtSpace == null)
- {
- m_lookAtSpace = new GameObject("_lookat_origin_").transform;
- m_lookAtSpace.SetParent(head);
- }
- return m_lookAtSpace;
- }
-
///
- /// Headローカルの注視点からYaw, Pitch角を計算する
+ /// Transform that indicates the position center of eyes.
+ /// This only represents the position of center of eyes, not the viewing direction.
+ /// Local +Z axis represents forward vector of the head.
+ /// Local +Y axis represents up vector of the head.
+ ///
+ /// 目の位置を示す Transform。
+ /// 視線方向は反映されない。
+ /// ローカル +Z 軸が頭の正面方向を表す。
+ /// ローカル +Y 軸が頭の上方向を表す。
///
- (float, float) CalcLookAtYawPitch(Vector3 targetWorldPosition, Transform head)
- {
- var lookAtSpace = GetLookAtOrigin(head);
- lookAtSpace.localPosition = m_lookat.OffsetFromHead;
- var localPosition = lookAtSpace.worldToLocalMatrix.MultiplyPoint(targetWorldPosition);
- float yaw, pitch;
- Matrix4x4.identity.CalcYawPitch(localPosition, out yaw, out pitch);
- return (yaw, pitch);
- }
- #endregion
+ public Transform LookAtOriginTransform { get; }
- #region LookAtTargetTypes.SetYawPitch
- float m_yaw;
- float m_pitch;
-
- ///
- /// LookAtTargetTypes.SetYawPitch時の視線の角度を指定する
- ///
- /// Headボーンのforwardに対するyaw角(度)
- /// Headボーンのforwardに対するpitch角(度)
- public void SetLookAtYawPitch(float yaw, float pitch)
+ internal Vrm10RuntimeLookAt(VRM10ObjectLookAt lookAt, UniHumanoid.Humanoid humanoid, Transform head)
{
- m_yaw = yaw;
- m_pitch = pitch;
- }
- #endregion
+ _lookAt = lookAt;
+ _head = head;
+ LookAtOriginTransform = InitializeEyePositionTransform(_head, _lookAt.OffsetFromHead);
+ _lookAtOriginTransformLocalPosition = LookAtOriginTransform.localPosition;
+ _lookAtOriginTransformLocalRotation = LookAtOriginTransform.localRotation;
- ///
- /// LookAtTargetType に応じた yaw, pitch を得る
- ///
- /// Headボーンのforwardに対するyaw角(度), pitch角(度)
- public (float, float) GetLookAtYawPitch(Transform head, VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform gaze)
- {
- switch (lookAtTargetType)
+ var leftEyeBone = humanoid.GetBoneTransform(HumanBodyBones.LeftEye);
+ var rightEyeBone = humanoid.GetBoneTransform(HumanBodyBones.RightEye);
+ if (_lookAt.LookAtType == LookAtType.bone && leftEyeBone != null && rightEyeBone != null)
{
- 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, UniHumanoid.Humanoid humanoid, Transform head, VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform gaze)
- {
- // 初期姿勢で初期化する!
- GetLookAtOrigin(head);
-
- m_lookat = lookat;
-
- m_head = head;
- m_leftEye = humanoid.GetBoneTransform(HumanBodyBones.LeftEye);
- m_rightEye = humanoid.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;
- }
-
- // bone が無いときのエラー防止。マイグレーション失敗?
- if (m_lookat.LookAtType == LookAtType.bone && m_leftEye != null && m_rightEye != null)
- {
- _eyeDirectionApplicable = new LookAtEyeDirectionApplicableToBone(m_leftEye, m_rightEye, m_lookat.HorizontalOuter, m_lookat.HorizontalInner, m_lookat.VerticalDown, m_lookat.VerticalUp);
+ EyeDirectionApplicable = new LookAtEyeDirectionApplicableToBone(leftEyeBone, rightEyeBone, _lookAt.HorizontalOuter, _lookAt.HorizontalInner, _lookAt.VerticalDown, _lookAt.VerticalUp);
}
else
{
- _eyeDirectionApplicable = new LookAtEyeDirectionApplicableToExpression(m_lookat.HorizontalOuter, m_lookat.HorizontalInner, m_lookat.VerticalDown, m_lookat.VerticalUp);
+ EyeDirectionApplicable = new LookAtEyeDirectionApplicableToExpression(_lookAt.HorizontalOuter, _lookAt.HorizontalInner, _lookAt.VerticalDown, _lookAt.VerticalUp);
}
}
- internal void Process(VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform gaze)
+ internal void Process(VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform lookAtTarget)
{
- var (yaw, pitch) = GetLookAtYawPitch(m_head, lookAtTargetType, gaze);
- EyeDirection = new LookAtEyeDirection(yaw, pitch, 0, 0);
+ LookAtOriginTransform.localPosition = _lookAtOriginTransformLocalPosition;
+ LookAtOriginTransform.localRotation = _lookAtOriginTransformLocalRotation;
+
+ switch (lookAtTargetType)
+ {
+ case VRM10ObjectLookAt.LookAtTargetTypes.SpecifiedTransform:
+ // NOTE: 指定された Transform の位置を向くように Yaw/Pitch を計算して適用する
+ if (lookAtTarget != null)
+ {
+ var value = CalculateYawPitchFromLookAtPosition(lookAtTarget.position);
+ SetYawPitchManually(value.Yaw, value.Pitch);
+ }
+ break;
+ case VRM10ObjectLookAt.LookAtTargetTypes.YawPitchValue:
+ // NOTE: 直接 Set された Yaw/Pitch を使って計算する
+ break;
+ }
+
+ EyeDirection = new LookAtEyeDirection(Yaw, Pitch, 0, 0);
}
+
+ ///
+ /// Yaw/Pitch 値を直接設定します。
+ /// LookAtTargetTypes が SpecifiedTransform の場合、ここで設定しても値は上書きされます。
+ ///
+ /// Headボーンのforwardに対するyaw角(度)
+ /// Headボーンのforwardに対するpitch角(度)
+ public void SetYawPitchManually(float yaw, float pitch)
+ {
+ Yaw = yaw;
+ Pitch = pitch;
+ }
+
+ public (float Yaw, float Pitch) CalculateYawPitchFromLookAtPosition(Vector3 lookAtWorldPosition)
+ {
+ var localPosition = LookAtOriginTransform.worldToLocalMatrix.MultiplyPoint(lookAtWorldPosition);
+ Matrix4x4.identity.CalcYawPitch(localPosition, out var yaw, out var pitch);
+ return (yaw, pitch);
+ }
+
+ private static Transform InitializeEyePositionTransform(Transform head, Vector3 eyeOffsetValue)
+ {
+ if (!Application.isPlaying) return null;
+
+ // NOTE: このメソッドを実行するとき、モデル全体は初期姿勢(T-Pose)でなければならない。
+ var eyePositionTransform = new GameObject("_eye_transform_").transform;
+ eyePositionTransform.SetParent(head);
+ eyePositionTransform.localPosition = eyeOffsetValue;
+ eyePositionTransform.rotation = Quaternion.identity;
+
+ return eyePositionTransform;
+ }
+
+#region Obsolete
+ [Obsolete]
+ public Transform GetLookAtOrigin(Transform head)
+ {
+ return LookAtOriginTransform;
+ }
+
+ [Obsolete]
+ public void SetLookAtYawPitch(float yaw, float pitch)
+ {
+ SetYawPitchManually(yaw, pitch);
+ }
+
+ [Obsolete]
+ public (float, float) GetLookAtYawPitch(
+ Transform head,
+ VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType,
+ Transform gaze)
+ {
+ switch (lookAtTargetType)
+ {
+ case VRM10ObjectLookAt.LookAtTargetTypes.SpecifiedTransform:
+ return CalculateYawPitchFromLookAtPosition(gaze.position);
+ case VRM10ObjectLookAt.LookAtTargetTypes.YawPitchValue:
+ return (Yaw, Pitch);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(lookAtTargetType), lookAtTargetType, null);
+ }
+ }
+#endregion
}
}
diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Loaded.cs b/Assets/VRM10_Samples/VRM10Viewer/VRM10Loaded.cs
index 861c2e783..60dc9e012 100644
--- a/Assets/VRM10_Samples/VRM10Viewer/VRM10Loaded.cs
+++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10Loaded.cs
@@ -69,8 +69,8 @@ namespace UniVRM10.VRM10Viewer
m_blink = instance.gameObject.AddComponent();
m_autoExpression = instance.gameObject.AddComponent();
- m_controller.LookAtTargetType = VRM10ObjectLookAt.LookAtTargetTypes.CalcYawPitchToGaze;
- m_controller.Gaze = lookAtTarget;
+ m_controller.LookAtTargetType = VRM10ObjectLookAt.LookAtTargetTypes.SpecifiedTransform;
+ m_controller.LookAtTarget = lookAtTarget;
}
}