Merge pull request #1601 from ousttrue/fix10/Vrm10Runtime

Fix10/vrm10 runtime
This commit is contained in:
ousttrue 2022-04-19 13:26:38 +09:00 committed by GitHub
commit 7729a3fe2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 343 additions and 281 deletions

View File

@ -48,16 +48,16 @@ namespace UniVRM10
{
m_expressionKeyWeights[slider.Key] = slider.Value;
}
m_target.Vrm.Expression.SetWeights(m_expressionKeyWeights);
m_target.Runtime.Expression.SetWeights(m_expressionKeyWeights);
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Override rates", EditorStyles.boldLabel);
EditorGUI.BeginDisabledGroup(true);
{
EditorGUILayout.Slider("Blink override rate", m_target.Vrm.Expression.BlinkOverrideRate, 0f, 1f);
EditorGUILayout.Slider("LookAt override rate", m_target.Vrm.Expression.LookAtOverrideRate, 0f, 1f);
EditorGUILayout.Slider("Mouth override rate", m_target.Vrm.Expression.MouthOverrideRate, 0f, 1f);
EditorGUILayout.Slider("Blink override rate", m_target.Runtime.Expression.BlinkOverrideRate, 0f, 1f);
EditorGUILayout.Slider("LookAt override rate", m_target.Runtime.Expression.LookAtOverrideRate, 0f, 1f);
EditorGUILayout.Slider("Mouth override rate", m_target.Runtime.Expression.MouthOverrideRate, 0f, 1f);
}
EditorGUI.EndDisabledGroup();
}

View File

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.EditorTools;
@ -60,7 +59,7 @@ namespace UniVRM10
Handles.BeginGUI();
if (Application.isPlaying)
{
ExpressionPreviewInPlay(root?.Vrm?.Expression);
ExpressionPreviewInPlay(root?.Vrm?.Expression, root?.Runtime.Expression);
}
else
{
@ -69,7 +68,7 @@ namespace UniVRM10
Handles.EndGUI();
}
void ExpressionPreviewInPlay(VRM10ObjectExpression expression)
void ExpressionPreviewInPlay(VRM10ObjectExpression expression, Vrm10RuntimeExpression runtime)
{
if (expression == null)
{
@ -87,7 +86,7 @@ namespace UniVRM10
GUILayout.FlexibleSpace();
m_map.Clear();
foreach (var kv in expression.GetWeights())
foreach (var kv in runtime.GetWeights())
{
var key = kv.Key;
if (kv.Key.Preset != ExpressionPreset.custom)
@ -98,7 +97,7 @@ namespace UniVRM10
}
GUILayout.FlexibleSpace();
expression.SetWeights(m_map);
runtime.SetWeights(m_map);
}
EditorGUILayout.EndVertical();
}

View File

@ -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,

View File

