From e8017dcf8af4e6a23c5654ed0e2a96a2d47c4d77 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 12 Nov 2024 18:17:41 +0900 Subject: [PATCH 01/14] =?UTF-8?q?copy=20=E3=81=97=E3=81=A6=E3=81=8B?= =?UTF-8?q?=E3=82=89=20unity=20version=20=E6=9B=B4=E6=96=B0=E3=81=97?= =?UTF-8?q?=E3=81=A1=E3=82=83=E3=81=A3=E3=81=9F=E3=80=82=20unity=20version?= =?UTF-8?q?=20=E6=9B=B4=E6=96=B0=E3=81=97=E3=81=9F=E3=81=AE=E3=81=A1?= =?UTF-8?q?=E3=81=AB=20copy=20=E3=81=99=E3=82=8B=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E3=81=82=E3=82=8A=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assets\VRM\Editor\Format\VRMSampleCopy.cs:126 --- .../UniversalRenderPipelineAsset.asset | 47 +++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/Assets/VRM10/Samples~/URPSample/Settings/UniversalRenderPipelineAsset.asset b/Assets/VRM10/Samples~/URPSample/Settings/UniversalRenderPipelineAsset.asset index 09d0fb9187..de2f369ae2 100644 --- a/Assets/VRM10/Samples~/URPSample/Settings/UniversalRenderPipelineAsset.asset +++ b/Assets/VRM10/Samples~/URPSample/Settings/UniversalRenderPipelineAsset.asset @@ -12,8 +12,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3} m_Name: UniversalRenderPipelineAsset m_EditorClassIdentifier: - k_AssetVersion: 9 - k_AssetPreviousVersion: 9 + k_AssetVersion: 11 + k_AssetPreviousVersion: 11 m_RendererType: 1 m_RendererData: {fileID: 0} m_RendererDataList: @@ -23,13 +23,16 @@ MonoBehaviour: m_RequireOpaqueTexture: 0 m_OpaqueDownsampling: 1 m_SupportsTerrainHoles: 1 - m_StoreActionsOptimization: 0 m_SupportsHDR: 1 + m_HDRColorBufferPrecision: 0 m_MSAA: 4 m_RenderScale: 1 m_UpscalingFilter: 0 m_FsrOverrideSharpness: 0 m_FsrSharpness: 0.92 + m_EnableLODCrossFade: 1 + m_LODCrossFadeDitheringType: 1 + m_ShEvalMode: 0 m_MainLightRenderingMode: 1 m_MainLightShadowsSupported: 1 m_MainLightShadowmapResolution: 2048 @@ -54,22 +57,58 @@ MonoBehaviour: m_SoftShadowsSupported: 1 m_ConservativeEnclosingSphere: 0 m_NumIterationsEnclosingSphere: 64 + m_SoftShadowQuality: 2 m_AdditionalLightsCookieResolution: 2048 m_AdditionalLightsCookieFormat: 3 m_UseSRPBatcher: 1 m_SupportsDynamicBatching: 0 m_MixedLightingSupported: 1 + m_SupportsLightCookies: 1 m_SupportsLightLayers: 0 m_DebugLevel: 0 + m_StoreActionsOptimization: 0 + m_EnableRenderGraph: 0 m_UseAdaptivePerformance: 1 m_ColorGradingMode: 0 m_ColorGradingLutSize: 32 m_UseFastSRGBLinearConversion: 0 + m_SupportDataDrivenLensFlare: 1 m_ShadowType: 1 m_LocalShadowsSupported: 0 m_LocalShadowsAtlasResolution: 256 m_MaxPixelLights: 0 m_ShadowAtlasResolution: 256 - m_ShaderVariantLogLevel: 0 m_VolumeFrameworkUpdateMode: 0 + m_Textures: + blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} + bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} + m_PrefilteringModeMainLightShadows: 1 + m_PrefilteringModeAdditionalLight: 4 + m_PrefilteringModeAdditionalLightShadows: 1 + m_PrefilterXRKeywords: 0 + m_PrefilteringModeForwardPlus: 1 + m_PrefilteringModeDeferredRendering: 1 + m_PrefilteringModeScreenSpaceOcclusion: 1 + m_PrefilterDebugKeywords: 0 + m_PrefilterWriteRenderingLayers: 0 + m_PrefilterHDROutput: 0 + m_PrefilterSSAODepthNormals: 0 + m_PrefilterSSAOSourceDepthLow: 0 + m_PrefilterSSAOSourceDepthMedium: 0 + m_PrefilterSSAOSourceDepthHigh: 0 + m_PrefilterSSAOInterleaved: 0 + m_PrefilterSSAOBlueNoise: 0 + m_PrefilterSSAOSampleCountLow: 0 + m_PrefilterSSAOSampleCountMedium: 0 + m_PrefilterSSAOSampleCountHigh: 0 + m_PrefilterDBufferMRT1: 0 + m_PrefilterDBufferMRT2: 0 + m_PrefilterDBufferMRT3: 0 + m_PrefilterSoftShadowsQualityLow: 0 + m_PrefilterSoftShadowsQualityMedium: 0 + m_PrefilterSoftShadowsQualityHigh: 0 + m_PrefilterSoftShadows: 0 + m_PrefilterScreenCoord: 0 + m_PrefilterNativeRenderPass: 0 + m_ShaderVariantLogLevel: 0 m_ShadowCascades: 0 From 270fbae1ac5896fe44f79f654e844f5933443a24 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 18 Nov 2024 14:05:28 +0900 Subject: [PATCH 02/14] avoid runtime exception. editor warning --- .../Editor/SpringBone/VRMSpringBoneEditor.cs | 60 +++++++++++++++++-- .../SpringBone/Logic/SpringBoneSystem.cs | 5 +- .../VRM/Runtime/SpringBone/VRMSpringBone.cs | 2 +- 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/Assets/VRM/Editor/SpringBone/VRMSpringBoneEditor.cs b/Assets/VRM/Editor/SpringBone/VRMSpringBoneEditor.cs index 68e2027fc6..c591ee6721 100644 --- a/Assets/VRM/Editor/SpringBone/VRMSpringBoneEditor.cs +++ b/Assets/VRM/Editor/SpringBone/VRMSpringBoneEditor.cs @@ -1,3 +1,6 @@ +using System.Collections.Generic; +using System.Linq; +using UniGLTF; using UnityEditor; using UnityEngine; @@ -9,6 +12,7 @@ class VRMSpringBoneEditor : Editor { private VRMSpringBone m_target; + private SerializedProperty m_script; private SerializedProperty m_commentProp; private SerializedProperty m_gizmoColorProp; private SerializedProperty m_stiffnessForceProp; @@ -21,6 +25,39 @@ class VRMSpringBoneEditor : Editor private SerializedProperty m_colliderGroupsProp; private SerializedProperty m_updateTypeProp; + void OnValidate() + { + if (Validate().Any()) + { + m_target.m_gizmoColor = Color.magenta; + } + } + + Dictionary m_rootCount = new(); + + IEnumerable Validate() + { + m_rootCount.Clear(); + foreach (var root in m_target.RootBones) + { + if (m_rootCount.TryGetValue(root, out var count)) + { + m_rootCount[root] = count + 1; + } + else + { + m_rootCount.Add(root, 1); + } + } + foreach (var (k, v) in m_rootCount) + { + if (v > 1) + { + yield return Validation.Error($"Duplicate rootBone: {k} => {v}"); + } + } + } + void OnEnable() { if (target == null) @@ -29,8 +66,9 @@ void OnEnable() } m_target = (VRMSpringBone)target; + m_script = serializedObject.FindProperty("m_Script"); m_commentProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_comment)); - m_gizmoColorProp = serializedObject.FindProperty("m_gizmoColor"); + m_gizmoColorProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_gizmoColor)); m_stiffnessForceProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_stiffnessForce)); m_gravityPowerProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_gravityPower)); m_gravityDirProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_gravityDir)); @@ -46,28 +84,38 @@ public override void OnInspectorGUI() { serializedObject.Update(); + // header + using (new EditorGUI.DisabledScope(true)) + { + EditorGUILayout.PropertyField(m_script); + } EditorGUILayout.PropertyField(m_commentProp); EditorGUILayout.PropertyField(m_gizmoColorProp); - EditorGUILayout.Space(); + foreach (var validation in Validate()) + { + validation.DrawGUI(); + } + // settings EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel); - LimitBreakSlider(m_stiffnessForceProp, 0.0f, 4.0f, 0.0f, Mathf.Infinity); LimitBreakSlider(m_gravityPowerProp, 0.0f, 2.0f, 0.0f, Mathf.Infinity); EditorGUILayout.PropertyField(m_gravityDirProp); EditorGUILayout.PropertyField(m_dragForceProp); EditorGUILayout.PropertyField(m_centerProp); EditorGUILayout.PropertyField(m_rootBonesProp); - EditorGUILayout.Space(); + // collision EditorGUILayout.LabelField("Collision", EditorStyles.boldLabel); - LimitBreakSlider(m_hitRadiusProp, 0.0f, 0.5f, 0.0f, Mathf.Infinity); EditorGUILayout.PropertyField(m_colliderGroupsProp); - EditorGUILayout.PropertyField(m_updateTypeProp); + EditorGUILayout.Space(); + // runtime + EditorGUILayout.LabelField("Runtime", EditorStyles.boldLabel); + EditorGUILayout.PropertyField(m_updateTypeProp); serializedObject.ApplyModifiedProperties(); } diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs index a44091bf1a..a30ca03f2c 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs @@ -38,7 +38,10 @@ public void Setup(SceneInfo scene, bool force) for (int i = 0; i < m_joints.Count; ++i) { - m_jointIndexMap.Add(m_joints[i].Item1, i); + if (!m_jointIndexMap.ContainsKey(m_joints[i].Item1)) + { + m_jointIndexMap.Add(m_joints[i].Item1, i); + } } } diff --git a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs index 2d8b5f8599..f173cbd321 100644 --- a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs +++ b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs @@ -12,7 +12,7 @@ namespace VRM public sealed class VRMSpringBone : MonoBehaviour { [SerializeField] public string m_comment; - [SerializeField] private Color m_gizmoColor = Color.yellow; + [SerializeField] public Color m_gizmoColor = Color.yellow; [SerializeField] public float m_stiffnessForce = 1.0f; [SerializeField] public float m_gravityPower; [SerializeField] public Vector3 m_gravityDir = new Vector3(0, -1.0f, 0); From ddf438edf7288b221d68daba6cd515557879262d Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 18 Nov 2024 14:15:22 +0900 Subject: [PATCH 03/14] RootBonesNonNullUnique --- .../Runtime/SpringBone/Logic/SpringBoneSystem.cs | 5 +---- Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs | 13 ++++++++++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs index a30ca03f2c..a44091bf1a 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs @@ -38,10 +38,7 @@ public void Setup(SceneInfo scene, bool force) for (int i = 0; i < m_joints.Count; ++i) { - if (!m_jointIndexMap.ContainsKey(m_joints[i].Item1)) - { - m_jointIndexMap.Add(m_joints[i].Item1, i); - } + m_jointIndexMap.Add(m_joints[i].Item1, i); } } diff --git a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs index f173cbd321..30c74ea7ac 100644 --- a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs +++ b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using UnityEngine; namespace VRM @@ -47,6 +48,16 @@ public enum SpringBoneUpdateType } [SerializeField] public SpringBoneUpdateType m_updateType = SpringBoneUpdateType.LateUpdate; + List m_rootBonesNonNullUnique = new(); + List RootBonesNonNullUnique + { + get + { + m_rootBonesNonNullUnique.Clear(); + m_rootBonesNonNullUnique.AddRange(RootBones.Where(x => x != null).Distinct()); + return m_rootBonesNonNullUnique; + } + } SpringBone.SpringBoneSystem m_system = new(); void Awake() @@ -55,7 +66,7 @@ void Awake() } SpringBone.SceneInfo Scene => new( - rootBones: RootBones, + rootBones: RootBonesNonNullUnique, center: m_center, colliderGroups: ColliderGroups, externalForce: ExternalForce); From 84b64c0be28d37a189a648c2ab9a497007ef6ed4 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 18 Nov 2024 16:30:16 +0900 Subject: [PATCH 04/14] use spring.transformIndexOffset --- .../FastSpringBoneBufferCombiner.cs | 4 - .../FastSpringBoneConbinedBuffer.cs | 93 ++++++++++--------- .../InputPorts/FastSpringBoneBuffer.cs | 12 --- .../FastSpringBoneBufferFactory.cs | 3 +- 4 files changed, 49 insertions(+), 63 deletions(-) diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs index cc4a9da2d2..016cbcd96e 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs @@ -60,10 +60,6 @@ private JobHandle ReconstructBuffers(JobHandle handle) Profiler.BeginSample("FastSpringBone.ReconstructBuffers.DisposeBuffers"); if (_combinedBuffer is FastSpringBoneCombinedBuffer combined) { - Profiler.BeginSample("FastSpringBone.ReconstructBuffers.SaveToSourceBuffer"); - combined.SaveToSourceBuffer(); - Profiler.EndSample(); - // TODO: Dispose せずに再利用? combined.Dispose(); } diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs index d6bd83c054..34410ece7f 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs @@ -97,7 +97,7 @@ internal static JobHandle Create(JobHandle handle, springsCount += buffer.Springs.Length; collidersCount += buffer.Colliders.Length; logicsCount += buffer.Logics.Length; - transformsCount += buffer.BlittableTransforms.Length; + transformsCount += buffer.Transforms.Length; } Profiler.EndSample(); @@ -112,6 +112,23 @@ internal static JobHandle Create(JobHandle handle, private JobHandle Batching(JobHandle handle) { + // TransformAccessArrayの構築 + Profiler.BeginSample("FastSpringBone.ReconstructBuffers.LoadTransformAccessArray"); + var transforms = new Transform[_transforms.Length]; + var transformAccessArrayOffset = 0; + foreach (var buffer in _batchedBuffers) + { + Array.Copy(buffer.Transforms, 0, transforms, transformAccessArrayOffset, buffer.Transforms.Length); + transformAccessArrayOffset += buffer.Transforms.Length; + } + _transformAccessArray = new TransformAccessArray(transforms); + Profiler.EndSample(); + + handle = new PullTransformJob + { + Transforms = Transforms + }.Schedule(TransformAccessArray, handle); + Profiler.BeginSample("FastSpringBone.ReconstructBuffers.ScheduleLoadBufferJobs"); var springsOffset = 0; var collidersOffset = 0; @@ -129,14 +146,6 @@ private JobHandle Batching(JobHandle handle) _jointMap.Add(buffer.Transforms[head], logicsOffset + j); } - // バッファの読み込みをスケジュール - handle = new LoadTransformsJob - { - SrcTransforms = buffer.BlittableTransforms, - DestTransforms = new NativeSlice(_transforms, transformOffset, - buffer.BlittableTransforms.Length) - }.Schedule(buffer.BlittableTransforms.Length, 1, handle); - handle = new LoadSpringsJob { ModelIndex = i, @@ -165,26 +174,9 @@ private JobHandle Batching(JobHandle handle) springsOffset += buffer.Springs.Length; collidersOffset += buffer.Colliders.Length; logicsOffset += buffer.Logics.Length; - transformOffset += buffer.BlittableTransforms.Length; + transformOffset += buffer.Transforms.Length; } - handle = InitCurrentTails(handle); - - // TransformAccessArrayの構築と並行してJobを行うため、この時点で走らせておく - JobHandle.ScheduleBatchedJobs(); - Profiler.EndSample(); - - // TransformAccessArrayの構築 - Profiler.BeginSample("FastSpringBone.ReconstructBuffers.LoadTransformAccessArray"); - var transforms = new Transform[_transforms.Length]; - var transformAccessArrayOffset = 0; - foreach (var buffer in _batchedBuffers) - { - Array.Copy(buffer.Transforms, 0, transforms, transformAccessArrayOffset, buffer.Transforms.Length); - transformAccessArrayOffset += buffer.BlittableTransforms.Length; - } - - _transformAccessArray = new TransformAccessArray(transforms); Profiler.EndSample(); return handle; @@ -328,29 +320,36 @@ public void Execute(int index) #endif private struct InitCurrentTailsJob : IJobParallelFor { + [ReadOnly] public NativeArray Springs; + [ReadOnly] public NativeArray Logics; [ReadOnly] public NativeArray Transforms; - [WriteOnly] public NativeSlice CurrentTails; - [WriteOnly] public NativeSlice PrevTails; - [WriteOnly] public NativeSlice NextTails; + [NativeDisableParallelForRestriction] public NativeSlice CurrentTails; + [NativeDisableParallelForRestriction] public NativeSlice PrevTails; + [NativeDisableParallelForRestriction] public NativeSlice NextTails; - public void Execute(int jointIndex) + public void Execute(int springIndex) { - var tailIndex = Logics[jointIndex].tailTransformIndex; - if (tailIndex == -1) + var spring = Springs[springIndex]; + for (int jointIndex = spring.logicSpan.startIndex; jointIndex < spring.logicSpan.EndIndex; ++jointIndex) { - // tail 無い - var tail = Transforms[Logics[jointIndex].headTransformIndex]; - CurrentTails[jointIndex] = tail.position; - PrevTails[jointIndex] = tail.position; - NextTails[jointIndex] = tail.position; - } - else - { - var tail = Transforms[tailIndex]; - CurrentTails[jointIndex] = tail.position; - PrevTails[jointIndex] = tail.position; - NextTails[jointIndex] = tail.position; + var tailIndex = Logics[jointIndex].tailTransformIndex; + if (tailIndex == -1) + { + // tail 無い + var index = springIndex + Logics[jointIndex].headTransformIndex; + var tail = Transforms[index]; + CurrentTails[jointIndex] = tail.position; + PrevTails[jointIndex] = tail.position; + NextTails[jointIndex] = tail.position; + } + else + { + var tail = Transforms[spring.transformIndexOffset + tailIndex]; + CurrentTails[jointIndex] = tail.position; + PrevTails[jointIndex] = tail.position; + NextTails[jointIndex] = tail.position; + } } } } @@ -365,12 +364,14 @@ public JobHandle InitCurrentTails(JobHandle handle) { return new InitCurrentTailsJob { + Springs = Springs, + Logics = Logics, Transforms = Transforms, CurrentTails = CurrentTails, PrevTails = PrevTails, NextTails = NextTails, - }.Schedule(Logics.Length, 1, handle); + }.Schedule(Springs.Length, 1, handle); } public void InitializeJointsLocalRotation(FastSpringBoneBuffer buffer) diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs index 9e9887176f..07c0de7414 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs @@ -22,7 +22,6 @@ public class FastSpringBoneBuffer : IDisposable public NativeArray Joints { get; } public NativeArray Colliders { get; } public NativeArray Logics { get; } - public NativeArray BlittableTransforms { get; } public Transform[] Transforms { get; } public bool IsDisposed { get; private set; } @@ -103,16 +102,6 @@ public FastSpringBoneBuffer(Transform model, FastSpringBoneSpring[] springs) 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.Select(transform => new BlittableTransform - { - position = transform.position, - rotation = transform.rotation, - localPosition = transform.localPosition, - localRotation = transform.localRotation, - localScale = transform.localScale, - localToWorldMatrix = transform.localToWorldMatrix, - worldToLocalMatrix = transform.worldToLocalMatrix - }).ToArray(), Allocator.Persistent); Profiler.EndSample(); } @@ -157,7 +146,6 @@ public void Dispose() IsDisposed = true; Springs.Dispose(); Joints.Dispose(); - BlittableTransforms.Dispose(); Colliders.Dispose(); Logics.Dispose(); } diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/FastSpringBoneBufferFactory.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/FastSpringBoneBufferFactory.cs index a6a03f23cf..c84f58de09 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/FastSpringBoneBufferFactory.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/FastSpringBoneBufferFactory.cs @@ -26,6 +26,7 @@ public static async Task ConstructSpringBoneAsync(IAwaitCa if (fastSpringBoneBuffer != null) { fastSpringBoneBuffer.Dispose(); + fastSpringBoneBuffer = null; } Func GetOrAddDefaultTransformState = (Transform tf) => @@ -41,7 +42,7 @@ public static async Task ConstructSpringBoneAsync(IAwaitCa // create(Spring情報の再収集。設定変更の反映) var springs = vrm.SpringBone.Springs.Select(spring => new FastSpringBoneSpring - { + { center = spring.Center, colliders = spring.ColliderGroups .SelectMany(group => group.Colliders) From 8e259e20dd6898f94355a2bbcbe22406733df420 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 18 Nov 2024 16:38:17 +0900 Subject: [PATCH 05/14] comment --- .../Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs index 34410ece7f..e067c07d4f 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs @@ -124,6 +124,7 @@ private JobHandle Batching(JobHandle handle) _transformAccessArray = new TransformAccessArray(transforms); Profiler.EndSample(); + // Transforms を更新。後続の InitCurrentTails で使う handle = new PullTransformJob { Transforms = Transforms @@ -176,6 +177,10 @@ private JobHandle Batching(JobHandle handle) logicsOffset += buffer.Logics.Length; transformOffset += buffer.Transforms.Length; } + + // verlet の current, prev, next のバッファを今の transform の状態にする。 + // 速度は 0 にクリアする。 + // TODO: 速度の維持は SaveToSourceBuffer でされていたのだがデータ構造変更で場所が変わった handle = InitCurrentTails(handle); Profiler.EndSample(); @@ -345,7 +350,7 @@ public void Execute(int springIndex) } else { - var tail = Transforms[spring.transformIndexOffset + tailIndex]; + var tail = Transforms[spring.transformIndexOffset + tailIndex]; CurrentTails[jointIndex] = tail.position; PrevTails[jointIndex] = tail.position; NextTails[jointIndex] = tail.position; From a8bd641bae98fa9c33c6378508a01da7ab13f05f Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 18 Nov 2024 16:44:15 +0900 Subject: [PATCH 06/14] fix tailIndex --- .../FastSpringBoneConbinedBuffer.cs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs index e067c07d4f..c126c5e952 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs @@ -338,23 +338,21 @@ public void Execute(int springIndex) var spring = Springs[springIndex]; for (int jointIndex = spring.logicSpan.startIndex; jointIndex < spring.logicSpan.EndIndex; ++jointIndex) { - var tailIndex = Logics[jointIndex].tailTransformIndex; - if (tailIndex == -1) + int tailIndex; + if (Logics[jointIndex].tailTransformIndex == -1) { // tail 無い - var index = springIndex + Logics[jointIndex].headTransformIndex; - var tail = Transforms[index]; - CurrentTails[jointIndex] = tail.position; - PrevTails[jointIndex] = tail.position; - NextTails[jointIndex] = tail.position; + tailIndex = spring.transformIndexOffset + Logics[jointIndex].headTransformIndex; } else { - var tail = Transforms[spring.transformIndexOffset + tailIndex]; - CurrentTails[jointIndex] = tail.position; - PrevTails[jointIndex] = tail.position; - NextTails[jointIndex] = tail.position; + tailIndex= spring.transformIndexOffset + Logics[jointIndex].tailTransformIndex; } + + var tail = Transforms[tailIndex]; + CurrentTails[jointIndex] = tail.position; + PrevTails[jointIndex] = tail.position; + NextTails[jointIndex] = tail.position; } } } From 32e004d821dbc3c470d435b43bcf784fc334639f Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 19 Nov 2024 01:50:05 +0900 Subject: [PATCH 07/14] Editor.OnValidate not work --- .../Editor/SpringBone/VRMSpringBoneEditor.cs | 31 ++++++++++++------- .../VRM/Runtime/SpringBone/VRMSpringBone.cs | 2 +- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Assets/VRM/Editor/SpringBone/VRMSpringBoneEditor.cs b/Assets/VRM/Editor/SpringBone/VRMSpringBoneEditor.cs index c591ee6721..5a870b0065 100644 --- a/Assets/VRM/Editor/SpringBone/VRMSpringBoneEditor.cs +++ b/Assets/VRM/Editor/SpringBone/VRMSpringBoneEditor.cs @@ -25,18 +25,12 @@ class VRMSpringBoneEditor : Editor private SerializedProperty m_colliderGroupsProp; private SerializedProperty m_updateTypeProp; - void OnValidate() - { - if (Validate().Any()) - { - m_target.m_gizmoColor = Color.magenta; - } - } - Dictionary m_rootCount = new(); + List m_validation = new(); IEnumerable Validate() { + m_validation.Clear(); m_rootCount.Clear(); foreach (var root in m_target.RootBones) { @@ -53,9 +47,10 @@ IEnumerable Validate() { if (v > 1) { - yield return Validation.Error($"Duplicate rootBone: {k} => {v}"); + m_validation.Add(Validation.Error($"Duplicate rootBone: {k} => {v}", ValidationContext.Create(k))); } } + return m_validation; } void OnEnable() @@ -68,7 +63,7 @@ void OnEnable() m_script = serializedObject.FindProperty("m_Script"); m_commentProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_comment)); - m_gizmoColorProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_gizmoColor)); + m_gizmoColorProp = serializedObject.FindProperty("m_gizmoColor"); m_stiffnessForceProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_stiffnessForce)); m_gravityPowerProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_gravityPower)); m_gravityDirProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_gravityDir)); @@ -78,6 +73,20 @@ void OnEnable() m_hitRadiusProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_hitRadius)); m_colliderGroupsProp = serializedObject.FindProperty(nameof(VRMSpringBone.ColliderGroups)); m_updateTypeProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_updateType)); + + Validate(); + } + + public void OnSceneGUI() + { + foreach (var valiation in m_validation) + { + var t = (Transform)valiation.Context.Context; + if (t != null) + { + Handles.Label(t.position, "duplicate rootBone !"); + } + } } public override void OnInspectorGUI() @@ -92,7 +101,7 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(m_commentProp); EditorGUILayout.PropertyField(m_gizmoColorProp); EditorGUILayout.Space(); - foreach (var validation in Validate()) + foreach (var validation in m_validation) { validation.DrawGUI(); } diff --git a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs index 30c74ea7ac..75ed5f9506 100644 --- a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs +++ b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs @@ -13,7 +13,7 @@ namespace VRM public sealed class VRMSpringBone : MonoBehaviour { [SerializeField] public string m_comment; - [SerializeField] public Color m_gizmoColor = Color.yellow; + [SerializeField] private Color m_gizmoColor = Color.yellow; [SerializeField] public float m_stiffnessForce = 1.0f; [SerializeField] public float m_gravityPower; [SerializeField] public Vector3 m_gravityDir = new Vector3(0, -1.0f, 0); From a78bf20884a5388492d3d2b4c03544a19611719e Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 19 Nov 2024 03:14:10 +0900 Subject: [PATCH 08/14] =?UTF-8?q?FastSpringBoneBuffer.=5FcurrentTailsBacku?= =?UTF-8?q?p=20=E3=81=A7=E3=83=90=E3=83=83=E3=82=AF=E3=82=A2=E3=83=83?= =?UTF-8?q?=E3=83=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FastSpringBoneBufferCombiner.cs | 23 ++++++- .../FastSpringBoneConbinedBuffer.cs | 69 ++++++------------- .../InputPorts/FastSpringBoneBuffer.cs | 35 ++++++++++ 3 files changed, 76 insertions(+), 51 deletions(-) diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs index 016cbcd96e..813d8ae900 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs @@ -4,6 +4,7 @@ using UnityEngine.Profiling; using UniGLTF.SpringBoneJobs.InputPorts; using UnityEngine; +using Unity.Collections; namespace UniGLTF.SpringBoneJobs { @@ -29,9 +30,27 @@ public void Register(FastSpringBoneBuffer buffer) _isDirty = true; } - public void Unregister(FastSpringBoneBuffer buffer) + public void Unregister(FastSpringBoneBuffer remove) { - _buffers.Remove(buffer); + // index が変わる前に シミュレーションの状態を保存する。 + // 状態の保存場所が BlittableJoint から CurrentTails に移動しているのでここでやる。 + if (_combinedBuffer is FastSpringBoneCombinedBuffer combined) + { + var logicsIndex = 0; + foreach (var buffer in _buffers) + { + if (buffer == remove) + { + // 削除するので skip + // joint の位置が変わる可能性があるので状態を保存せずに速度を0にする方がよい + continue; + } + buffer.BackupCurrentTails(combined.CurrentTails, logicsIndex); + logicsIndex += buffer.Logics.Length; + } + } + + _buffers.Remove(remove); _isDirty = true; } diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs index c126c5e952..2e4c578ea0 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs @@ -147,6 +147,9 @@ private JobHandle Batching(JobHandle handle) _jointMap.Add(buffer.Transforms[head], logicsOffset + j); } + // 速度の維持 + buffer.RestoreCurrentTails(_currentTails, logicsOffset); + handle = new LoadSpringsJob { ModelIndex = i, @@ -205,25 +208,6 @@ public void Dispose() if (_transformAccessArray.isCreated) _transformAccessArray.Dispose(); } - /// - /// バッチングされたバッファから、個々のバッファへと値を戻す - /// Logics to _batchedBuffers[].Logics - /// バッファの再構築前にこの処理を行わないと、揺れの状態がリセットされてしまい、不自然な挙動になる - /// - internal void SaveToSourceBuffer() - { - var logicsIndex = 0; - for (var i = 0; i < _batchedBuffers.Length; ++i) - { - var length = _batchedBufferLogicSizes[i]; - if (!_batchedBuffers[i].IsDisposed && length > 0) - { - NativeArray.Copy(Logics, logicsIndex, _batchedBuffers[i].Logics, 0, length); - } - logicsIndex += length; - } - } - public void FlipBuffer() { var tmp = _prevTails; @@ -248,23 +232,6 @@ public void SetModelLevel(Transform model, BlittableModelLevel modelSetting) } } -#if ENABLE_SPRINGBONE_BURST - [BurstCompile] -#endif - /// - /// - /// - private struct LoadTransformsJob : IJobParallelFor - { - [ReadOnly] public NativeArray SrcTransforms; - [WriteOnly] public NativeSlice DestTransforms; - - public void Execute(int index) - { - DestTransforms[index] = SrcTransforms[index]; - } - } - #if ENABLE_SPRINGBONE_BURST [BurstCompile] #endif @@ -338,21 +305,25 @@ public void Execute(int springIndex) var spring = Springs[springIndex]; for (int jointIndex = spring.logicSpan.startIndex; jointIndex < spring.logicSpan.EndIndex; ++jointIndex) { - int tailIndex; - if (Logics[jointIndex].tailTransformIndex == -1) + if (float.IsNaN(CurrentTails[jointIndex].x)) { - // tail 無い - tailIndex = spring.transformIndexOffset + Logics[jointIndex].headTransformIndex; - } - else - { - tailIndex= spring.transformIndexOffset + Logics[jointIndex].tailTransformIndex; - } + // Transsform の現状を使う。velocity を zero にする + int tailIndex; + if (Logics[jointIndex].tailTransformIndex == -1) + { + // tail 無い + tailIndex = spring.transformIndexOffset + Logics[jointIndex].headTransformIndex; + } + else + { + tailIndex = spring.transformIndexOffset + Logics[jointIndex].tailTransformIndex; + } - var tail = Transforms[tailIndex]; - CurrentTails[jointIndex] = tail.position; - PrevTails[jointIndex] = tail.position; - NextTails[jointIndex] = tail.position; + var tail = Transforms[tailIndex]; + CurrentTails[jointIndex] = tail.position; + PrevTails[jointIndex] = tail.position; + NextTails[jointIndex] = tail.position; + } } } } diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs index 07c0de7414..c1bf55ffb2 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs @@ -22,6 +22,7 @@ public class FastSpringBoneBuffer : IDisposable public NativeArray Joints { get; } public NativeArray Colliders { get; } public NativeArray Logics { get; } + private NativeArray _currentTailsBackup; public Transform[] Transforms { get; } public bool IsDisposed { get; private set; } @@ -140,6 +141,40 @@ public static IEnumerable LogicFromTransform(Transform[ } } + public void BackupCurrentTails(NativeArray currentTails, int offset) + { + if (!IsDisposed) + { + return; + } + if (Logics.Length == 0) + { + return; + } + if (!_currentTailsBackup.IsCreated) + { + _currentTailsBackup = new(Logics.Length, Allocator.Persistent); + } + NativeArray.Copy(currentTails, offset, _currentTailsBackup, 0, Logics.Length); + } + + public void RestoreCurrentTails(NativeArray currentTails, int offset) + { + if (_currentTailsBackup.IsCreated) + { + NativeArray.Copy(_currentTailsBackup, 0, currentTails, offset, Logics.Length); + } + else + { + var end = offset + Logics.Length; + for (int i = offset; i < end; ++i) + { + // mark velocity zero + currentTails.GetSubArray(offset, Logics.Length).AsSpan().Fill(new Vector3(float.NaN, float.NaN, float.NaN)); + } + } + } + public void Dispose() { if (IsDisposed) return; From e85d332e5650b4c364ad737e7bf0acf8cbfacb55 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 19 Nov 2024 03:41:07 +0900 Subject: [PATCH 09/14] fix gizmo and assert --- .../FastSpringBoneConbinedBuffer.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs index 2e4c578ea0..0e597b70d3 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs @@ -354,9 +354,9 @@ public void InitializeJointsLocalRotation(FastSpringBoneBuffer buffer) for (var i = 0; i < _batchedBuffers.Length; ++i) { var length = _batchedBufferLogicSizes[i]; - Debug.Assert(length == buffer.Logics.Length); if (_batchedBuffers[i] == buffer) { + Debug.Assert(length == buffer.Logics.Length); for (var j = 0; j < length; ++j) { var logic = buffer.Logics[j]; @@ -376,22 +376,23 @@ public void InitializeJointsLocalRotation(FastSpringBoneBuffer buffer) public void DrawGizmos() { - foreach (var collider in _colliders) - { - collider.DrawGizmo(_transforms[collider.transformIndex]); - } - foreach (var spring in _springs) { + for (int i = spring.colliderSpan.startIndex; i < spring.colliderSpan.EndIndex; ++i) + { + var collider = _colliders[i]; + collider.DrawGizmo(_transforms[spring.transformIndexOffset + collider.transformIndex]); + } + for (int i = spring.logicSpan.startIndex; i < spring.logicSpan.EndIndex; ++i) { var joint = _logics[i]; - joint.DrawGizmo(_transforms[joint.tailTransformIndex], _joints[i]); + joint.DrawGizmo(_transforms[spring.transformIndexOffset + joint.tailTransformIndex], _joints[i]); Gizmos.matrix = Matrix4x4.identity; Gizmos.DrawLine( - _transforms[joint.tailTransformIndex].position, - _transforms[joint.headTransformIndex].position); + _transforms[spring.transformIndexOffset + joint.tailTransformIndex].position, + _transforms[spring.transformIndexOffset + joint.headTransformIndex].position); } } } From 5bda6740ff077b6d49c340597b46be82eb16e7dd Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 19 Nov 2024 03:53:34 +0900 Subject: [PATCH 10/14] =?UTF-8?q?buffer.BackupCurrentTails=20=E3=82=92=20b?= =?UTF-8?q?uffer=20=E5=A2=97=E6=B8=9B=E3=81=AE=E7=9B=B4=E5=89=8D=E3=81=AB?= =?UTF-8?q?=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FastSpringBoneBufferCombiner.cs | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs index 813d8ae900..a43d5b4399 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs @@ -5,6 +5,7 @@ using UniGLTF.SpringBoneJobs.InputPorts; using UnityEngine; using Unity.Collections; +using System.Linq; namespace UniGLTF.SpringBoneJobs { @@ -21,28 +22,39 @@ public sealed class FastSpringBoneBufferCombiner : IDisposable private FastSpringBoneCombinedBuffer _combinedBuffer; public FastSpringBoneCombinedBuffer Combined => _combinedBuffer; private readonly LinkedList _buffers = new LinkedList(); - private bool _isDirty; + private Queue<(bool isAdd, FastSpringBoneBuffer buffer)> _request = new(); public bool HasBuffer => _buffers.Count > 0 && _combinedBuffer != null; public void Register(FastSpringBoneBuffer buffer) { - _buffers.AddLast(buffer); - _isDirty = true; + _request.Enqueue((true, buffer)); } - public void Unregister(FastSpringBoneBuffer remove) + public void Unregister(FastSpringBoneBuffer buffer) { - // index が変わる前に シミュレーションの状態を保存する。 - // 状態の保存場所が BlittableJoint から CurrentTails に移動しているのでここでやる。 + _request.Enqueue((false, buffer)); + } + + /// + /// 変更があったならばバッファを再構築する + /// + public JobHandle ReconstructIfDirty(JobHandle handle) + { + if (_request.Count == 0) + { + return handle; + } + if (_combinedBuffer is FastSpringBoneCombinedBuffer combined) { + // index が変わる前に シミュレーションの状態を保存する。 + // 状態の保存場所が BlittableJoint から CurrentTails に移動しているのでここでやる。 var logicsIndex = 0; foreach (var buffer in _buffers) { - if (buffer == remove) + if (_request.Any(x => !x.isAdd && x.buffer == buffer)) { // 削除するので skip - // joint の位置が変わる可能性があるので状態を保存せずに速度を0にする方がよい continue; } buffer.BackupCurrentTails(combined.CurrentTails, logicsIndex); @@ -50,23 +62,23 @@ public void Unregister(FastSpringBoneBuffer remove) } } - _buffers.Remove(remove); - _isDirty = true; - } - - /// - /// 変更があったならばバッファを再構築する - /// - public JobHandle ReconstructIfDirty(JobHandle handle) - { - if (_isDirty) + // buffer 増減 + while (_request.Count > 0) { - var result = ReconstructBuffers(handle); - _isDirty = false; - return result; + var (isAdd, buffer) = _request.Dequeue(); + if (isAdd) + { + // 速度 0 にする + _buffers.AddLast(buffer); + } + else + { + _buffers.Remove(buffer); + } } - return handle; + // 再構築 + return ReconstructBuffers(handle); } /// From 5ead212afa397ad9b7eeee05d2c41bf66906e2f1 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 19 Nov 2024 09:53:37 +0900 Subject: [PATCH 11/14] FastSpringBoneBuffer.Dispose --- .../InputPorts/FastSpringBoneBuffer.cs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs index c1bf55ffb2..f17b068f2d 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs @@ -24,7 +24,6 @@ public class FastSpringBoneBuffer : IDisposable public NativeArray Logics { get; } private NativeArray _currentTailsBackup; public Transform[] Transforms { get; } - public bool IsDisposed { get; private set; } /// /// Joint, Collider, Center の Transform のリスト @@ -143,11 +142,7 @@ public static IEnumerable LogicFromTransform(Transform[ public void BackupCurrentTails(NativeArray currentTails, int offset) { - if (!IsDisposed) - { - return; - } - if (Logics.Length == 0) + if (!Logics.IsCreated || Logics.Length == 0) { return; } @@ -177,12 +172,11 @@ public void RestoreCurrentTails(NativeArray currentTails, int offset) public void Dispose() { - if (IsDisposed) return; - IsDisposed = true; - Springs.Dispose(); - Joints.Dispose(); - Colliders.Dispose(); - Logics.Dispose(); + if (Springs.IsCreated) Springs.Dispose(); + if (Joints.IsCreated) Joints.Dispose(); + if (Colliders.IsCreated) Colliders.Dispose(); + if (Logics.IsCreated) Logics.Dispose(); + if (_currentTailsBackup.IsCreated) _currentTailsBackup.Dispose(); } } } \ No newline at end of file From eed18136be27c08350dfc0bf7e8030d2aa95f003 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 19 Nov 2024 10:17:30 +0900 Subject: [PATCH 12/14] _nextTailsBackup --- .../FastSpringBoneBufferCombiner.cs | 2 +- .../FastSpringBoneConbinedBuffer.cs | 2 +- .../InputPorts/FastSpringBoneBuffer.cs | 30 ++++++++++--------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs index a43d5b4399..f22112b5eb 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneBufferCombiner.cs @@ -57,7 +57,7 @@ public JobHandle ReconstructIfDirty(JobHandle handle) // 削除するので skip continue; } - buffer.BackupCurrentTails(combined.CurrentTails, logicsIndex); + buffer.BackupCurrentTails(combined.CurrentTails, combined.NextTails, logicsIndex); logicsIndex += buffer.Logics.Length; } } diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs index 0e597b70d3..ae66220b68 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs @@ -148,7 +148,7 @@ private JobHandle Batching(JobHandle handle) } // 速度の維持 - buffer.RestoreCurrentTails(_currentTails, logicsOffset); + buffer.RestoreCurrentTails(_currentTails, _nextTails, logicsOffset); handle = new LoadSpringsJob { diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs index c1bf55ffb2..455e17dd64 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs @@ -23,8 +23,8 @@ public class FastSpringBoneBuffer : IDisposable public NativeArray Colliders { get; } public NativeArray Logics { get; } private NativeArray _currentTailsBackup; + private NativeArray _nextTailsBackup; public Transform[] Transforms { get; } - public bool IsDisposed { get; private set; } /// /// Joint, Collider, Center の Transform のリスト @@ -141,13 +141,9 @@ public static IEnumerable LogicFromTransform(Transform[ } } - public void BackupCurrentTails(NativeArray currentTails, int offset) + public void BackupCurrentTails(NativeArray currentTails, NativeArray nextTails, int offset) { - if (!IsDisposed) - { - return; - } - if (Logics.Length == 0) + if (!Logics.IsCreated || Logics.Length == 0) { return; } @@ -155,14 +151,20 @@ public void BackupCurrentTails(NativeArray currentTails, int offset) { _currentTailsBackup = new(Logics.Length, Allocator.Persistent); } + if (!_nextTailsBackup.IsCreated) + { + _nextTailsBackup = new(Logics.Length, Allocator.Persistent); + } NativeArray.Copy(currentTails, offset, _currentTailsBackup, 0, Logics.Length); + NativeArray.Copy(nextTails, offset, _nextTailsBackup, 0, Logics.Length); } - public void RestoreCurrentTails(NativeArray currentTails, int offset) + public void RestoreCurrentTails(NativeArray currentTails, NativeArray nextTails, int offset) { if (_currentTailsBackup.IsCreated) { NativeArray.Copy(_currentTailsBackup, 0, currentTails, offset, Logics.Length); + NativeArray.Copy(_nextTailsBackup, 0, nextTails, offset, Logics.Length); } else { @@ -177,12 +179,12 @@ public void RestoreCurrentTails(NativeArray currentTails, int offset) public void Dispose() { - if (IsDisposed) return; - IsDisposed = true; - Springs.Dispose(); - Joints.Dispose(); - Colliders.Dispose(); - Logics.Dispose(); + if (Springs.IsCreated) Springs.Dispose(); + if (Joints.IsCreated) Joints.Dispose(); + if (Colliders.IsCreated) Colliders.Dispose(); + if (Logics.IsCreated) Logics.Dispose(); + if (_currentTailsBackup.IsCreated) _currentTailsBackup.Dispose(); + if (_nextTailsBackup.IsCreated) _nextTailsBackup.Dispose(); } } } \ No newline at end of file From bf9c438f1fe131c4317440fe197cfee66a579bef Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 19 Nov 2024 12:58:52 +0900 Subject: [PATCH 13/14] use MonoBehaviour.OnValidate --- .../Editor/SpringBone/VRMSpringBoneEditor.cs | 34 ++----------------- .../VRM/Runtime/SpringBone/VRMSpringBone.cs | 28 +++++++++++++++ 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/Assets/VRM/Editor/SpringBone/VRMSpringBoneEditor.cs b/Assets/VRM/Editor/SpringBone/VRMSpringBoneEditor.cs index 5a870b0065..680bde7c53 100644 --- a/Assets/VRM/Editor/SpringBone/VRMSpringBoneEditor.cs +++ b/Assets/VRM/Editor/SpringBone/VRMSpringBoneEditor.cs @@ -25,34 +25,6 @@ class VRMSpringBoneEditor : Editor private SerializedProperty m_colliderGroupsProp; private SerializedProperty m_updateTypeProp; - Dictionary m_rootCount = new(); - List m_validation = new(); - - IEnumerable Validate() - { - m_validation.Clear(); - m_rootCount.Clear(); - foreach (var root in m_target.RootBones) - { - if (m_rootCount.TryGetValue(root, out var count)) - { - m_rootCount[root] = count + 1; - } - else - { - m_rootCount.Add(root, 1); - } - } - foreach (var (k, v) in m_rootCount) - { - if (v > 1) - { - m_validation.Add(Validation.Error($"Duplicate rootBone: {k} => {v}", ValidationContext.Create(k))); - } - } - return m_validation; - } - void OnEnable() { if (target == null) @@ -73,13 +45,11 @@ void OnEnable() m_hitRadiusProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_hitRadius)); m_colliderGroupsProp = serializedObject.FindProperty(nameof(VRMSpringBone.ColliderGroups)); m_updateTypeProp = serializedObject.FindProperty(nameof(VRMSpringBone.m_updateType)); - - Validate(); } public void OnSceneGUI() { - foreach (var valiation in m_validation) + foreach (var valiation in m_target.Validations) { var t = (Transform)valiation.Context.Context; if (t != null) @@ -101,7 +71,7 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(m_commentProp); EditorGUILayout.PropertyField(m_gizmoColorProp); EditorGUILayout.Space(); - foreach (var validation in m_validation) + foreach (var validation in m_target.Validations) { validation.DrawGUI(); } diff --git a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs index 75ed5f9506..056224d357 100644 --- a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs +++ b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using UniGLTF; using UnityEngine; namespace VRM @@ -60,6 +61,33 @@ List RootBonesNonNullUnique } SpringBone.SpringBoneSystem m_system = new(); + Dictionary m_rootCount = new(); + List m_validations = new(); + public List Validations => m_validations; + public void OnValidate() + { + Validations.Clear(); + m_rootCount.Clear(); + foreach (var root in RootBones) + { + if (m_rootCount.TryGetValue(root, out var count)) + { + m_rootCount[root] = count + 1; + } + else + { + m_rootCount.Add(root, 1); + } + } + foreach (var (k, v) in m_rootCount) + { + if (v > 1) + { + Validations.Add(Validation.Error($"Duplicate rootBone: {k} => {v}", ValidationContext.Create(k))); + } + } + } + void Awake() { Setup(); From c983367f40849d5d3604a9f8be685b3c7709c9fe Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 19 Nov 2024 13:15:55 +0900 Subject: [PATCH 14/14] update comment --- .../FastSpringBoneConbinedBuffer.cs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs index ae66220b68..f06f3f70a7 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs @@ -181,9 +181,6 @@ private JobHandle Batching(JobHandle handle) transformOffset += buffer.Transforms.Length; } - // verlet の current, prev, next のバッファを今の transform の状態にする。 - // 速度は 0 にクリアする。 - // TODO: 速度の維持は SaveToSourceBuffer でされていたのだがデータ構造変更で場所が変わった handle = InitCurrentTails(handle); Profiler.EndSample(); @@ -328,12 +325,21 @@ public void Execute(int springIndex) } } - /// - /// Transform から currentTail を更新。 - /// prevTail も同じ内容にする(速度0)。 + /// + /// # CurrentTails[i] == NAN + /// + /// Transforms から Current, Prev, Next を代入する。 + /// 速度 0 で初期化することになる。 + /// + /// # CurrentTails[i] != NAN + /// + /// 本処理はスキップされて Current, Next の利用が継続されます。 + /// + /// # NAN + /// + /// Batching 関数内の FastSpringBoneBuffer.RestoreCurrentTails にて backup の Current, Next が無かったときに + /// 目印として NAN が代入されます。 /// - /// - /// public JobHandle InitCurrentTails(JobHandle handle) { return new InitCurrentTailsJob