diff --git a/Assets/VRM10/Runtime/Components/LookAt/LookAtInput.cs b/Assets/VRM10/Runtime/Components/LookAt/LookAtInput.cs
new file mode 100644
index 000000000..10a26e95b
--- /dev/null
+++ b/Assets/VRM10/Runtime/Components/LookAt/LookAtInput.cs
@@ -0,0 +1,15 @@
+using UnityEngine;
+
+namespace UniVRM10
+{
+ ///
+ /// LookAt を具体的な値に解決する前の入力値
+ /// この値を元に LookAtEyeDirection を生成し、
+ /// LookAtEyeDirection を Bone もしくは MorphTarget に対して適用する。
+ ///
+ public struct LookAtInput
+ {
+ public LookAtEyeDirection? YawPitch;
+ public Vector3? WorldPosition;
+ }
+}
diff --git a/Assets/VRM10/Runtime/Components/LookAt/LookAtInput.cs.meta b/Assets/VRM10/Runtime/Components/LookAt/LookAtInput.cs.meta
new file mode 100644
index 000000000..71262e061
--- /dev/null
+++ b/Assets/VRM10/Runtime/Components/LookAt/LookAtInput.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7f7a52869fd45b2439bce28499c3f8dc
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs
index 8bc37b485..599778319 100644
--- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs
+++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs
@@ -202,21 +202,6 @@ namespace UniVRM10
{
Expression.SetWeight(k, v());
}
-
- // TODO: look at target
- //
- // この Frame の LookAt 値をアップデート
- //
- // struct LookAtValue
- // {
- // LookAtTargetTypes;
- //
- // (float, float) YawPitch; // 一番明確
- // Vector3 GazePosition; // 座標系?
- // Transform GazeTarget; // 解決順のため遅延させる意図があるか
- // }
- //
- // あとで、LookAt.Process の引き数にわたす
}
// 2. Control Rig
@@ -229,10 +214,37 @@ namespace UniVRM10
}
// 4. Gaze control
- LookAt.Process(m_instance.LookAtTargetType, m_instance.LookAtTarget);
+ LookAtInput lookAtInput = default;
+ if (VrmAnimation != null && VrmAnimation.LookAt.HasValue)
+ {
+ // VrmAnimation から LookAt を供給される
+ lookAtInput = VrmAnimation.LookAt.Value;
+ }
+ else if (m_instance.LookAtTargetType == VRM10ObjectLookAt.LookAtTargetTypes.SpecifiedTransform
+ && m_instance.LookAtTarget != null)
+ {
+ // Transform 追跡で 視線を計算する
+ lookAtInput = new LookAtInput { WorldPosition = m_instance.LookAtTarget.position };
+ }
+ else
+ {
+ // 事前に LookAt.SetYawPitchManually を呼び出し済みであることが期待される
+ lookAtInput = new LookAtInput { YawPitch = new LookAtEyeDirection(LookAt.Yaw, LookAt.Pitch, 0, 0) };
+ }
+
+ LookAtEyeDirection eyeDirection = default;
+ if (lookAtInput.YawPitch.HasValue)
+ {
+ eyeDirection = lookAtInput.YawPitch.Value;
+ }
+ else if (lookAtInput.WorldPosition.HasValue)
+ {
+ eyeDirection = LookAt.Process(lookAtInput.WorldPosition.Value);
+ }
// 5. Apply Expression
- Expression.Process(LookAt.EyeDirection);
+ // LookAt の角度制限などはこちらで処理されます。
+ Expression.Process(eyeDirection);
}
}
}
diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs
index d72ecf54b..db66cf427 100644
--- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs
+++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs
@@ -4,8 +4,22 @@ using UnityEngine;
namespace UniVRM10
{
- public sealed class Vrm10RuntimeLookAt : ILookAtEyeDirectionProvider
+ public sealed class Vrm10RuntimeLookAt
{
+ public float Yaw { get; private set; }
+ public float Pitch { get; private set; }
+ ///
+ /// Yaw/Pitch 値を直接設定します。
+ /// LookAtTargetTypes が SpecifiedTransform の場合、ここで設定しても値は上書きされます。
+ ///
+ /// Headボーンのforwardに対するyaw角(度)
+ /// Headボーンのforwardに対するpitch角(度)
+ public void SetYawPitchManually(float yaw, float pitch)
+ {
+ Yaw = yaw;
+ Pitch = pitch;
+ }
+
private readonly VRM10ObjectLookAt _lookAt;
private readonly Transform _head;
private readonly Vector3 _lookAtOriginTransformLocalPosition;
@@ -13,8 +27,6 @@ namespace UniVRM10
internal ILookAtEyeDirectionApplicable EyeDirectionApplicable { get; }
- public float Yaw { get; private set; }
- public float Pitch { get; private set; }
public LookAtEyeDirection EyeDirection { get; private set; }
///
@@ -52,39 +64,12 @@ namespace UniVRM10
}
}
- internal void Process(VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform lookAtTarget)
+ internal LookAtEyeDirection Process(Vector3 worldPosition)
{
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;
+ var (yaw, pitch) = CalculateYawPitchFromLookAtPosition(worldPosition);
+ return new LookAtEyeDirection(yaw, pitch, 0, 0);
}
public (float Yaw, float Pitch) CalculateYawPitchFromLookAtPosition(Vector3 lookAtWorldPosition)
@@ -104,36 +89,5 @@ namespace UniVRM10
return lookAtOrigin;
}
-
-#region Obsolete
- [Obsolete("Use " + nameof(LookAtOriginTransform))]
- public Transform GetLookAtOrigin(Transform head)
- {
- return LookAtOriginTransform;
- }
-
- [Obsolete("Use " + nameof(SetYawPitchManually))]
- public void SetLookAtYawPitch(float yaw, float pitch)
- {
- SetYawPitchManually(yaw, pitch);
- }
-
- [Obsolete("Use " + nameof(Yaw) + " & " + nameof(Pitch))]
- 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/Runtime/Components/VrmAnimationInstance/IVrm10Animation.cs b/Assets/VRM10/Runtime/Components/VrmAnimationInstance/IVrm10Animation.cs
index 7242e5b1f..6936ab7a3 100644
--- a/Assets/VRM10/Runtime/Components/VrmAnimationInstance/IVrm10Animation.cs
+++ b/Assets/VRM10/Runtime/Components/VrmAnimationInstance/IVrm10Animation.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using UnityEngine;
namespace UniVRM10
{
@@ -8,5 +9,6 @@ namespace UniVRM10
(INormalizedPoseProvider, ITPoseProvider) ControlRig { get; }
IReadOnlyDictionary> ExpressionMap { get; }
public void ShowBoxMan(bool enable);
+ LookAtInput? LookAt { get; }
}
}
diff --git a/Assets/VRM10/Runtime/Components/VrmAnimationInstance/Vrm10AnimationInstance.cs b/Assets/VRM10/Runtime/Components/VrmAnimationInstance/Vrm10AnimationInstance.cs
index fd0beccef..4cbb3b861 100644
--- a/Assets/VRM10/Runtime/Components/VrmAnimationInstance/Vrm10AnimationInstance.cs
+++ b/Assets/VRM10/Runtime/Components/VrmAnimationInstance/Vrm10AnimationInstance.cs
@@ -33,6 +33,8 @@ namespace UniVRM10
readonly Dictionary> _ExpressionSetterMap = new();
public IReadOnlyDictionary> ExpressionSetterMap => _ExpressionSetterMap;
+ public LookAtInput? LookAt { get; set; }
+
void InitializeExpression(ExpressionKey key, Func getter, Action setter)
{
_ExpressionGetterMap.Add(key, getter);
diff --git a/Assets/VRM10_Samples/VRM10Viewer/Motions/BvhMotion.cs b/Assets/VRM10_Samples/VRM10Viewer/Motions/BvhMotion.cs
index ffebf9cab..ffb925bb9 100644
--- a/Assets/VRM10_Samples/VRM10Viewer/Motions/BvhMotion.cs
+++ b/Assets/VRM10_Samples/VRM10Viewer/Motions/BvhMotion.cs
@@ -17,6 +17,8 @@ namespace UniVRM10.VRM10Viewer
IDictionary> _ExpressionMap = new Dictionary>();
public IReadOnlyDictionary> ExpressionMap => (IReadOnlyDictionary>)_ExpressionMap;
+ public LookAtInput? LookAt { get; set; }
+
public BvhMotion(UniHumanoid.BvhImporterContext context)
{
m_context = context;