@ -265,124 +265,7 @@ namespace UniVRM10
// }
// }
public static IExpressionValidatorFactory ExpressionValidatorFactory = new DefaultExpressionValidator.Factory();
private List<ExpressionKey> _keys = new List<ExpressionKey>();
private Dictionary<ExpressionKey, float> _inputWeights = new Dictionary<ExpressionKey, float>();
private Dictionary<ExpressionKey, float> _actualWeights = new Dictionary<ExpressionKey, float>();
private ExpressionMerger _merger;
private IExpressionValidator _validator;
private LookAtEyeDirection _inputEyeDirection;
private LookAtEyeDirection _actualEyeDirection;
private ILookAtEyeDirectionProvider _eyeDirectionProvider;
private ILookAtEyeDirectionApplicable _eyeDirectionApplicable;
public IReadOnlyList<ExpressionKey> ExpressionKeys => _keys;
public IReadOnlyDictionary<ExpressionKey, float> ActualWeights => _actualWeights;
public LookAtEyeDirection ActualEyeDirection => _actualEyeDirection;
public float BlinkOverrideRate { get; private set; }
public float LookAtOverrideRate { get; private set; }
public float MouthOverrideRate { get; private set; }
int m_debugCount;
internal void Setup(Vrm10Instance target, ILookAtEyeDirectionProvider eyeDirectionProvider, ILookAtEyeDirectionApplicable eyeDirectionApplicable)
{
Restore();
_merger = new ExpressionMerger(this, target.transform);
_keys = Clips.Select(x => CreateKey(x.Clip)).ToList();
var oldInputWeights = _inputWeights;
_inputWeights = _keys.ToDictionary(x => x, x => 0f);
foreach (var key in _keys)
{
// remain user input weights.
if (oldInputWeights.ContainsKey(key)) _inputWeights[key] = oldInputWeights[key];
}
_actualWeights = _keys.ToDictionary(x => x, x => 0f);
_validator = ExpressionValidatorFactory.Create(this);
_eyeDirectionProvider = eyeDirectionProvider;
_eyeDirectionApplicable = eyeDirectionApplicable;
}
internal void Restore()
{
_merger?.RestoreMaterialInitialValues();
_merger = null;
_eyeDirectionApplicable?.Restore();
_eyeDirectionApplicable = null;
}
public void Process()
{
Apply();
}
public IDictionary<ExpressionKey, float> GetWeights()
{
return _inputWeights;
}
public float GetWeight(ExpressionKey expressionKey)
{
if (_inputWeights.ContainsKey(expressionKey))
{
return _inputWeights[expressionKey];
}
return 0f;
}
public LookAtEyeDirection GetEyeDirection()
{
return _inputEyeDirection;
}
public void SetWeights(IEnumerable<KeyValuePair<ExpressionKey, float>> weights)
{
foreach (var (expressionKey, weight) in weights.Select(kv => (kv.Key, kv.Value)))
{
if (_inputWeights.ContainsKey(expressionKey))
{
_inputWeights[expressionKey] = weight;
}
}
Apply();
}
public void SetWeight(ExpressionKey expressionKey, float weight)
{
if (_inputWeights.ContainsKey(expressionKey))
{
_inputWeights[expressionKey] = weight;
}
Apply();
}
/// <summary>
/// 入力 Weight を基に、Validation を行い実際にモデルに適用される Weights を計算し、Merger を介して適用する。
/// この際、LookAt の情報を pull してそれも適用する。
/// </summary>
private void Apply()
{
// 1. Get eye direction from provider.
_inputEyeDirection = _eyeDirectionProvider?.EyeDirection ?? default;
// 2. Validate user input, and Output as actual weights.
_validator.Validate(_inputWeights, _actualWeights,
_inputEyeDirection, out _actualEyeDirection,
out var blink, out var lookAt, out var mouth);
// 3. Set eye direction expression weights or any other side-effects (ex. eye bone).
_eyeDirectionApplicable?.Apply(_actualEyeDirection, _actualWeights);
// 4. Set actual weights to raw blendshapes.
_merger.SetValues(_actualWeights);
BlinkOverrideRate = blink;
LookAtOverrideRate = lookAt;
MouthOverrideRate = mouth;
}
}
}

View File

@ -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);
}
}
}

View File

