IVrm10SpringBoneRuntime

This commit is contained in:
ousttrue
2024-09-20 15:13:25 +09:00
parent c840dcb7a7
commit f7f7f756fa
7 changed files with 118 additions and 32 deletions

View File

@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UniGLTF.Utils;
using UnityEngine;
using UnityEngine.Serialization;
@@ -66,12 +68,36 @@ namespace UniVRM10
private UniHumanoid.Humanoid m_humanoid;
private Vrm10Runtime m_runtime;
public IVrm10SpringBoneRuntime m_springBoneRuntime { get; set; }
private IReadOnlyDictionary<Transform, TransformState> m_defaultTransformStates;
/// <summary>
/// ControlRig の生成オプション
/// </summary>
private bool m_useControlRig;
public IReadOnlyDictionary<Transform, TransformState> DefaultTransformStates
{
get
{
if (m_defaultTransformStates == null)
{
if (TryGetComponent<RuntimeGltfInstance>(out var gltfInstance))
{
// ランタイムインポートならここに到達してゼロコストになる
m_defaultTransformStates = gltfInstance.InitialTransformStates;
}
else
{
// エディタでプレハブ配置してる奴ならこっちに到達して収集する
m_defaultTransformStates = GetComponentsInChildren<Transform>()
.ToDictionary(tf => tf, tf => new TransformState(tf));
}
}
return m_defaultTransformStates;
}
}
/// <summary>
/// VRM ファイルに記録された Humanoid ボーンに対応します。
/// これは、コントロールリグのボーンとは異なります。
@@ -88,9 +114,11 @@ namespace UniVRM10
}
}
/// <summary>
/// ランタイム情報
/// </summary>
public Vrm10Runtime MakeRuntime(bool useControlRig)
{
return new Vrm10Runtime(this, useControlRig, m_springBoneRuntime);
}
public Vrm10Runtime Runtime
{
get
@@ -98,15 +126,39 @@ namespace UniVRM10
if (m_runtime == null)
{
if (this == null) throw new MissingReferenceException("instance was destroyed");
m_runtime = new Vrm10Runtime(this, m_useControlRig);
m_runtime = MakeRuntime(m_useControlRig);
}
return m_runtime;
}
}
internal void InitializeAtRuntime(bool useControlRig)
internal void InitializeAtRuntime(
bool useControlRig,
IVrm10SpringBoneRuntime springBoneRuntime,
IReadOnlyDictionary<Transform, TransformState> defaultTransformStates = null
)
{
m_useControlRig = useControlRig;
m_springBoneRuntime = springBoneRuntime;
if (defaultTransformStates != null)
{
m_defaultTransformStates = defaultTransformStates;
}
else
{
if (TryGetComponent<RuntimeGltfInstance>(out var gltfInstance))
{
// ランタイムインポートならここに到達してゼロコストになる
defaultTransformStates = gltfInstance.InitialTransformStates;
}
else
{
// エディタでプレハブ配置してる奴ならこっちに到達して収集する
defaultTransformStates = GetComponentsInChildren<Transform>()
.ToDictionary(tf => tf, tf => new TransformState(tf));
}
}
}
void Start()

View File

