diff --git a/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirection.cs b/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirection.cs
index f4d9db503c..2f36fe60b1 100644
--- a/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirection.cs
+++ b/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirection.cs
@@ -2,43 +2,24 @@
{
public readonly struct LookAtEyeDirection
{
- ///
- /// Yaw of LeftEye
- ///
- public float LeftYaw { get; }
-
+ public float Yaw { get; }
+
///
/// Pitch of LeftEye
///
- public float LeftPitch { get; }
-
- ///
- /// NOTE: 何故か使われていない
- /// Yaw of RightEye
- ///
- public float RightYaw { get; }
-
- ///
- /// NOTE: 何故か使われていない
- /// Pitch of RightEye
- ///
- public float RightPitch { get; }
+ public float Pitch { get; }
- public LookAtEyeDirection(float leftYaw, float leftPitch, float rightYaw, float rightPitch)
+ public LookAtEyeDirection(float yaw, float pitch)
{
- LeftYaw = leftYaw;
- LeftPitch = leftPitch;
- RightYaw = rightYaw;
- RightPitch = rightPitch;
+ Yaw = yaw;
+ Pitch = pitch;
}
public static LookAtEyeDirection Multiply(LookAtEyeDirection a, float b)
{
return new LookAtEyeDirection(
- a.LeftYaw * b,
- a.LeftPitch * b,
- a.RightYaw * b,
- a.RightPitch * b
+ a.Yaw * b,
+ a.Pitch * b
);
}
}
diff --git a/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs b/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs
index bf4dda2741..89e483c670 100644
--- a/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs
+++ b/Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs
@@ -20,7 +20,7 @@ public LookAtEyeDirectionApplicableToBone(Transform leftEye, Transform rightEye,
CurveMapper horizontalOuter, CurveMapper horizontalInner, CurveMapper verticalDown, CurveMapper verticalUp)
{
_leftEye = leftEye;
- _leftInit= Matrix4x4.Rotate(leftEye.localRotation);
+ _leftInit = Matrix4x4.Rotate(leftEye.localRotation);
_rightEye = rightEye;
_rightInit = Matrix4x4.Rotate(rightEye.localRotation);
_horizontalOuter = horizontalOuter;
@@ -35,9 +35,9 @@ public LookAtEyeDirectionApplicableToBone(Transform leftEye, Transform rightEye,
public void Apply(LookAtEyeDirection eyeDirection, Dictionary actualWeights)
{
// FIXME
- var yaw = eyeDirection.LeftYaw;
- var pitch = eyeDirection.LeftPitch;
-
+ var yaw = eyeDirection.Yaw;
+ var pitch = eyeDirection.Pitch;
+
// horizontal
float leftYaw, rightYaw;
if (yaw < 0)
@@ -62,20 +62,23 @@ public void Apply(LookAtEyeDirection eyeDirection, Dictionary actualWeights)
{
- var yaw = eyeDirection.LeftYaw;
- var pitch = eyeDirection.LeftPitch;
+ var yaw = eyeDirection.Yaw;
+ var pitch = eyeDirection.Pitch;
if (yaw < 0)
{
diff --git a/Assets/VRM10/Runtime/Components/LookAt/LookAtInput.cs b/Assets/VRM10/Runtime/Components/LookAt/LookAtInput.cs
new file mode 100644
index 0000000000..10a26e95b8
--- /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 0000000000..71262e0613
--- /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 459ca42667..8a40ad9e57 100644
--- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs
+++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs
@@ -21,7 +21,7 @@ namespace UniVRM10
///
public class Vrm10Runtime : IDisposable
{
- private readonly Vrm10Instance m_target;
+ private readonly Vrm10Instance m_instance;
private readonly Transform m_head;
private readonly FastSpringBoneService m_fastSpringBoneService;
private readonly IReadOnlyDictionary m_defaultTransformStates;
@@ -51,38 +51,38 @@ public Vector3 ExternalForce
}
}
- public Vrm10Runtime(Vrm10Instance target, bool useControlRig)
+ public Vrm10Runtime(Vrm10Instance instance, bool useControlRig)
{
if (!Application.isPlaying)
{
Debug.LogWarning($"{nameof(Vrm10Runtime)} expects runtime behaviour.");
}
- m_target = target;
+ m_instance = instance;
- if (!target.TryGetBoneTransform(HumanBodyBones.Head, out m_head))
+ if (!instance.TryGetBoneTransform(HumanBodyBones.Head, out m_head))
{
throw new Exception();
}
if (useControlRig)
{
- ControlRig = new Vrm10RuntimeControlRig(target.Humanoid, m_target.transform);
+ ControlRig = new Vrm10RuntimeControlRig(instance.Humanoid, m_instance.transform);
}
- Constraints = target.GetComponentsInChildren();
- LookAt = new Vrm10RuntimeLookAt(target.Vrm.LookAt, target.Humanoid, ControlRig);
- Expression = new Vrm10RuntimeExpression(target, LookAt.EyeDirectionApplicable);
+ Constraints = instance.GetComponentsInChildren();
+ LookAt = new Vrm10RuntimeLookAt(instance.Vrm.LookAt, instance.Humanoid, ControlRig);
+ Expression = new Vrm10RuntimeExpression(instance, LookAt.EyeDirectionApplicable);
- var instance = target.GetComponent();
- if (instance != null)
+ var gltfInstance = instance.GetComponent();
+ if (gltfInstance != null)
{
// ランタイムインポートならここに到達してゼロコストになる
- m_defaultTransformStates = instance.InitialTransformStates;
+ m_defaultTransformStates = gltfInstance.InitialTransformStates;
}
else
{
// エディタでプレハブ配置してる奴ならこっちに到達して収集する
- m_defaultTransformStates = target.GetComponentsInChildren()
+ m_defaultTransformStates = instance.GetComponentsInChildren()
.ToDictionary(tf => tf, tf => new TransformState(tf));
}
@@ -90,7 +90,7 @@ public Vrm10Runtime(Vrm10Instance target, bool useControlRig)
if (Application.isPlaying)
{
m_fastSpringBoneService = FastSpringBoneService.Instance;
- m_fastSpringBoneBuffer = CreateFastSpringBoneBuffer(m_target.SpringBone);
+ m_fastSpringBoneBuffer = CreateFastSpringBoneBuffer(m_instance.SpringBone);
m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer);
}
}
@@ -111,7 +111,7 @@ public void ReconstructSpringBone()
m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer);
m_fastSpringBoneBuffer.Dispose();
- m_fastSpringBoneBuffer = CreateFastSpringBoneBuffer(m_target.SpringBone);
+ m_fastSpringBoneBuffer = CreateFastSpringBoneBuffer(m_instance.SpringBone);
m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer);
}
@@ -203,20 +203,11 @@ public void Process()
Expression.SetWeight(k, v());
}
- // TODO: look at target
- //
- // この Frame の LookAt 値をアップデート
- //
- // struct LookAtValue
- // {
- // LookAtTargetTypes;
- //
- // (float, float) YawPitch; // 一番明確
- // Vector3 GazePosition; // 座標系?
- // Transform GazeTarget; // 解決順のため遅延させる意図があるか
- // }
- //
- // あとで、LookAt.Process の引き数にわたす
+ // look at
+ if (VrmAnimation.LookAt.HasValue)
+ {
+ LookAt.LookAtInput = VrmAnimation.LookAt.Value;
+ }
}
// 2. Control Rig
@@ -228,11 +219,20 @@ public void Process()
constraint.Process();
}
+ if (m_instance.LookAtTargetType == VRM10ObjectLookAt.LookAtTargetTypes.SpecifiedTransform
+ && m_instance.LookAtTarget != null)
+ {
+ // Transform 追跡で視線を生成する。
+ // 値を上書きします。
+ LookAt.LookAtInput = new LookAtInput { WorldPosition = m_instance.LookAtTarget.position };
+ }
+
// 4. Gaze control
- LookAt.Process(m_target.LookAtTargetType, m_target.LookAtTarget);
+ var eyeDirection = LookAt.Process();
// 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 d72ecf54b6..c7b3d0c1df 100644
--- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs
+++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeLookAt.cs
@@ -13,9 +13,17 @@ public sealed class Vrm10RuntimeLookAt : ILookAtEyeDirectionProvider
internal ILookAtEyeDirectionApplicable EyeDirectionApplicable { get; }
- public float Yaw { get; private set; }
- public float Pitch { get; private set; }
+ ///
+ /// 入力値。適宜更新可。
+ ///
+ public LookAtInput LookAtInput { get; set; }
+
+ ///
+ /// 出力値。Process() のみが更新する
+ ///
public LookAtEyeDirection EyeDirection { get; private set; }
+ public float Yaw => EyeDirection.Yaw;
+ public float Pitch => EyeDirection.Pitch;
///
/// Transform that indicates the position center of eyes.
@@ -52,39 +60,33 @@ internal Vrm10RuntimeLookAt(VRM10ObjectLookAt lookAt, UniHumanoid.Humanoid human
}
}
- internal void Process(VRM10ObjectLookAt.LookAtTargetTypes lookAtTargetType, Transform lookAtTarget)
+ internal LookAtEyeDirection Process()
{
LookAtOriginTransform.localPosition = _lookAtOriginTransformLocalPosition;
LookAtOriginTransform.localRotation = _lookAtOriginTransformLocalRotation;
- switch (lookAtTargetType)
+ if (LookAtInput.YawPitch is LookAtEyeDirection dir)
{
- 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 = dir;
}
-
- EyeDirection = new LookAtEyeDirection(Yaw, Pitch, 0, 0);
+ else if (LookAtInput.WorldPosition is Vector3 worldPosition)
+ {
+ // NOTE: 指定された Transform の位置を向くように Yaw/Pitch を計算して適用する
+ var (yaw, pitch) = CalculateYawPitchFromLookAtPosition(worldPosition);
+ EyeDirection = new LookAtEyeDirection(yaw, pitch);
+ }
+ return EyeDirection;
}
///
/// Yaw/Pitch 値を直接設定します。
- /// LookAtTargetTypes が SpecifiedTransform の場合、ここで設定しても値は上書きされます。
+ /// Vrm10Instance.LookAtTargetTypes が SpecifiedTransform の場合、ここで設定しても値は上書きされます。
///
/// Headボーンのforwardに対するyaw角(度)
/// Headボーンのforwardに対するpitch角(度)
public void SetYawPitchManually(float yaw, float pitch)
{
- Yaw = yaw;
- Pitch = pitch;
+ LookAtInput = new LookAtInput { YawPitch = new LookAtEyeDirection(yaw, pitch) };
}
public (float Yaw, float Pitch) CalculateYawPitchFromLookAtPosition(Vector3 lookAtWorldPosition)
@@ -105,7 +107,7 @@ private static Transform InitializeLookAtOriginTransform(Transform rawHead, Tran
return lookAtOrigin;
}
-#region Obsolete
+ #region Obsolete
[Obsolete("Use " + nameof(LookAtOriginTransform))]
public Transform GetLookAtOrigin(Transform head)
{
@@ -134,6 +136,6 @@ public void SetLookAtYawPitch(float yaw, float pitch)
throw new ArgumentOutOfRangeException(nameof(lookAtTargetType), lookAtTargetType, null);
}
}
-#endregion
+ #endregion
}
}
diff --git a/Assets/VRM10/Runtime/Components/VrmAnimationInstance/IVrm10Animation.cs b/Assets/VRM10/Runtime/Components/VrmAnimationInstance/IVrm10Animation.cs
index 7242e5b1f2..6936ab7a31 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 @@ public interface IVrm10Animation : IDisposable
(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 fd0beccefe..4cbb3b861a 100644
--- a/Assets/VRM10/Runtime/Components/VrmAnimationInstance/Vrm10AnimationInstance.cs
+++ b/Assets/VRM10/Runtime/Components/VrmAnimationInstance/Vrm10AnimationInstance.cs
@@ -33,6 +33,8 @@ public void Dispose()
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 ffebf9cabc..ffb925bb97 100644
--- a/Assets/VRM10_Samples/VRM10Viewer/Motions/BvhMotion.cs
+++ b/Assets/VRM10_Samples/VRM10Viewer/Motions/BvhMotion.cs
@@ -17,6 +17,8 @@ public class BvhMotion : IVrm10Animation
IDictionary> _ExpressionMap = new Dictionary>();
public IReadOnlyDictionary> ExpressionMap => (IReadOnlyDictionary>)_ExpressionMap;
+ public LookAtInput? LookAt { get; set; }
+
public BvhMotion(UniHumanoid.BvhImporterContext context)
{
m_context = context;