mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-04-25 07:28:51 -05:00
IVrm10SpringBoneRuntime.InitializeAsync
This commit is contained in:
parent
9e5d11be62
commit
0b08507f7a
|
|
@ -122,6 +122,7 @@ namespace UniVRM10
|
|||
// deafult に fallback
|
||||
// TODO: scene に配置した prefab に SpringRuntime をカスタムする手段
|
||||
m_springBoneRuntime = new Vrm10FastSpringboneRuntime();
|
||||
m_springBoneRuntime.InitializeAsync(this, new ImmediateCaller());
|
||||
}
|
||||
return new Vrm10Runtime(this, useControlRig, m_springBoneRuntime);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UniGLTF;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using UniGLTF.SpringBoneJobs.InputPorts;
|
||||
using UniGLTF.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public static class FastSpringBoneBufferFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// このVRMに紐づくSpringBone関連のバッファを構築する。
|
||||
/// </summary>
|
||||
/// <param name="awaitCaller"></param>
|
||||
/// <param name="fastSpringBoneBuffer">TODO: 再利用する</param>
|
||||
/// <returns></returns>
|
||||
public static async Task<FastSpringBoneBuffer> ConstructSpringBoneAsync(IAwaitCaller awaitCaller, Vrm10Instance vrm,
|
||||
FastSpringBoneBuffer fastSpringBoneBuffer = null)
|
||||
{
|
||||
// TODO: Dispose せずに再利用する最適化
|
||||
// new FastSpringBoneBuffer にも構築ロジックがあるので合体して整理する必要あり。
|
||||
// GC 軽減と await 挟み込み
|
||||
if (fastSpringBoneBuffer != null)
|
||||
{
|
||||
fastSpringBoneBuffer.Dispose();
|
||||
}
|
||||
|
||||
Func<Transform, TransformState> GetOrAddDefaultTransformState = (Transform tf) =>
|
||||
{
|
||||
if (vrm.DefaultTransformStates.TryGetValue(tf, out var defaultTransformState))
|
||||
{
|
||||
return defaultTransformState;
|
||||
}
|
||||
|
||||
Debug.LogWarning($"{tf.name} does not exist on load.");
|
||||
return new TransformState(null);
|
||||
};
|
||||
|
||||
// create(Spring情報の再収集。設定変更の反映)
|
||||
var springs = vrm.SpringBone.Springs.Select(spring => new FastSpringBoneSpring
|
||||
{
|
||||
center = spring.Center,
|
||||
colliders = spring.ColliderGroups
|
||||
.SelectMany(group => group.Colliders)
|
||||
.Select(collider => new FastSpringBoneCollider
|
||||
{
|
||||
Transform = collider.transform,
|
||||
Collider = new BlittableCollider
|
||||
{
|
||||
offset = collider.Offset,
|
||||
radius = collider.Radius,
|
||||
tailOrNormal = collider.TailOrNormal,
|
||||
colliderType = TranslateColliderType(collider.ColliderType)
|
||||
}
|
||||
}).ToArray(),
|
||||
joints = spring.Joints
|
||||
.Select(joint => new FastSpringBoneJoint
|
||||
{
|
||||
Transform = joint.transform,
|
||||
Joint = new BlittableJointMutable
|
||||
{
|
||||
radius = joint.m_jointRadius,
|
||||
dragForce = joint.m_dragForce,
|
||||
gravityDir = joint.m_gravityDir,
|
||||
gravityPower = joint.m_gravityPower,
|
||||
stiffnessForce = joint.m_stiffnessForce
|
||||
},
|
||||
DefaultLocalRotation = GetOrAddDefaultTransformState(joint.transform).LocalRotation,
|
||||
}).ToArray(),
|
||||
}).ToArray();
|
||||
|
||||
await awaitCaller.NextFrame();
|
||||
|
||||
fastSpringBoneBuffer = new FastSpringBoneBuffer(springs);
|
||||
return fastSpringBoneBuffer;
|
||||
}
|
||||
|
||||
private static BlittableColliderType TranslateColliderType(VRM10SpringBoneColliderTypes colliderType)
|
||||
{
|
||||
switch (colliderType)
|
||||
{
|
||||
case VRM10SpringBoneColliderTypes.Sphere:
|
||||
return BlittableColliderType.Sphere;
|
||||
case VRM10SpringBoneColliderTypes.Capsule:
|
||||
return BlittableColliderType.Capsule;
|
||||
case VRM10SpringBoneColliderTypes.Plane:
|
||||
return BlittableColliderType.Plane;
|
||||
case VRM10SpringBoneColliderTypes.SphereInside:
|
||||
return BlittableColliderType.SphereInside;
|
||||
case VRM10SpringBoneColliderTypes.CapsuleInside:
|
||||
return BlittableColliderType.CapsuleInside;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f46ef09901938a64aa8a6ce21d1ae044
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,10 +1,8 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using UniGLTF;
|
||||
using UniGLTF.Utils;
|
||||
using UnityEngine;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using UniGLTF.SpringBoneJobs.InputPorts;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
|
|
@ -17,9 +15,12 @@ namespace UniVRM10
|
|||
{
|
||||
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;
|
||||
/// <summary>
|
||||
/// 多重実行防止
|
||||
/// </summary>
|
||||
private bool m_building = false;
|
||||
|
||||
public Vector3 ExternalForce
|
||||
{
|
||||
get => m_fastSpringBoneBuffer.ExternalForce;
|
||||
|
|
@ -33,15 +34,16 @@ namespace UniVRM10
|
|||
|
||||
public float DeltaTime => throw new NotImplementedException();
|
||||
|
||||
/// <param name="initialTransform">VRMの初期姿勢(T-Pose)状態。instanceがT-Poseから変化していても大丈夫</param>
|
||||
public void Initialize(Vrm10Instance instance)
|
||||
public async Task InitializeAsync(Vrm10Instance instance, IAwaitCaller awaitCaller)
|
||||
{
|
||||
m_instance = instance;
|
||||
|
||||
// NOTE: FastSpringBoneService は UnitTest などでは動作しない
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
ReconstructSpringBone();
|
||||
m_fastSpringBoneBuffer = await FastSpringBoneBufferFactory.ConstructSpringBoneAsync(awaitCaller, m_instance);
|
||||
// 登録
|
||||
m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -57,93 +59,40 @@ namespace UniVRM10
|
|||
/// </summary>
|
||||
public void ReconstructSpringBone()
|
||||
{
|
||||
// release
|
||||
if (m_building)
|
||||
{
|
||||
Debug.LogWarning("already building");
|
||||
return;
|
||||
}
|
||||
m_building = true;
|
||||
|
||||
// 登録削除
|
||||
if (m_fastSpringBoneBuffer != null)
|
||||
{
|
||||
m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer);
|
||||
m_fastSpringBoneBuffer.Dispose();
|
||||
}
|
||||
|
||||
// create(Spring情報の再収集。設定変更の反映)
|
||||
m_springs = m_instance.SpringBone.Springs.Select(spring => new FastSpringBoneSpring
|
||||
{
|
||||
center = spring.Center,
|
||||
colliders = spring.ColliderGroups
|
||||
.SelectMany(group => group.Colliders)
|
||||
.Select(collider => new FastSpringBoneCollider
|
||||
{
|
||||
Transform = collider.transform,
|
||||
Collider = new BlittableCollider
|
||||
{
|
||||
offset = collider.Offset,
|
||||
radius = collider.Radius,
|
||||
tailOrNormal = collider.TailOrNormal,
|
||||
colliderType = TranslateColliderType(collider.ColliderType)
|
||||
}
|
||||
}).ToArray(),
|
||||
joints = spring.Joints
|
||||
.Select(joint => new FastSpringBoneJoint
|
||||
{
|
||||
Transform = joint.transform,
|
||||
Joint = new BlittableJointMutable
|
||||
{
|
||||
radius = joint.m_jointRadius,
|
||||
dragForce = joint.m_dragForce,
|
||||
gravityDir = joint.m_gravityDir,
|
||||
gravityPower = joint.m_gravityPower,
|
||||
stiffnessForce = joint.m_stiffnessForce
|
||||
},
|
||||
DefaultLocalRotation = GetOrAddDefaultTransformState(joint.transform).LocalRotation,
|
||||
}).ToArray(),
|
||||
}).ToArray();
|
||||
// new ImmediateCaller() により即時実行して結果を得る。
|
||||
// スパイクは許容する。
|
||||
var task = FastSpringBoneBufferFactory.ConstructSpringBoneAsync(new ImmediateCaller(), m_instance, m_fastSpringBoneBuffer);
|
||||
m_fastSpringBoneBuffer = task.Result;
|
||||
|
||||
// DOTS buffer 構築
|
||||
m_fastSpringBoneBuffer = new FastSpringBoneBuffer(m_springs);
|
||||
// 登録
|
||||
m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer);
|
||||
// reset 用の初期状態の記録
|
||||
m_initialLocalRotations = m_fastSpringBoneBuffer.Transforms.Select(x => x.localRotation).ToArray();
|
||||
}
|
||||
|
||||
private TransformState GetOrAddDefaultTransformState(Transform tf)
|
||||
{
|
||||
if (m_instance.DefaultTransformStates.TryGetValue(tf, out var defaultTransformState))
|
||||
{
|
||||
return defaultTransformState;
|
||||
}
|
||||
|
||||
Debug.LogWarning($"{tf.name} does not exist on load.");
|
||||
return new TransformState(null);
|
||||
}
|
||||
|
||||
private static BlittableColliderType TranslateColliderType(VRM10SpringBoneColliderTypes colliderType)
|
||||
{
|
||||
switch (colliderType)
|
||||
{
|
||||
case VRM10SpringBoneColliderTypes.Sphere:
|
||||
return BlittableColliderType.Sphere;
|
||||
case VRM10SpringBoneColliderTypes.Capsule:
|
||||
return BlittableColliderType.Capsule;
|
||||
case VRM10SpringBoneColliderTypes.Plane:
|
||||
return BlittableColliderType.Plane;
|
||||
case VRM10SpringBoneColliderTypes.SphereInside:
|
||||
return BlittableColliderType.SphereInside;
|
||||
case VRM10SpringBoneColliderTypes.CapsuleInside:
|
||||
return BlittableColliderType.CapsuleInside;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
m_building = false;
|
||||
}
|
||||
|
||||
public void RestoreInitialTransform()
|
||||
{
|
||||
// Spring の joint に対応する transform の回転を初期状態
|
||||
var instance = m_instance.GetComponent<RuntimeGltfInstance>();
|
||||
for (int i = 0; i < m_fastSpringBoneBuffer.Transforms.Length; ++i)
|
||||
{
|
||||
var transform = m_fastSpringBoneBuffer.Transforms[i];
|
||||
transform.localRotation = m_initialLocalRotations[i];
|
||||
transform.localRotation = instance.InitialTransformStates[transform].LocalRotation;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// TODO: jobs のバッファにも反映する必要あり
|
||||
}
|
||||
|
||||
public void Process()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using UniGLTF;
|
||||
using UniGLTF.Utils;
|
||||
using UnityEngine;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using UniGLTF.SpringBoneJobs.InputPorts;
|
||||
using UniGLTF.SpringBoneJobs;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
|
|
@ -18,11 +18,10 @@ namespace UniVRM10
|
|||
public class Vrm10FastSpringboneRuntimeStandalone : IVrm10SpringBoneRuntime
|
||||
{
|
||||
private Vrm10Instance m_instance;
|
||||
private FastSpringBoneSpring[] m_springs;
|
||||
private Quaternion[] m_initialLocalRotations;
|
||||
private FastSpringBoneBuffer m_fastSpringBoneBuffer;
|
||||
public FastSpringBoneBufferCombiner m_bufferCombiner = new();
|
||||
private FastSpringBoneScheduler m_fastSpringBoneScheduler;
|
||||
private bool m_building = false;
|
||||
|
||||
public Vector3 ExternalForce
|
||||
{
|
||||
|
|
@ -42,15 +41,15 @@ namespace UniVRM10
|
|||
m_fastSpringBoneScheduler = new(m_bufferCombiner);
|
||||
}
|
||||
|
||||
/// <param name="initialTransform">VRMの初期姿勢(T-Pose)状態。instanceがT-Poseから変化していても大丈夫</param>
|
||||
public void Initialize(Vrm10Instance instance)
|
||||
public async Task InitializeAsync(Vrm10Instance instance, IAwaitCaller awaitCaller)
|
||||
{
|
||||
m_instance = instance;
|
||||
|
||||
// NOTE: FastSpringBoneService は UnitTest などでは動作しない
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
ReconstructSpringBone();
|
||||
m_fastSpringBoneBuffer = await FastSpringBoneBufferFactory.ConstructSpringBoneAsync(awaitCaller, m_instance, m_fastSpringBoneBuffer);
|
||||
m_bufferCombiner.Register(m_fastSpringBoneBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -69,93 +68,39 @@ namespace UniVRM10
|
|||
/// </summary>
|
||||
public void ReconstructSpringBone()
|
||||
{
|
||||
// release
|
||||
if (m_building)
|
||||
{
|
||||
Debug.LogWarning("already building");
|
||||
return;
|
||||
}
|
||||
m_building = true;
|
||||
|
||||
// 登録解除
|
||||
if (m_fastSpringBoneBuffer != null)
|
||||
{
|
||||
m_bufferCombiner.Unregister(m_fastSpringBoneBuffer);
|
||||
m_fastSpringBoneBuffer.Dispose();
|
||||
}
|
||||
|
||||
// create(Spring情報の再収集。設定変更の反映)
|
||||
m_springs = m_instance.SpringBone.Springs.Select(spring => new FastSpringBoneSpring
|
||||
{
|
||||
center = spring.Center,
|
||||
colliders = spring.ColliderGroups
|
||||
.SelectMany(group => group.Colliders)
|
||||
.Select(collider => new FastSpringBoneCollider
|
||||
{
|
||||
Transform = collider.transform,
|
||||
Collider = new BlittableCollider
|
||||
{
|
||||
offset = collider.Offset,
|
||||
radius = collider.Radius,
|
||||
tailOrNormal = collider.TailOrNormal,
|
||||
colliderType = TranslateColliderType(collider.ColliderType)
|
||||
}
|
||||
}).ToArray(),
|
||||
joints = spring.Joints
|
||||
.Select(joint => new FastSpringBoneJoint
|
||||
{
|
||||
Transform = joint.transform,
|
||||
Joint = new BlittableJointMutable
|
||||
{
|
||||
radius = joint.m_jointRadius,
|
||||
dragForce = joint.m_dragForce,
|
||||
gravityDir = joint.m_gravityDir,
|
||||
gravityPower = joint.m_gravityPower,
|
||||
stiffnessForce = joint.m_stiffnessForce
|
||||
},
|
||||
DefaultLocalRotation = GetOrAddDefaultTransformState(joint.transform).LocalRotation,
|
||||
}).ToArray(),
|
||||
}).ToArray();
|
||||
// new ImmediateCaller() により即時実行して結果を得る。
|
||||
// スパイクは許容する。
|
||||
var task = FastSpringBoneBufferFactory.ConstructSpringBoneAsync(new ImmediateCaller(), m_instance, m_fastSpringBoneBuffer);
|
||||
m_fastSpringBoneBuffer = task.Result;
|
||||
|
||||
// DOTS buffer 構築
|
||||
m_fastSpringBoneBuffer = new FastSpringBoneBuffer(m_springs);
|
||||
// 登録
|
||||
m_bufferCombiner.Register(m_fastSpringBoneBuffer);
|
||||
// reset 用の初期状態の記録
|
||||
m_initialLocalRotations = m_fastSpringBoneBuffer.Transforms.Select(x => x.localRotation).ToArray();
|
||||
}
|
||||
|
||||
private TransformState GetOrAddDefaultTransformState(Transform tf)
|
||||
{
|
||||
if (m_instance.DefaultTransformStates.TryGetValue(tf, out var defaultTransformState))
|
||||
{
|
||||
return defaultTransformState;
|
||||
}
|
||||
|
||||
Debug.LogWarning($"{tf.name} does not exist on load.");
|
||||
return new TransformState(null);
|
||||
}
|
||||
|
||||
private static BlittableColliderType TranslateColliderType(VRM10SpringBoneColliderTypes colliderType)
|
||||
{
|
||||
switch (colliderType)
|
||||
{
|
||||
case VRM10SpringBoneColliderTypes.Sphere:
|
||||
return BlittableColliderType.Sphere;
|
||||
case VRM10SpringBoneColliderTypes.Capsule:
|
||||
return BlittableColliderType.Capsule;
|
||||
case VRM10SpringBoneColliderTypes.Plane:
|
||||
return BlittableColliderType.Plane;
|
||||
case VRM10SpringBoneColliderTypes.SphereInside:
|
||||
return BlittableColliderType.SphereInside;
|
||||
case VRM10SpringBoneColliderTypes.CapsuleInside:
|
||||
return BlittableColliderType.CapsuleInside;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public void RestoreInitialTransform()
|
||||
{
|
||||
// Spring の joint に対応する transform の回転を初期状態
|
||||
var instance = m_instance.GetComponent<RuntimeGltfInstance>();
|
||||
for (int i = 0; i < m_fastSpringBoneBuffer.Transforms.Length; ++i)
|
||||
{
|
||||
var transform = m_fastSpringBoneBuffer.Transforms[i];
|
||||
transform.localRotation = m_initialLocalRotations[i];
|
||||
transform.localRotation = instance.InitialTransformStates[transform].LocalRotation;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// TODO: jobs のバッファにも反映する必要あり
|
||||
}
|
||||
|
||||
public void Process()
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ namespace UniVRM10
|
|||
LookAt = new Vrm10RuntimeLookAt(instance.Vrm.LookAt, instance.Humanoid, ControlRig);
|
||||
Expression = new Vrm10RuntimeExpression(instance, LookAt.EyeDirectionApplicable);
|
||||
SpringBone = springBoneRuntime;
|
||||
SpringBone.Initialize(instance);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public interface IVrm10SpringBoneRuntime : IDisposable
|
||||
{
|
||||
public void Initialize(Vrm10Instance instance);
|
||||
public Task InitializeAsync(Vrm10Instance instance, IAwaitCaller awaitCaller);
|
||||
|
||||
/// <summary>
|
||||
/// 主に singleton のバッチング更新。
|
||||
|
|
|
|||
|
|
@ -273,6 +273,8 @@ namespace UniVRM10
|
|||
if (UniGLTF.Extensions.VRMC_springBone.GltfDeserializer.TryGet(Data.GLTF.extensions, out UniGLTF.Extensions.VRMC_springBone.VRMC_springBone springBone))
|
||||
{
|
||||
await LoadSpringBoneAsync(awaitCaller, controller, springBone);
|
||||
// Vrm10Runtime で初期化していたが async にするため、こちらに引越し `v0.127`
|
||||
await m_springboneRuntime.InitializeAsync(controller, awaitCaller);
|
||||
}
|
||||
// constraint
|
||||
await LoadConstraintAsync(awaitCaller, controller);
|
||||
|
|
|
|||
|
|
@ -6842,6 +6842,7 @@ MonoBehaviour:
|
|||
m_enableAutoBlink: {fileID: 634488422}
|
||||
m_enableAutoExpression: {fileID: 1767738855}
|
||||
m_useAsync: {fileID: 602093299}
|
||||
m_useSingelton: {fileID: 522109225}
|
||||
m_target: {fileID: 802105000}
|
||||
m_motion: {fileID: 4900000, guid: 08df5151e71aed748b13547492fb8b9a, type: 3}
|
||||
m_texts:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user