@ -1,21 +1,12 @@
using System;
using UnityEngine;
using UnityEngine;
namespace UniVRM10
{
/// <summary>
/// VRM全体を制御するコンポーネント。
/// VRM全体を制御するRoot
///
/// 各フレームのHumanoidへのモーション適用後に任意のタイミングで
/// Applyを呼び出してください。
///
/// ヒエラルキー内への参照のシリアライズ
///
/// * Humanoid(VRM必須)
/// * SpringBone の MonoBehaviour でない部分
/// * ColliderGroup
/// * Springs
/// Importer(scripted importer) -> Prefab(editor/asset) -> Instance(scene/MonoBehavior) -> Runtime(play時)
///
/// * DefaultExecutionOrder(11000) means calculate springbone after FinalIK( VRIK )
/// </summary>
@ -24,9 +15,16 @@ namespace UniVRM10
[DefaultExecutionOrder(11000)]
public class Vrm10Instance : MonoBehaviour
{
/// <summary>
/// シリアライズ情報
/// </summary>
[SerializeField, Header("VRM1")]
public VRM10Object Vrm;
/// <summary>
/// SpringBone のシリアライズ情報
/// </summary>
/// <returns></returns>
[SerializeField]
public Vrm10InstanceSpringBone SpringBone = new Vrm10InstanceSpringBone();
@ -55,18 +53,18 @@ namespace UniVRM10
[SerializeField]
public VRM10ObjectLookAt.LookAtTargetTypes LookAtTargetType;
Vrm10InstanceRuntime m_runtime;
Vrm10Runtime m_runtime;
/// <summary>
/// ランタイム実行時に生成されるインスタンス
/// ランタイム情報
/// </summary>
public Vrm10InstanceRuntime Runtime
public Vrm10Runtime Runtime
{
get
{
if (m_runtime == null)
{
m_runtime = new Vrm10InstanceRuntime(this);
m_runtime = new Vrm10Runtime(this);
}
return m_runtime;
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ea81ef4ff96a05a4f8d4f0eefc8bd2fd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -9,7 +9,7 @@ namespace UniVRM10
/// <summary>
/// Play時 と Editorからの参照情報置き場
/// </summary>
public class Vrm10InstanceRuntime : IDisposable
public class Vrm10Runtime : IDisposable
{
private readonly Vrm10Instance m_target;
private readonly VRM10Constraint[] m_constraints;
@ -18,7 +18,13 @@ namespace UniVRM10
private FastSpringBoneBuffer m_fastSpringBoneBuffer;
public Vrm10InstanceRuntime(Vrm10Instance target)
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;
var animator = target.GetComponent<Animator>();
@ -28,8 +34,8 @@ namespace UniVRM10
}
m_head = animator.GetBoneTransform(HumanBodyBones.Head);
target.Vrm.LookAt.Setup(animator, m_head, target.LookAtTargetType, target.Gaze);
target.Vrm.Expression.Setup(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)
{
@ -131,12 +137,12 @@ 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
//
m_target.Vrm.Expression.Process();
m_target.Runtime.Expression.Process();
}
public void Dispose()

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 56e3778fb3288a54d8f898a458e81a23
guid: f690a05022c98184bacf46b6675f5bc8
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -0,0 +1,128 @@
using System.Collections.Generic;
using System.Linq;
namespace UniVRM10
{
public class Vrm10RuntimeExpression
{
public static IExpressionValidatorFactory ExpressionValidatorFactory = new DefaultExpressionValidator.Factory();
private List<ExpressionKey> _keys = new List<ExpressionKey>();
private Dictionary<ExpressionKey, float> _inputWeights = new Dictionary<ExpressionKey, float>();
private Dictionary<ExpressionKey, float> _actualWeights = new Dictionary<ExpressionKey, float>();
private ExpressionMerger _merger;
private IExpressionValidator _validator;
private LookAtEyeDirection _inputEyeDirection;
private LookAtEyeDirection _actualEyeDirection;
private ILookAtEyeDirectionProvider _eyeDirectionProvider;
private ILookAtEyeDirectionApplicable _eyeDirectionApplicable;
public IReadOnlyList<ExpressionKey> ExpressionKeys => _keys;
public IReadOnlyDictionary<ExpressionKey, float> ActualWeights => _actualWeights;
public LookAtEyeDirection ActualEyeDirection => _actualEyeDirection;
public float BlinkOverrideRate { get; private set; }
public float LookAtOverrideRate { get; private set; }
public float MouthOverrideRate { get; private set; }
int m_debugCount;
internal Vrm10RuntimeExpression(Vrm10Instance target, ILookAtEyeDirectionProvider eyeDirectionProvider, ILookAtEyeDirectionApplicable eyeDirectionApplicable)
{
Restore();
_merger = new ExpressionMerger(target.Vrm.Expression, target.transform);
_keys = target.Vrm.Expression.Clips.Select(x => target.Vrm.Expression.CreateKey(x.Clip)).ToList();
var oldInputWeights = _inputWeights;
_inputWeights = _keys.ToDictionary(x => x, x => 0f);
foreach (var key in _keys)
{
// remain user input weights.
if (oldInputWeights.ContainsKey(key)) _inputWeights[key] = oldInputWeights[key];
}
_actualWeights = _keys.ToDictionary(x => x, x => 0f);
_validator = ExpressionValidatorFactory.Create(target.Vrm.Expression);
_eyeDirectionProvider = eyeDirectionProvider;
_eyeDirectionApplicable = eyeDirectionApplicable;
}
internal void Restore()
{
_merger?.RestoreMaterialInitialValues();
_merger = null;
_eyeDirectionApplicable?.Restore();
_eyeDirectionApplicable = null;
}
public void Process()
{
Apply();
}
public IDictionary<ExpressionKey, float> GetWeights()
{
return _inputWeights;
}
public float GetWeight(ExpressionKey expressionKey)
{
if (_inputWeights.ContainsKey(expressionKey))
{
return _inputWeights[expressionKey];
}
return 0f;
}
public LookAtEyeDirection GetEyeDirection()
{
return _inputEyeDirection;
}
public void SetWeights(IEnumerable<KeyValuePair<ExpressionKey, float>> weights)
{
foreach (var (expressionKey, weight) in weights.Select(kv => (kv.Key, kv.Value)))
{
if (_inputWeights.ContainsKey(expressionKey))
{
_inputWeights[expressionKey] = weight;
}
}
Apply();
}
public void SetWeight(ExpressionKey expressionKey, float weight)
{
if (_inputWeights.ContainsKey(expressionKey))
{
_inputWeights[expressionKey] = weight;
}
Apply();
}
/// <summary>
/// 入力 Weight を基に、Validation を行い実際にモデルに適用される Weights を計算し、Merger を介して適用する。
/// この際、LookAt の情報を pull してそれも適用する。
/// </summary>
private void Apply()
{
// 1. Get eye direction from provider.
_inputEyeDirection = _eyeDirectionProvider?.EyeDirection ?? default;
// 2. Validate user input, and Output as actual weights.
_validator.Validate(_inputWeights, _actualWeights,
_inputEyeDirection, out _actualEyeDirection,
out var blink, out var lookAt, out var mouth);
// 3. Set eye direction expression weights or any other side-effects (ex. eye bone).
_eyeDirectionApplicable?.Apply(_actualEyeDirection, _actualWeights);
// 4. Set actual weights to raw blendshapes.
_merger.SetValues(_actualWeights);
BlinkOverrideRate = blink;
LookAtOverrideRate = lookAt;
MouthOverrideRate = mouth;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c644583b448f6e743a6d2a55d1d617bf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 08fd3fec20846764dbb598cf75b13356
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -32,7 +32,7 @@ namespace UniVRM10.Test
controller.Vrm.Expression.Aa.MaterialColorBindings = src.ToArray();
// ok if no exception
var r = new Vrm10InstanceRuntime(controller);
var r = new Vrm10Runtime(controller);
}
[Test]
@ -56,7 +56,7 @@ namespace UniVRM10.Test
controller.Vrm.Expression.Aa.MaterialUVBindings = src.ToArray();
// ok if no exception
var r = new Vrm10InstanceRuntime(controller);
var r = new Vrm10Runtime(controller);
}
}
}

View File

@ -30,17 +30,17 @@ namespace UniVRM10.VRM10Viewer
{
for (var value = 0.0f; value <= 1.0f; value += velocity)
{
Controller.Vrm.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), value);
Controller.Runtime.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), value);
yield return null;
}
Controller.Vrm.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), 1.0f);
Controller.Runtime.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), 1.0f);
yield return new WaitForSeconds(wait);
for (var value = 1.0f; value >= 0; value -= velocity)
{
Controller.Vrm.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), value);
Controller.Runtime.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), value);
yield return null;
}
Controller.Vrm.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), 0);
Controller.Runtime.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), 0);
yield return new WaitForSeconds(wait * 2);
}

