diff --git a/Assets/VRM10/Runtime/Components/VrmAnimationInstance/TPose.cs b/Assets/VRM10/Runtime/Components/VrmAnimationInstance/TPose.cs new file mode 100644 index 000000000..96e763cfa --- /dev/null +++ b/Assets/VRM10/Runtime/Components/VrmAnimationInstance/TPose.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using UniGLTF.Utils; +using UnityEngine; + +namespace UniVRM10 +{ + public class TPose : IVrm10Animation + { + public class NoRotation : INormalizedPoseProvider + { + readonly Vector3 m_hips; + + public NoRotation(Vector3 hips) + { + m_hips = hips; + } + + public Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone) + { + return new Quaternion(0, 0, 0, 1); + } + + public Vector3 GetRawHipsPosition() + { + return m_hips; + } + } + + public class Skeleton : ITPoseProvider + { + Vector3 m_hips; + public Skeleton(Vector3 hips) + { + m_hips = hips; + } + + public EuclideanTransform? GetWorldTransform(HumanBodyBones bone) + { + if (bone == HumanBodyBones.Hips) + { + return new EuclideanTransform(m_hips); + } + return default; + } + } + + public (INormalizedPoseProvider, ITPoseProvider) m_controlRig; + + public (INormalizedPoseProvider, ITPoseProvider) ControlRig => m_controlRig; + + // empty + public IReadOnlyDictionary> ExpressionMap => new Dictionary>(); + + public LookAtInput? LookAt => default; + + public TPose(Vector3 hips) + { + m_controlRig = (new NoRotation(hips), new Skeleton(hips)); + } + + public void Dispose() + { + } + + public void ShowBoxMan(bool enable) + { + } + } +} \ No newline at end of file diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs.meta b/Assets/VRM10/Runtime/Components/VrmAnimationInstance/TPose.cs.meta similarity index 83% rename from Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs.meta rename to Assets/VRM10/Runtime/Components/VrmAnimationInstance/TPose.cs.meta index 51e773495..1052a38e1 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs.meta +++ b/Assets/VRM10/Runtime/Components/VrmAnimationInstance/TPose.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 49423dc9e9a224545a90221f41d975c8 +guid: 90e77483e976b074db9a08fcdc1b5d40 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/VRM10/Runtime/ControlRig/Vrm10Retarget.cs b/Assets/VRM10/Runtime/ControlRig/Vrm10Retarget.cs index 045be6766..53abe0bef 100644 --- a/Assets/VRM10/Runtime/ControlRig/Vrm10Retarget.cs +++ b/Assets/VRM10/Runtime/ControlRig/Vrm10Retarget.cs @@ -13,7 +13,8 @@ namespace UniVRM10 } // scaling hips position - var scaling = sink.TPose.GetWorldTransform(HumanBodyBones.LeftUpperLeg).Value.Translation.y / source.TPose.GetWorldTransform(HumanBodyBones.LeftUpperLeg).Value.Translation.y; + var scaleRef = HumanBodyBones.Hips; + var scaling = sink.TPose.GetWorldTransform(scaleRef).Value.Translation.y / source.TPose.GetWorldTransform(scaleRef).Value.Translation.y; var delta = source.Pose.GetRawHipsPosition() - source.TPose.GetWorldTransform(HumanBodyBones.Hips).Value.Translation; sink.Pose.SetRawHipsPosition(sink.TPose.GetWorldTransform(HumanBodyBones.Hips).Value.Translation + delta * scaling); } diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs b/Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs deleted file mode 100644 index 2d91fb3e6..000000000 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs +++ /dev/null @@ -1,31 +0,0 @@ -using UnityEngine; - -namespace UniVRM10.VRM10Viewer -{ - public static class VRM10Retarget - { - public static void Retarget((INormalizedPoseProvider Pose, ITPoseProvider TPose) source, (INormalizedPoseApplicable Pose, ITPoseProvider TPose) sink) - { - foreach (var (head, parent) in sink.TPose.EnumerateBoneParentPairs()) - { - var q = source.Pose.GetNormalizedLocalRotation(head, parent); - sink.Pose.SetNormalizedLocalRotation(head, q); - } - - // scaling hips position - var scaling = sink.TPose.GetWorldTransform(HumanBodyBones.LeftUpperLeg).Value.Translation.y / source.TPose.GetWorldTransform(HumanBodyBones.LeftUpperLeg).Value.Translation.y; - var delta = source.Pose.GetRawHipsPosition() - source.TPose.GetWorldTransform(HumanBodyBones.Hips).Value.Translation; - sink.Pose.SetRawHipsPosition(sink.TPose.GetWorldTransform(HumanBodyBones.Hips).Value.Translation + delta * scaling); - } - - public static void EnforceTPose((INormalizedPoseApplicable Pose, ITPoseProvider TPose) sink) - { - foreach (var (bone, parent) in sink.TPose.EnumerateBoneParentPairs()) - { - sink.Pose.SetNormalizedLocalRotation(bone, Quaternion.identity); - } - - sink.Pose.SetRawHipsPosition(sink.TPose.GetWorldTransform(HumanBodyBones.Hips).Value.Translation); - } - } -} diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs index 9a813670f..2c057385a 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs @@ -61,9 +61,13 @@ namespace UniVRM10.VRM10Viewer m_src.Dispose(); } m_src = value; + + TPose = new TPose(m_src.ControlRig.Item1.GetRawHipsPosition()); } } + public IVrm10Animation TPose; + private CancellationTokenSource _cancellationTokenSource; [Serializable] @@ -209,13 +213,13 @@ namespace UniVRM10.VRM10Viewer ToggleMotion = groups.First(x => x.name == "_Motion_"); } - public bool IsBvhEnabled + public bool IsTPose { - get => ToggleMotion.ActiveToggles().FirstOrDefault() == ToggleMotionBVH; + get => ToggleMotion.ActiveToggles().FirstOrDefault() == ToggleMotionTPose; set { - ToggleMotionTPose.isOn = !value; - ToggleMotionBVH.isOn = value; + ToggleMotionTPose.isOn = value; + ToggleMotionBVH.isOn = !value; } } } @@ -331,7 +335,7 @@ namespace UniVRM10.VRM10Viewer _cancellationTokenSource?.Dispose(); } - bool? m_lastUseBvh = default; + private void Update() { if (Input.GetKeyDown(KeyCode.Tab)) @@ -357,31 +361,19 @@ namespace UniVRM10.VRM10Viewer m_loaded.EnableLipSyncValue = m_enableLipSync.isOn; m_loaded.EnableBlinkValue = m_enableAutoBlink.isOn; m_loaded.EnableAutoExpressionValue = m_enableAutoExpression.isOn; + } - var useBvh = Motion != null; - if (useBvh) + if (m_loaded != null) + { + if (m_ui.IsTPose) { - // update humanoid - if (Motion.ControlRig.Item1 != null && Motion.ControlRig.Item2 != null) - { - VRM10Retarget.Retarget(Motion.ControlRig, (m_loaded.ControlRig, m_loaded.ControlRig)); - } - // update expressions - foreach (var (k, v) in Motion.ExpressionMap) - { - // VRMA-expression use localPosition.x as expression weight - m_loaded.Runtime.Expression.SetWeight(k, v()); - } + m_loaded.Runtime.VrmAnimation = TPose; } - else + else if (Motion != null) { - if (!m_lastUseBvh.HasValue || m_lastUseBvh.Value) - { - Debug.Log("SetPose"); - VRM10Retarget.EnforceTPose((m_loaded.ControlRig, m_loaded.ControlRig)); - } + // Automatically retarget in Vrm10Runtime.Process + m_loaded.Runtime.VrmAnimation = Motion; } - m_lastUseBvh = useBvh; } } @@ -446,9 +438,6 @@ namespace UniVRM10.VRM10Viewer return; } - m_ui.IsBvhEnabled = false; - m_lastUseBvh = false; - try { Motion = await Vrm10PoseLoader.LoadVrmAnimationPose(text);