diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs index d55439841..587fc21d0 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs @@ -14,8 +14,8 @@ namespace UniVRM10 private readonly Vrm10Instance m_instance; private readonly IReadOnlyDictionary m_defaultTransformStates; private readonly FastSpringBoneService m_fastSpringBoneService; - - private FastSpringBoneBufferBuilder m_initialData; + private FastSpringBoneSpring[] m_springs; + private Quaternion[] m_initialLocalRotations; private FastSpringBoneBuffer m_fastSpringBoneBuffer; public Vector3 ExternalForce { @@ -73,7 +73,7 @@ namespace UniVRM10 } // create - var springs = m_instance.SpringBone.Springs.Select(spring => new FastSpringBoneSpring + m_springs = m_instance.SpringBone.Springs.Select(spring => new FastSpringBoneSpring { center = spring.Center, colliders = spring.ColliderGroups @@ -105,9 +105,9 @@ namespace UniVRM10 }).ToArray(), }).ToArray(); - m_initialData = new FastSpringBoneBufferBuilder(springs); - m_fastSpringBoneBuffer = new FastSpringBoneBuffer(m_initialData); + m_fastSpringBoneBuffer = new FastSpringBoneBuffer(m_springs); m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer); + m_initialLocalRotations = m_fastSpringBoneBuffer.Transforms.Select(x => x.localRotation).ToArray(); } private TransformState GetOrAddDefaultTransformState(Transform tf) @@ -143,21 +143,21 @@ namespace UniVRM10 public void RestoreInitialTransform() { // Spring の joint に対応する transform の回転を初期状態 - for (int i = 0; i < m_initialData.Transforms.Length; ++i) + for (int i = 0; i < m_fastSpringBoneBuffer.Transforms.Length; ++i) { - var transform = m_initialData.Transforms[i]; - transform.localRotation = m_initialData.InitialLocalRotations[i]; + var transform = m_fastSpringBoneBuffer.Transforms[i]; + transform.localRotation = m_initialLocalRotations[i]; } // 初期状態にしたtransformを使って spring logic を構築 - m_initialData.BlittableLogics.Clear(); - foreach (var spring in m_initialData.Springs) + List blittableLogics = new(); + foreach (var spring in m_springs) { - m_initialData.AddLogic(spring); + FastSpringBoneBuffer.AddLogic(m_fastSpringBoneBuffer.Transforms, blittableLogics, spring); } // DOTS バッファーを更新 - m_initialData.SyncAndZeroVelocity(m_fastSpringBoneBuffer.Logics); + m_fastSpringBoneBuffer.SyncAndZeroVelocity(blittableLogics); } } } \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs index 3ae2fcbc5..5e26d473d 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using UnityEngine; @@ -47,28 +49,148 @@ namespace UniVRM10.FastSpringBones.System IsSpringBoneEnabled = value, }; } - } - public unsafe FastSpringBoneBuffer(FastSpringBoneBufferBuilder b) + /// + /// Joint, Collider, Center の Transform のリスト + /// - 重複を除去 + /// + /// + /// + static Transform[] MakeFlattenTransformList(FastSpringBoneSpring[] springs) { - Profiler.BeginSample("FastSpringBone.ConstructBuffers.ConstructNativeArrays"); + var transformHashSet = new HashSet(); + foreach (var spring in springs) + { + foreach (var joint in spring.joints) + { + transformHashSet.Add(joint.Transform); + if (joint.Transform.parent != null) transformHashSet.Add(joint.Transform.parent); + } + + foreach (var collider in spring.colliders) + { + transformHashSet.Add(collider.Transform); + } + + if (spring.center != null) transformHashSet.Add(spring.center); + } + var Transforms = transformHashSet.ToArray(); + return Transforms; + } + + public unsafe FastSpringBoneBuffer(FastSpringBoneSpring[] springs) + { + Profiler.BeginSample("FastSpringBone.ConstructBuffers.BufferBuilder"); + Transforms = MakeFlattenTransformList(springs); _externalData = new NativeArray(1, Allocator.Persistent); _externalData[0] = new BlittableExternalData { ExternalForce = Vector3.zero, IsSpringBoneEnabled = true, }; - b.SetExternalDataPtr((BlittableExternalData*)_externalData.GetUnsafePtr()); - Springs = new NativeArray(b.BlittableSprings.ToArray(), Allocator.Persistent); - Joints = new NativeArray(b.BlittableJoints.ToArray(), Allocator.Persistent); - Colliders = new NativeArray(b.BlittableColliders.ToArray(), Allocator.Persistent); - Logics = new NativeArray(b.BlittableLogics.ToArray(), Allocator.Persistent); - BlittableTransforms = new NativeArray(b.Transforms.Length, Allocator.Persistent); - Transforms = b.Transforms; + + var externalDataPtr = (BlittableExternalData*)_externalData.GetUnsafePtr(); + List blittableSprings = new(); + List blittableJoints = new(); + List blittableColliders = new(); + List blittableLogics = new(); + foreach (var spring in springs) + { + var blittableSpring = new BlittableSpring + { + colliderSpan = new BlittableSpan + { + startIndex = blittableColliders.Count, + count = spring.colliders.Length, + }, + logicSpan = new BlittableSpan + { + startIndex = blittableJoints.Count, + count = spring.joints.Length - 1, + }, + centerTransformIndex = Array.IndexOf(Transforms, spring.center), + ExternalData = externalDataPtr, + }; + blittableSprings.Add(blittableSpring); + + blittableColliders.AddRange(spring.colliders.Select(collider => + { + var blittable = collider.Collider; + blittable.transformIndex = Array.IndexOf(Transforms, collider.Transform); + return blittable; + })); + blittableJoints.AddRange(spring.joints + .Take(spring.joints.Length - 1).Select(joint => + { + var blittable = joint.Joint; + return blittable; + })); + + AddLogic(Transforms, blittableLogics, spring); + } + + Springs = new NativeArray(blittableSprings.ToArray(), Allocator.Persistent); + Joints = new NativeArray(blittableJoints.ToArray(), Allocator.Persistent); + Colliders = new NativeArray(blittableColliders.ToArray(), Allocator.Persistent); + Logics = new NativeArray(blittableLogics.ToArray(), Allocator.Persistent); + BlittableTransforms = new NativeArray(Transforms.Length, Allocator.Persistent); Profiler.EndSample(); } + static public void AddLogic(Transform[] Transforms, List BlittableLogics, FastSpringBoneSpring spring) + { + for (var i = 0; i < spring.joints.Length - 1; ++i) + { + var joint = spring.joints[i]; + var tailJoint = i + 1 < spring.joints.Length ? spring.joints[i + 1] : (FastSpringBoneJoint?)null; + var parentJoint = i - 1 >= 0 ? spring.joints[i - 1] : (FastSpringBoneJoint?)null; + var localPosition = Vector3.zero; + if (tailJoint.HasValue) + { + localPosition = tailJoint.Value.Transform.localPosition; + } + else + { + if (parentJoint.HasValue) + { + var delta = joint.Transform.position - parentJoint.Value.Transform.position; + localPosition = + joint.Transform.worldToLocalMatrix.MultiplyPoint(joint.Transform.position + delta); + } + else + { + localPosition = Vector3.down; + } + } + + var scale = tailJoint.HasValue ? tailJoint.Value.Transform.lossyScale : joint.Transform.lossyScale; + var localChildPosition = new Vector3( + localPosition.x * scale.x, + localPosition.y * scale.y, + localPosition.z * scale.z + ); + + var worldChildPosition = joint.Transform.TransformPoint(localChildPosition); + var currentTail = spring.center != null + ? spring.center.InverseTransformPoint(worldChildPosition) + : worldChildPosition; + var parent = joint.Transform.parent; + + + BlittableLogics.Add(new BlittableLogic + { + headTransformIndex = Array.IndexOf(Transforms, joint.Transform), + parentTransformIndex = Array.IndexOf(Transforms, parent), + currentTail = currentTail, + prevTail = currentTail, + localRotation = joint.DefaultLocalRotation, + boneAxis = localChildPosition.normalized, + length = localChildPosition.magnitude + }); + } + } + public void Dispose() { if (IsDisposed) return; @@ -80,5 +202,16 @@ namespace UniVRM10.FastSpringBones.System Logics.Dispose(); _externalData.Dispose(); } + + public unsafe void SyncAndZeroVelocity(IReadOnlyList logics) + { + var dst = Logics; + for (int i = 0; i < logics.Count; ++i) + { + var l = logics[i]; + l.prevTail = l.currentTail; + dst[i] = l; + } + } } } \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs deleted file mode 100644 index 5d348d1aa..000000000 --- a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs +++ /dev/null @@ -1,161 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Unity.Collections; -using UnityEngine; -using UnityEngine.Profiling; -using UniVRM10.FastSpringBones.Blittables; - -namespace UniVRM10.FastSpringBones.System -{ - public class FastSpringBoneBufferBuilder - { - public readonly List BlittableSprings = new(); - public readonly List BlittableJoints = new(); - public readonly List BlittableColliders = new(); - public readonly List BlittableLogics = new(); - public readonly Transform[] Transforms; - public readonly Quaternion[] InitialLocalRotations; - public struct TransformInfo - { - public int Index; - public Quaternion InitialLocalRotation; - } - public readonly FastSpringBoneSpring[] Springs; - - public FastSpringBoneBufferBuilder(FastSpringBoneSpring[] springs) - { - Springs = springs; - Profiler.BeginSample("FastSpringBone.ConstructBuffers.BufferBuilder"); - var transformHashSet = new HashSet(); - foreach (var spring in springs) - { - foreach (var joint in spring.joints) - { - transformHashSet.Add(joint.Transform); - if (joint.Transform.parent != null) transformHashSet.Add(joint.Transform.parent); - } - - foreach (var collider in spring.colliders) - { - transformHashSet.Add(collider.Transform); - } - - if (spring.center != null) transformHashSet.Add(spring.center); - } - Transforms = transformHashSet.ToArray(); - InitialLocalRotations = Transforms.Select(x => x.localRotation).ToArray(); - - foreach (var spring in springs) - { - var blittableSpring = new BlittableSpring - { - colliderSpan = new BlittableSpan - { - startIndex = BlittableColliders.Count, - count = spring.colliders.Length, - }, - logicSpan = new BlittableSpan - { - startIndex = BlittableJoints.Count, - count = spring.joints.Length - 1, - }, - centerTransformIndex = Array.IndexOf(Transforms, spring.center), - }; - BlittableSprings.Add(blittableSpring); - - BlittableColliders.AddRange(spring.colliders.Select(collider => - { - var blittable = collider.Collider; - blittable.transformIndex = Array.IndexOf(Transforms, collider.Transform); - return blittable; - })); - BlittableJoints.AddRange(spring.joints - .Take(spring.joints.Length - 1).Select(joint => - { - var blittable = joint.Joint; - return blittable; - })); - - AddLogic(spring); - - } - Profiler.EndSample(); - } - - public void AddLogic(FastSpringBoneSpring spring) - { - for (var i = 0; i < spring.joints.Length - 1; ++i) - { - var joint = spring.joints[i]; - var tailJoint = i + 1 < spring.joints.Length ? spring.joints[i + 1] : (FastSpringBoneJoint?)null; - var parentJoint = i - 1 >= 0 ? spring.joints[i - 1] : (FastSpringBoneJoint?)null; - var localPosition = Vector3.zero; - if (tailJoint.HasValue) - { - localPosition = tailJoint.Value.Transform.localPosition; - } - else - { - if (parentJoint.HasValue) - { - var delta = joint.Transform.position - parentJoint.Value.Transform.position; - localPosition = - joint.Transform.worldToLocalMatrix.MultiplyPoint(joint.Transform.position + delta); - } - else - { - localPosition = Vector3.down; - } - } - - var scale = tailJoint.HasValue ? tailJoint.Value.Transform.lossyScale : joint.Transform.lossyScale; - var localChildPosition = new Vector3( - localPosition.x * scale.x, - localPosition.y * scale.y, - localPosition.z * scale.z - ); - - var worldChildPosition = joint.Transform.TransformPoint(localChildPosition); - var currentTail = spring.center != null - ? spring.center.InverseTransformPoint(worldChildPosition) - : worldChildPosition; - var parent = joint.Transform.parent; - BlittableLogics.Add(new BlittableLogic - { - headTransformIndex = Array.IndexOf(Transforms, joint.Transform), - parentTransformIndex = Array.IndexOf(Transforms, parent), - currentTail = currentTail, - prevTail = currentTail, - localRotation = joint.DefaultLocalRotation, - boneAxis = localChildPosition.normalized, - length = localChildPosition.magnitude - }); - } - } - - public unsafe void SetExternalDataPtr(BlittableExternalData* externalData) - { - for (int i = 0; i < BlittableSprings.Count; ++i) - { - // blittableSprings[i] = blittableSprings[i] with - // { - // ExternalData = externalData, - // }; - var b = BlittableSprings[i]; - b.ExternalData = externalData; - BlittableSprings[i] = b; - } - } - - public unsafe void SyncAndZeroVelocity(NativeArray logics) - { - for (int i = 0; i < BlittableLogics.Count; ++i) - { - var l = BlittableLogics[i]; - l.prevTail = l.currentTail; - logics[i] = BlittableLogics[i]; - } - } - } -} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs.meta deleted file mode 100644 index 29bea2967..000000000 --- a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 82dbc85cfa7168546b209a51f6342d84 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: