Merge pull request #2672 from ousttrue/fix/SafeGetInitialPose

nullcheck つきの初期姿勢
This commit is contained in:
ousttrue 2025-06-05 17:26:42 +09:00 committed by GitHub
commit 7faed7e86e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 35 additions and 15 deletions

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using UniGLTF.Utils;
using UnityEngine;
@ -249,5 +250,33 @@ namespace UniGLTF
UnityObjectDestroyer.DestroyRuntimeOrEditor(this.gameObject);
}
}
static Dictionary<Transform, IReadOnlyDictionary<Transform, TransformState>> PoseMap = new();
public static IReadOnlyDictionary<Transform, TransformState> SafeGetInitialPose(
Transform root, bool useCache = true)
{
if (useCache && PoseMap.TryGetValue(root, out var pose))
{
return pose;
}
if (root.TryGetComponent<RuntimeGltfInstance>(out var runtime))
{
// RuntimeGltfInstance があるとき => RuntimeLoad => 初期姿勢は glTF の node に由来する
// copy
pose = runtime.InitialTransformStates.ToDictionary((kv) => kv.Key, (kv) => kv.Value);
}
else
{
// RuntimeGltfInstance が無いとき => Scene 配置の prefab など。シーンの現状を代用する。
// T-Pose であることを期待しているが既に T-Pose でないかもしれない。
pose = root.GetComponentsInChildren<Transform>().ToDictionary(x => x, x => new TransformState(x));
}
// add cache
PoseMap.Add(root, pose);
return pose;
}
}
}

View File

@ -53,8 +53,7 @@ namespace VRM.SpringBoneJobs
}
}
var runtime = root.GetComponent<RuntimeGltfInstance>();
var initMap = runtime != null ? runtime.InitialTransformStates : root.GetComponentsInChildren<Transform>().ToDictionary(x => x, x => new TransformState(x));
var initMap = RuntimeGltfInstance.SafeGetInitialPose(root.transform);
var joints = new List<FastSpringBoneJoint>();
foreach (var springRoot in component.RootBones)

View File

@ -140,15 +140,7 @@ namespace UniVRM10
// importer 内で InitializeAsync が呼び出し済み
}
var runtime = GetComponent<RuntimeGltfInstance>();
// Vrm10Runtimeが使う初期姿勢を固定する。SpringBone や Constraint の初期姿勢になる。
var initPose = runtime != null
// RuntimeGltfInstance があるとき => RuntimeLoad => 初期姿勢は glTF の node に由来する
? runtime.InitialTransformStates.ToDictionary((kv) => kv.Key, (kv) => kv.Value)
// RuntimeGltfInstance が無いとき => Scene 配置の prefab など。シーンの現状を代用する。既に T-Pose でないかもしれない。
: GetComponentsInChildren<Transform>().ToDictionary(x => x, x => new TransformState(x))
;
var initPose = RuntimeGltfInstance.SafeGetInitialPose(transform);
return new Vrm10Runtime(this, useControlRig, m_springBoneRuntime, initPose);
}

View File

@ -101,11 +101,11 @@ namespace UniVRM10
public void RestoreInitialTransform()
{
// Spring の joint に対応する transform の回転を初期状態
var instance = m_instance.GetComponent<RuntimeGltfInstance>();
var pose = RuntimeGltfInstance.SafeGetInitialPose(m_instance.transform);
foreach (var logic in m_fastSpringBoneBuffer.Logics)
{
var transform = m_fastSpringBoneBuffer.Transforms[logic.headTransformIndex];
transform.localRotation = instance.InitialTransformStates[transform].LocalRotation;
transform.localRotation = pose[transform].LocalRotation;
}
// jobs のバッファにも反映する必要あり

View File

@ -107,11 +107,11 @@ namespace UniVRM10
public void RestoreInitialTransform()
{
// Spring の joint に対応する transform の回転を初期状態
var instance = m_instance.GetComponent<RuntimeGltfInstance>();
var pose = RuntimeGltfInstance.SafeGetInitialPose(m_instance.transform);
foreach (var logic in m_fastSpringBoneBuffer.Logics)
{
var transform = m_fastSpringBoneBuffer.Transforms[logic.headTransformIndex];
transform.localRotation = instance.InitialTransformStates[transform].LocalRotation;
transform.localRotation = pose[transform].LocalRotation;
}
// jobs のバッファにも反映する必要あり