IControlRigGetter と IControlRigSetter を追加

add ControlRigRetarget
impl InitialRotationRigGetter.cs
impl NormalizedRotationRigGetter.cs
mv Assets/Vrm10/Runtime/ControlRig/Vrm10ControlBone.cs => Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10ControlBone.cs
mv Assets/VRM10/Runtime/ControlRig/InitialRotations/ControlRigGenerationOption.cs => Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRigGenerationOption.cs
rename Vrm10BoneInitialRotation => BoneInitialRotation
remove Vrm0XCompatibleRig.cs
This commit is contained in:
ousttrue 2023-02-20 15:49:50 +09:00
parent 17973d694a
commit 6dd2bb38cc
19 changed files with 222 additions and 26 deletions

View File

@ -239,7 +239,7 @@ namespace UniHumanoid
return null;
}
IEnumerable<(Transform, HumanBodyBones)> BoneMap
public IEnumerable<(Transform, HumanBodyBones)> BoneMap
{
get
{

View File

@ -34,6 +34,7 @@ namespace UniVRM10
private readonly Quaternion _initialTargetLocalRotation;
private readonly Quaternion _initialTargetGlobalRotation;
private readonly List<Vrm10ControlBone> _children = new List<Vrm10ControlBone>();
public IReadOnlyList<Vrm10ControlBone> Children => _children;
private Vrm10ControlBone(Transform controlTarget, HumanBodyBones boneType, Vrm10ControlBone parent)
{

View File

@ -13,7 +13,7 @@ namespace UniVRM10
/// Create a control rig for the VRM 1.0 model instance.
/// This provides the normalized operation of bones, like VRM 0.x.
/// </summary>
public sealed class Vrm10RuntimeControlRig : IDisposable
public sealed class Vrm10RuntimeControlRig : IDisposable, IControlRigSetter
{
private readonly Transform _controlRigRoot;
private readonly Vrm10ControlBone _hipBone;
@ -73,12 +73,46 @@ namespace UniVRM10
public void EnforceTPose()
{
// TODO: restore hips position
SetRootPosition(_hipBone.ControlBone.position);
foreach (var bone in _bones.Values)
{
bone.ControlBone.localRotation = Quaternion.identity;
}
}
public void SetRootPosition(Vector3 position)
{
// TODO: scale model local position
_hipBone.ControlTarget.position = position;
}
public void SetNormalizedLocalRotation(HumanBodyBones bone, Quaternion normalizedLocalRotation)
{
if (_bones.TryGetValue(bone, out var t))
{
t.ControlBone.localRotation = normalizedLocalRotation;
}
}
IEnumerable<(HumanBodyBones Head, HumanBodyBones Parent)> Traverse(Vrm10ControlBone bone, Vrm10ControlBone parent = null)
{
yield return (bone.BoneType, parent != null ? parent.BoneType : HumanBodyBones.LastBone);
foreach (var child in bone.Children)
{
foreach (var headParent in Traverse(child, bone))
{
yield return headParent;
}
}
}
public IEnumerable<(HumanBodyBones Head, HumanBodyBones Parent)> EnumerateBones()
{
foreach (var headParent in Traverse(_hipBone))
{
yield return headParent;
}
}
}
}

View File

@ -5,7 +5,7 @@ namespace UniVRM10
/// <summary>
/// Represents the rotation at the initial pose (TPose)
/// </summary>
public readonly struct Vrm10BoneInitialRotation
public readonly struct BoneInitialRotation
{
public readonly Transform Transform;
@ -15,7 +15,7 @@ namespace UniVRM10
public readonly Quaternion InitialGlobalRotation;
public Vrm10BoneInitialRotation(Transform transform)
public BoneInitialRotation(Transform transform)
{
Transform = transform;
InitialLocalPosition = transform.localPosition;
@ -24,11 +24,9 @@ namespace UniVRM10
}
/// <summary>
/// 初期姿勢からの相対的な回転。
///
/// VRM-0.X 互換リグでは localRotation と同じ値を示す。
/// Convert the local rotation, including the initial rotation, to a normalized local rotation
/// </summary>
Quaternion NormalizedLocalRotation
public Quaternion NormalizedLocalRotation
{
get
{

View File

@ -0,0 +1,15 @@
namespace UniVRM10
{
public static class ControlRigRetarget
{
public static void Retarget(IControlRigGetter getter, IControlRigSetter setter)
{
foreach (var (head, parent) in setter.EnumerateBones())
{
var q = getter.GetNormalizedLocalRotation(head, parent);
setter.SetNormalizedLocalRotation(head, q);
}
setter.SetRootPosition(getter.GetRootPosition());
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: d1e0f212571bf3f41809f19c2d8f3211
guid: 55c7c4cd6bc756142a927d385a1c0d29
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -0,0 +1,11 @@
using UnityEngine;
namespace UniVRM10
{
public interface IControlRigGetter
{
Vector3 GetRootPosition();
Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone);
}
}

View File

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

View File

@ -0,0 +1,17 @@
using System.Collections.Generic;
using UnityEngine;
namespace UniVRM10
{
public interface IControlRigSetter
{
/// TODO: 何らかのスケーリングが必用
void SetRootPosition(Vector3 position);
/// <param name="normalizedLocalRotation">初期姿勢(TPose) が Quaternion.Identity である相対回転</param>
void SetNormalizedLocalRotation(HumanBodyBones bone, Quaternion normalizedLocalRotation);
/// <returns>ボーンを親ボーンとセットで返す</returns>
IEnumerable<(HumanBodyBones Head, HumanBodyBones Parent)> EnumerateBones();
}
}

View File

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

View File

@ -0,0 +1,50 @@
using System.Collections.Generic;
using UnityEngine;
namespace UniVRM10
{
/// <summary>
/// VRM0TPose と異なる初期回転を持ったヒエラルキー
///
/// - XR_EXT_hand_tracking
/// - XR_FB_body_tracking
/// - vrm-animation
///
/// から VRM0TPose 互換の NormalizedLocalRotation(VRM0互換)を取り出す。
/// BoneInitialRotation が値を計算できる。
/// </summary>
public class InitRotationRigGetter : IControlRigGetter
{
Transform m_root;
private readonly Dictionary<HumanBodyBones, BoneInitialRotation> m_bones = new Dictionary<HumanBodyBones, BoneInitialRotation>();
/// <param name="tpose">TPoseのヒエラルキー</param>
public InitRotationRigGetter(Transform root, UniHumanoid.Humanoid humanoid)
{
m_root = root;
foreach (var (t, bone) in humanoid.BoneMap)
{
m_bones.Add(bone, new BoneInitialRotation(t));
}
}
public Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone)
{
if (m_bones.TryGetValue(bone, out var c))
{
return c.NormalizedLocalRotation;
}
else
{
// Debug.LogWarning($"${bone} not found");
return Quaternion.identity;
}
}
public Vector3 GetRootPosition()
{
// TODO: from m_root relative ? scaling ?
return m_bones[HumanBodyBones.Hips].Transform.localPosition;
}
}
}

View File

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

View File

@ -1,15 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
namespace UniVRM10
{
public static class Vrm0XCompatibleRig
{
/// <summary>
/// 空の Dictionary を返します。
/// HumanBodyBones に対応する Quaternion が無い場合は Quaternion.Identity を採用する仕様です。
/// VRM-0.X では T-Pose のときにすべてのボーンが Quaternion.Identity です。
/// </summary>
public static IReadOnlyDictionary<HumanBodyBones, Quaternion> InitialRotations => new Dictionary<HumanBodyBones, Quaternion>();
}
}

View File

@ -0,0 +1,41 @@
using UnityEngine;
namespace UniVRM10
{
/// <summary>
/// 正規化済みのヒエラルキーの getter。
/// localRotation をコピーするだけなのだが、
/// GetNormalizedLocalRotation にて、ボーンの有無(upperChestなど)の違いの対応をする予定(未実装)。
/// </summary>
public class NormalizedRigGetter : IControlRigGetter
{
Transform m_root;
Animator m_animator;
public NormalizedRigGetter(Transform root, Animator animator)
{
m_root = root;
m_animator = animator;
}
public Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone)
{
if (m_animator.GetBoneTransform(bone) is Transform t)
{
// TODO: parentBone relative
return t.localRotation;
}
else
{
// Debug.LogWarning($"{bone} not found");
return Quaternion.identity;
}
}
public Vector3 GetRootPosition()
{
// TODO: from model root ?
return m_animator.GetBoneTransform(HumanBodyBones.Hips).localPosition;
}
}
}

View File

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