mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-28 05:44:48 -05:00
Merge pull request #1996 from ousttrue/feature/EuclideanTransform
ITPoseProvider を縮小。EuclideanTransform 導入
This commit is contained in:
31
Assets/UniGLTF/Runtime/Utils/EuclideanTransform.cs
Normal file
31
Assets/UniGLTF/Runtime/Utils/EuclideanTransform.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF.Utils
|
||||
{
|
||||
public readonly struct EuclideanTransform
|
||||
{
|
||||
public readonly Quaternion Rotation;
|
||||
public readonly Vector3 Translation;
|
||||
|
||||
public EuclideanTransform(Quaternion rotation, Vector3 translation)
|
||||
{
|
||||
Rotation = rotation;
|
||||
Translation = translation;
|
||||
}
|
||||
public EuclideanTransform(Quaternion rotation)
|
||||
{
|
||||
Rotation = rotation;
|
||||
Translation = Vector3.zero;
|
||||
}
|
||||
public EuclideanTransform(Vector3 translation)
|
||||
{
|
||||
Rotation = Quaternion.identity;
|
||||
Translation = translation;
|
||||
}
|
||||
public EuclideanTransform(Matrix4x4 matrix)
|
||||
{
|
||||
Rotation = matrix.rotation;
|
||||
Translation = matrix.GetColumn(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/UniGLTF/Runtime/Utils/EuclideanTransform.cs.meta
Normal file
11
Assets/UniGLTF/Runtime/Utils/EuclideanTransform.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af1b96890351fa24e9a49e7c4a6c2185
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UniHumanoid;
|
||||
using UnityEngine;
|
||||
using UniGLTF.Utils;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
@@ -68,53 +69,30 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
#region INormalizedPoseApplicable
|
||||
public void SetRawHipsPosition(Vector3 position)
|
||||
void INormalizedPoseApplicable.SetRawHipsPosition(Vector3 position)
|
||||
{
|
||||
var world = _controlRigRoot.TransformPoint(position);
|
||||
_hipBone.ControlBone.position = world;
|
||||
}
|
||||
|
||||
public void SetNormalizedLocalRotation(HumanBodyBones bone, Quaternion normalizedLocalRotation)
|
||||
void INormalizedPoseApplicable.SetNormalizedLocalRotation(HumanBodyBones bone, Quaternion normalizedLocalRotation)
|
||||
{
|
||||
if (_bones.TryGetValue(bone, out var t))
|
||||
{
|
||||
t.ControlBone.localRotation = normalizedLocalRotation;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
IEnumerable<(HumanBodyBones Head, HumanBodyBones Parent)> Traverse(Vrm10ControlBone bone, Vrm10ControlBone parent = null)
|
||||
EuclideanTransform? ITPoseProvider.GetWorldTransform(HumanBodyBones bone)
|
||||
{
|
||||
yield return (bone.BoneType, parent != null ? parent.BoneType : HumanBodyBones.LastBone);
|
||||
|
||||
foreach (var child in bone.Children)
|
||||
if (_bones.TryGetValue(bone, out var t))
|
||||
{
|
||||
foreach (var headParent in Traverse(child, bone))
|
||||
{
|
||||
yield return headParent;
|
||||
}
|
||||
return new EuclideanTransform(t.InitialTargetGlobalPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
#region ITPoseProvider
|
||||
public IEnumerable<(HumanBodyBones Bone, HumanBodyBones Parent)> EnumerateBoneParentPairs()
|
||||
{
|
||||
foreach (var headParent in Traverse(_hipBone))
|
||||
{
|
||||
yield return headParent;
|
||||
}
|
||||
}
|
||||
|
||||
public Quaternion? GetBoneWorldRotation(HumanBodyBones bone)
|
||||
{
|
||||
return Quaternion.identity;
|
||||
}
|
||||
|
||||
public Vector3? GetBoneWorldPosition(HumanBodyBones bone)
|
||||
{
|
||||
return _bones[bone].InitialTargetGlobalPosition;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UniGLTF.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
@@ -16,7 +17,7 @@ namespace UniVRM10
|
||||
{
|
||||
Transform m_root;
|
||||
Animator m_animator;
|
||||
Dictionary<HumanBodyBones, Vector3> m_posMap = new Dictionary<HumanBodyBones, Vector3>();
|
||||
Dictionary<HumanBodyBones, EuclideanTransform> m_posMap = new Dictionary<HumanBodyBones, EuclideanTransform>();
|
||||
|
||||
public AnimatorPoseProvider(Transform root, Animator animator)
|
||||
{
|
||||
@@ -24,24 +25,22 @@ namespace UniVRM10
|
||||
m_animator = animator;
|
||||
|
||||
var hips = animator.GetBoneTransform(HumanBodyBones.Hips);
|
||||
HipTPoseWorldPosition = root.worldToLocalMatrix.MultiplyPoint(hips.position);
|
||||
|
||||
foreach (HumanBodyBones bone in Enum.GetValues(typeof(HumanBodyBones)))
|
||||
{
|
||||
if(bone==HumanBodyBones.LastBone)
|
||||
if (bone == HumanBodyBones.LastBone)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var t = animator.GetBoneTransform(bone);
|
||||
if (t != null)
|
||||
{
|
||||
m_posMap[bone] = root.worldToLocalMatrix.MultiplyPoint(t.position);
|
||||
m_posMap[bone] = new EuclideanTransform(root.worldToLocalMatrix * t.localToWorldMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region INormalizedPoseProvider
|
||||
public Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone)
|
||||
Quaternion INormalizedPoseProvider.GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone)
|
||||
{
|
||||
if (m_animator.GetBoneTransform(bone) is Transform t)
|
||||
{
|
||||
@@ -55,30 +54,22 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 GetRawHipsPosition()
|
||||
Vector3 INormalizedPoseProvider.GetRawHipsPosition()
|
||||
{
|
||||
// TODO: from model root ?
|
||||
return m_animator.GetBoneTransform(HumanBodyBones.Hips).localPosition;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ITPoseProvider
|
||||
public Vector3 HipTPoseWorldPosition { get; }
|
||||
|
||||
public IEnumerable<(HumanBodyBones Bone, HumanBodyBones Parent)> EnumerateBoneParentPairs()
|
||||
EuclideanTransform? ITPoseProvider.GetWorldTransform(HumanBodyBones bone)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
if (m_posMap.TryGetValue(bone, out var t))
|
||||
{
|
||||
return t;
|
||||
}
|
||||
else
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
public Quaternion? GetBoneWorldRotation(HumanBodyBones bone)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public Vector3? GetBoneWorldPosition(HumanBodyBones bone)
|
||||
{
|
||||
return m_posMap[bone];
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UniGLTF.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
@@ -6,15 +8,56 @@ namespace UniVRM10
|
||||
public interface ITPoseProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// このTPoseに含まれるボーンと親ボーンの組み合わせを列挙する。
|
||||
///
|
||||
/// * Humanoidの木構造を深さ優先の順番で列挙する
|
||||
///
|
||||
/// TPose 時のモデルルートを基準とした world 回転と位置を返す。
|
||||
/// 該当する bone が無いときは null。
|
||||
/// </summary>
|
||||
/// <returns>hips の場合は parent は HumanBodyBones.LastBone で null を表す</returns>
|
||||
IEnumerable<(HumanBodyBones Bone, HumanBodyBones Parent)> EnumerateBoneParentPairs();
|
||||
EuclideanTransform? GetWorldTransform(HumanBodyBones bone);
|
||||
}
|
||||
|
||||
Quaternion? GetBoneWorldRotation(HumanBodyBones bone);
|
||||
Vector3? GetBoneWorldPosition(HumanBodyBones bone);
|
||||
public static class ITPoseProviderExtensions
|
||||
{
|
||||
static HumanBodyBones GetParent(ITPoseProvider self, HumanBodyBones bone)
|
||||
{
|
||||
var current = bone;
|
||||
// 無限ループ防止のため念のためカウンター付き
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
var vrmBone = Vrm10HumanoidBoneSpecification.ConvertFromUnityBone(current);
|
||||
var def = Vrm10HumanoidBoneSpecification.GetDefine(vrmBone);
|
||||
var parentBone = Vrm10HumanoidBoneSpecification.ConvertToUnityBone(def.ParentBone.Value);
|
||||
if (self.GetWorldTransform(parentBone).HasValue)
|
||||
{
|
||||
return parentBone;
|
||||
}
|
||||
current = parentBone;
|
||||
}
|
||||
|
||||
// Hips 以外は必ず親ボーンが有るはずなのでここには来ない
|
||||
throw new Exception("parent not found");
|
||||
}
|
||||
|
||||
public static IEnumerable<(HumanBodyBones Bone, HumanBodyBones Parent)> EnumerateBoneParentPairs(this ITPoseProvider self)
|
||||
{
|
||||
foreach (var bone in CachedEnum.GetValues<HumanBodyBones>())
|
||||
{
|
||||
if (bone == HumanBodyBones.LastBone)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!self.GetWorldTransform(bone).HasValue)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bone == HumanBodyBones.Hips)
|
||||
{
|
||||
yield return (bone, HumanBodyBones.LastBone);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return (bone, GetParent(self, bone));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using UniGLTF.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
@@ -31,7 +32,7 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
public Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone)
|
||||
Quaternion INormalizedPoseProvider.GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone)
|
||||
{
|
||||
if (m_bones.TryGetValue(bone, out var c))
|
||||
{
|
||||
@@ -44,7 +45,7 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 GetRawHipsPosition()
|
||||
Vector3 INormalizedPoseProvider.GetRawHipsPosition()
|
||||
{
|
||||
if (m_hips.parent == m_root)
|
||||
{
|
||||
@@ -56,17 +57,7 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<(HumanBodyBones Bone, HumanBodyBones Parent)> EnumerateBoneParentPairs()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public Quaternion? GetBoneWorldRotation(HumanBodyBones bone)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public Vector3? GetBoneWorldPosition(HumanBodyBones bone)
|
||||
EuclideanTransform? ITPoseProvider.GetWorldTransform(HumanBodyBones bone)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ namespace UniVRM10.VRM10Viewer
|
||||
}
|
||||
|
||||
// scaling hips position
|
||||
var scaling = sink.TPose.GetBoneWorldPosition(HumanBodyBones.LeftUpperLeg).Value.y / source.TPose.GetBoneWorldPosition(HumanBodyBones.LeftUpperLeg).Value.y;
|
||||
var delta = source.Pose.GetRawHipsPosition() - source.TPose.GetBoneWorldPosition(HumanBodyBones.Hips).Value;
|
||||
sink.Pose.SetRawHipsPosition(sink.TPose.GetBoneWorldPosition(HumanBodyBones.Hips).Value + delta * scaling);
|
||||
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)
|
||||
@@ -25,7 +25,7 @@ namespace UniVRM10.VRM10Viewer
|
||||
sink.Pose.SetNormalizedLocalRotation(bone, Quaternion.identity);
|
||||
}
|
||||
|
||||
sink.Pose.SetRawHipsPosition(sink.TPose.GetBoneWorldPosition(HumanBodyBones.Hips).Value);
|
||||
sink.Pose.SetRawHipsPosition(sink.TPose.GetWorldTransform(HumanBodyBones.Hips).Value.Translation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user