66 lines
2.2 KiB
C#
66 lines
2.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UniGLTF.Utils;
|
|
using UnityEngine;
|
|
|
|
namespace UniVRM10
|
|
{
|
|
public interface ITPoseProvider
|
|
{
|
|
/// <summary>
|
|
/// TPose 時のモデルルートを基準とした、各ボーンの world 回転と位置を返す。
|
|
/// 該当する bone が無いときは null。
|
|
///
|
|
/// 位置のスケーリングに使用するので hips は必ず値を返すこと。
|
|
/// </summary>
|
|
EuclideanTransform? GetWorldTransform(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));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|