mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-21 18:15:39 -05:00
Vrm10RuntimeLookAt
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Headローカルの注視点からYaw, Pitch角を計算する
|
||||
/// </summary>
|
||||
(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;
|
||||
|
||||
/// <summary>
|
||||
/// LookAtTargetTypes.SetYawPitch時の視線の角度を指定する
|
||||
/// </summary>
|
||||
/// <param name="yaw">Headボーンのforwardに対するyaw角(度)</param>
|
||||
/// <param name="pitch">Headボーンのforwardに対するpitch角(度)</param>
|
||||
public void SetLookAtYawPitch(float yaw, float pitch)
|
||||
{
|
||||
m_yaw = yaw;
|
||||
m_pitch = pitch;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// LookAtTargetType に応じた yaw, pitch を得る
|
||||
/// </summary>
|
||||
/// <returns>Headボーンのforwardに対するyaw角(度), pitch角(度)</returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Headローカルの注視点からYaw, Pitch角を計算する
|
||||
/// </summary>
|
||||
(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;
|
||||
|
||||
/// <summary>
|
||||
/// LookAtTargetTypes.SetYawPitch時の視線の角度を指定する
|
||||
/// </summary>
|
||||
/// <param name="yaw">Headボーンのforwardに対するyaw角(度)</param>
|
||||
/// <param name="pitch">Headボーンのforwardに対するpitch角(度)</param>
|
||||
public void SetLookAtYawPitch(float yaw, float pitch)
|
||||
{
|
||||
m_yaw = yaw;
|
||||
m_pitch = pitch;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// LookAtTargetType に応じた yaw, pitch を得る
|
||||
/// </summary>
|
||||
/// <returns>Headボーンのforwardに対するyaw角(度), pitch角(度)</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08fd3fec20846764dbb598cf75b13356
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user