@@ -27,7 +27,7 @@ namespace UniVRM10
public IVrm10Constraint[] Constraints { get; }
public Vrm10RuntimeExpression Expression { get; }
public Vrm10RuntimeLookAt LookAt { get; }
public Vrm10RuntimeSpringBone SpringBone { get; }
public IVrm10SpringBoneRuntime SpringBone { get; }
public IVrm10Animation VrmAnimation { get; set; }
[Obsolete("use Vrm10Runtime.SpringBone.ExternalForce")]
@@ -37,7 +37,7 @@ namespace UniVRM10
set { SpringBone.ExternalForce = value; }
}
public Vrm10Runtime(Vrm10Instance instance, bool useControlRig)
public Vrm10Runtime(Vrm10Instance instance, bool useControlRig, IVrm10SpringBoneRuntime springBoneRuntime)
{
if (!Application.isPlaying)
{
@@ -58,7 +58,8 @@ namespace UniVRM10
Constraints = instance.GetComponentsInChildren<IVrm10Constraint>();
LookAt = new Vrm10RuntimeLookAt(instance.Vrm.LookAt, instance.Humanoid, ControlRig);
Expression = new Vrm10RuntimeExpression(instance, LookAt.EyeDirectionApplicable);
SpringBone = new Vrm10RuntimeSpringBone(instance);
SpringBone = springBoneRuntime;
SpringBone.Initialize(instance);
}
public void Dispose()

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UniGLTF.Utils;
@@ -9,11 +8,10 @@ using UniGLTF.SpringBoneJobs.InputPorts;
namespace UniVRM10
{
public class Vrm10RuntimeSpringBone : IDisposable
public class Vrm10RuntimeSpringBone : IVrm10SpringBoneRuntime
{
private readonly Vrm10Instance m_instance;
private readonly IReadOnlyDictionary<Transform, TransformState> m_defaultTransformStates;
private readonly FastSpringBones.FastSpringBoneService m_fastSpringBoneService;
private Vrm10Instance m_instance;
private readonly FastSpringBones.FastSpringBoneService m_fastSpringBoneService = FastSpringBones.FastSpringBoneService.Instance;
private FastSpringBoneSpring[] m_springs;
private Quaternion[] m_initialLocalRotations;
private FastSpringBoneBuffer m_fastSpringBoneBuffer;
@@ -28,26 +26,14 @@ namespace UniVRM10
set => m_fastSpringBoneBuffer.IsSpringBoneEnabled = value;
}
internal Vrm10RuntimeSpringBone(Vrm10Instance instance)
/// <param name="initialTransform">VRMの初期姿勢(T-Pose)状態。instanceがT-Poseから変化していても大丈夫</param>
public void Initialize(Vrm10Instance instance)
{
m_instance = instance;
if (instance.TryGetComponent<RuntimeGltfInstance>(out var gltfInstance))
{
// ランタイムインポートならここに到達してゼロコストになる
m_defaultTransformStates = gltfInstance.InitialTransformStates;
}
else
{
// エディタでプレハブ配置してる奴ならこっちに到達して収集する
m_defaultTransformStates = instance.GetComponentsInChildren<Transform>()
.ToDictionary(tf => tf, tf => new TransformState(tf));
}
// NOTE: FastSpringBoneService は UnitTest などでは動作しない
if (Application.isPlaying)
{
m_fastSpringBoneService = FastSpringBones.FastSpringBoneService.Instance;
ReconstructSpringBone();
}
}
@@ -113,7 +99,7 @@ namespace UniVRM10
private TransformState GetOrAddDefaultTransformState(Transform tf)
{
if (m_defaultTransformStates.TryGetValue(tf, out var defaultTransformState))
if (m_instance.DefaultTransformStates.TryGetValue(tf, out var defaultTransformState))
{
return defaultTransformState;
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UniGLTF;
using UniGLTF.Utils;
using UnityEngine;
namespace UniVRM10
{
public interface IVrm10SpringBoneRuntime : IDisposable
{
public void Initialize(Vrm10Instance instance);
/// <summary>
/// 主に singleton のバッチング更新。
///
/// 再構築。initialTransform を使って再構築?
/// Joint の増減、T-Pose の変更などある?
/// </summary>
public void ReconstructSpringBone();
/// <summary>
/// initialTransform 状態に復帰。verlet の速度 も 0 に。
/// </summary>
public void RestoreInitialTransform();
public Vector3 ExternalForce { get; set; }
public bool IsSpringBoneEnabled { get; set; }
}
}

View File

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

View File

@@ -24,13 +24,16 @@ namespace UniVRM10
private VRM10Object m_vrmObject;
private List<(ExpressionPreset Preset, VRM10Expression Clip)> m_expressions = new List<(ExpressionPreset, VRM10Expression)>();
private IVrm10SpringBoneRuntime m_springboneRuntime;
public Vrm10Importer(
Vrm10Data vrm,
IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> externalObjectMap = null,
ITextureDeserializer textureDeserializer = null,
IMaterialDescriptorGenerator materialGenerator = null,
bool useControlRig = false,
ImporterContextSettings settings = null
ImporterContextSettings settings = null,
IVrm10SpringBoneRuntime springboneRuntime = null
)
: base(vrm.Data, externalObjectMap, textureDeserializer, settings: settings)
{
@@ -49,6 +52,8 @@ namespace UniVRM10
{
m_externalMap = new Dictionary<SubAssetKey, UnityEngine.Object>();
}
m_springboneRuntime = springboneRuntime ?? new Vrm10RuntimeSpringBone();
}
static void AssignHumanoid(List<VrmLib.Node> nodes, UniGLTF.Extensions.VRMC_vrm.HumanBone humanBone, VrmLib.HumanoidBones key)
@@ -258,7 +263,7 @@ namespace UniVRM10
// VrmController
var controller = Root.AddComponent<Vrm10Instance>();
controller.InitializeAtRuntime(m_useControlRig);
controller.InitializeAtRuntime(m_useControlRig, m_springboneRuntime);
controller.enabled = false;
// vrm

View File

@@ -32,7 +32,7 @@ namespace UniVRM10.Test
controller.Vrm.Expression.Aa.MaterialColorBindings = src.ToArray();
// ok if no exception
var r = new Vrm10Runtime(controller, useControlRig: false);
var r = controller.MakeRuntime(useControlRig: false);
}
[Test]
@@ -56,7 +56,7 @@ namespace UniVRM10.Test
controller.Vrm.Expression.Aa.MaterialUVBindings = src.ToArray();
// ok if no exception
var r = new Vrm10Runtime(controller, useControlRig: false);
var r = controller.MakeRuntime(useControlRig: false);
}
}
}