mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-12 13:59:21 -05:00
Merge pull request #1990 from ousttrue/feature/retarget_interface
IControlRigGetter と IControlRigSetter を追加
This commit is contained in:
@@ -239,7 +239,7 @@ namespace UniHumanoid
|
||||
return null;
|
||||
}
|
||||
|
||||
IEnumerable<(Transform, HumanBodyBones)> BoneMap
|
||||
public IEnumerable<(Transform, HumanBodyBones)> BoneMap
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0f3a2bf6126d4a49b24a5fc2a7b6e64
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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, INormalizedPoseApplicable, ITPoseProvider
|
||||
{
|
||||
private readonly Transform _controlRigRoot;
|
||||
private readonly Vrm10ControlBone _hipBone;
|
||||
@@ -22,7 +22,8 @@ namespace UniVRM10
|
||||
|
||||
public IReadOnlyDictionary<HumanBodyBones, Vrm10ControlBone> Bones => _bones;
|
||||
public Animator ControlRigAnimator { get; }
|
||||
public float InitialHipsHeight { get; }
|
||||
|
||||
public float InitialHipsHeight => HipTPoseWorldPosition.y;
|
||||
|
||||
/// <summary>
|
||||
/// humanoid に対して ControlRig を生成します
|
||||
@@ -37,7 +38,7 @@ namespace UniVRM10
|
||||
_hipBone = Vrm10ControlBone.Build(humanoid, out _bones);
|
||||
_hipBone.ControlBone.SetParent(_controlRigRoot);
|
||||
|
||||
InitialHipsHeight = _hipBone.ControlTarget.position.y;
|
||||
HipTPoseWorldPosition = vrmRoot.worldToLocalMatrix.MultiplyPoint(_hipBone.ControlTarget.position);
|
||||
|
||||
var transformBonePairs = _bones.Select(kv => (kv.Value.ControlBone, kv.Key));
|
||||
_controlRigAvatar = HumanoidLoader.LoadHumanoidAvatar(vrmRoot, transformBonePairs);
|
||||
@@ -73,12 +74,53 @@ namespace UniVRM10
|
||||
|
||||
public void EnforceTPose()
|
||||
{
|
||||
// TODO: restore hips position
|
||||
|
||||
SetHipsPosition(_hipBone.ControlBone.position);
|
||||
foreach (var bone in _bones.Values)
|
||||
{
|
||||
bone.ControlBone.localRotation = Quaternion.identity;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetHipsPosition(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;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 HipTPoseWorldPosition { get; }
|
||||
|
||||
public Quaternion GetBoneTPoseWorldRotation(HumanBodyBones bone)
|
||||
{
|
||||
return Quaternion.identity;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
12
Assets/VRM10/Runtime/ControlRig/INormalizedPoseApplicable.cs
Normal file
12
Assets/VRM10/Runtime/ControlRig/INormalizedPoseApplicable.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public interface INormalizedPoseApplicable
|
||||
{
|
||||
void SetHipsPosition(Vector3 position);
|
||||
|
||||
void SetNormalizedLocalRotation(HumanBodyBones bone, Quaternion normalizedLocalRotation);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d1e0f212571bf3f41809f19c2d8f3211
|
||||
guid: 9e200e64e4f18884d8a35bf9ce27cd4a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
17
Assets/VRM10/Runtime/ControlRig/INormalizedPoseProvider.cs
Normal file
17
Assets/VRM10/Runtime/ControlRig/INormalizedPoseProvider.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public interface INormalizedPoseProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Get hips position in model root space
|
||||
/// </summary>
|
||||
Vector3 GetHipsPosition();
|
||||
|
||||
/// <summary>
|
||||
/// Get normalized local rotation
|
||||
/// </summary>
|
||||
Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 624d9ba92e6c69b40abab8223e530d9e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs
Normal file
27
Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public interface ITPoseProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// * world は ModelRoot を意図していることに注意
|
||||
/// </summary>
|
||||
Vector3 HipTPoseWorldPosition { get; }
|
||||
|
||||
/// <summary>
|
||||
/// * world は ModelRoot を意図していることに注意
|
||||
/// * bone 無いときはどう振る舞うべきか
|
||||
/// </summary>
|
||||
/// <param name="bone"></param>
|
||||
/// <returns></returns>
|
||||
Quaternion GetBoneTPoseWorldRotation(HumanBodyBones bone);
|
||||
|
||||
/// <summary>
|
||||
/// ボーンを親ボーンとセットで列挙する</returns>
|
||||
/// </summary>
|
||||
/// <returns>hips の場合は parent は HumanBodyBones.LastBone で null を表す</returns>
|
||||
IEnumerable<(HumanBodyBones Head, HumanBodyBones Parent)> EnumerateBones();
|
||||
}
|
||||
}
|
||||
11
Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs.meta
Normal file
11
Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc1da1cfaa59c824295059dc6b1f22c0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,69 @@
|
||||
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 sealed class InitRotationPoseProvider : INormalizedPoseProvider, ITPoseProvider
|
||||
{
|
||||
Transform m_root;
|
||||
Transform m_hips;
|
||||
private readonly Dictionary<HumanBodyBones, BoneInitialRotation> m_bones = new Dictionary<HumanBodyBones, BoneInitialRotation>();
|
||||
|
||||
public Vector3 HipTPoseWorldPosition => throw new System.NotImplementedException();
|
||||
|
||||
public InitRotationPoseProvider(Transform root, UniHumanoid.Humanoid humanoid)
|
||||
{
|
||||
m_root = root;
|
||||
m_hips = m_bones[HumanBodyBones.Hips].Transform;
|
||||
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 GetHipsPosition()
|
||||
{
|
||||
if (m_hips.parent == m_root)
|
||||
{
|
||||
return m_hips.localPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public Quaternion GetBoneTPoseWorldRotation(HumanBodyBones bone)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<(HumanBodyBones Head, HumanBodyBones Parent)> EnumerateBones()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b21b9221f1a87564ea6dc5cf6037195a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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>();
|
||||
}
|
||||
}
|
||||
54
Assets/VRM10/Runtime/ControlRig/NormalizedPoseProvider.cs
Normal file
54
Assets/VRM10/Runtime/ControlRig/NormalizedPoseProvider.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
/// <summary>
|
||||
/// 正規化済みのヒエラルキーの getter。
|
||||
/// localRotation をコピーするだけなのだが、
|
||||
/// GetNormalizedLocalRotation にて、ボーンの有無(upperChestなど)の違いの対応をする予定(未実装)。
|
||||
/// </summary>
|
||||
public sealed class NormalizedPoseProvider : INormalizedPoseProvider, ITPoseProvider
|
||||
{
|
||||
Transform m_root;
|
||||
Animator m_animator;
|
||||
|
||||
public Vector3 HipTPoseWorldPosition => throw new System.NotImplementedException();
|
||||
|
||||
public NormalizedPoseProvider(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 GetHipsPosition()
|
||||
{
|
||||
// TODO: from model root ?
|
||||
return m_animator.GetBoneTransform(HumanBodyBones.Hips).localPosition;
|
||||
}
|
||||
|
||||
public Quaternion GetBoneTPoseWorldRotation(HumanBodyBones bone)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<(HumanBodyBones Head, HumanBodyBones Parent)> EnumerateBones()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77dc323422a0e59449bd822dac490495
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
15
Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs
Normal file
15
Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace UniVRM10
|
||||
{
|
||||
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.EnumerateBones())
|
||||
{
|
||||
var q = source.Pose.GetNormalizedLocalRotation(head, parent);
|
||||
sink.Pose.SetNormalizedLocalRotation(head, q);
|
||||
}
|
||||
sink.Pose.SetHipsPosition(source.Pose.GetHipsPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs.meta
Normal file
11
Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49423dc9e9a224545a90221f41d975c8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user