View File

@ -33,17 +33,17 @@ namespace UniVRM10.VRM10Viewer
{
for (var value = 0.0f; value <= 1.0f; value += velocity)
{
Controller.Vrm.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), value);
Controller.Runtime.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), value);
yield return null;
}
Controller.Vrm.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), 1.0f);
Controller.Runtime.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), 1.0f);
yield return new WaitForSeconds(wait);
for (var value = 1.0f; value >= 0; value -= velocity)
{
Controller.Vrm.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), value);
Controller.Runtime.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), value);
yield return null;
}
Controller.Vrm.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), 0);
Controller.Runtime.Expression.SetWeight(ExpressionKey.CreateFromPreset(preset), 0);
yield return new WaitForSeconds(wait * 2);
}

View File

@ -72,10 +72,10 @@ namespace UniVRM10.VRM10Viewer
break;
}
m_controller.Vrm.Expression.SetWeight(ExpressionKey.CreateFromPreset(ExpressionPreset.blink), value);
m_controller.Runtime.Expression.SetWeight(ExpressionKey.CreateFromPreset(ExpressionPreset.blink), value);
yield return null;
}
m_controller.Vrm.Expression.SetWeight(ExpressionKey.CreateFromPreset(ExpressionPreset.blink), 1.0f);
m_controller.Runtime.Expression.SetWeight(ExpressionKey.CreateFromPreset(ExpressionPreset.blink), 1.0f);
// wait...
yield return new WaitForSeconds(ClosingTime);
@ -91,10 +91,10 @@ namespace UniVRM10.VRM10Viewer
break;
}
m_controller.Vrm.Expression.SetWeight(ExpressionKey.CreateFromPreset(ExpressionPreset.blink), value);
m_controller.Runtime.Expression.SetWeight(ExpressionKey.CreateFromPreset(ExpressionPreset.blink), value);
yield return null;
}
m_controller.Vrm.Expression.SetWeight(ExpressionKey.CreateFromPreset(ExpressionPreset.blink), 0);
m_controller.Runtime.Expression.SetWeight(ExpressionKey.CreateFromPreset(ExpressionPreset.blink), 0);
}
}

View File

@ -450,6 +450,9 @@ namespace UniVRM10.VRM10Viewer
ct: cancellationToken);
if (vrm10Instance != null)
{
// test. error にならなければよい
vrm10Instance.Runtime.Expression.SetWeight(ExpressionKey.Aa, 0);
if (cancellationToken.IsCancellationRequested)
{
UnityObjectDestoyer.DestroyRuntimeOrEditor(vrm10Instance.gameObject);