From af9e18c09c07c2846e7e835db36b827af9d9a2a5 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 16 Jul 2024 18:02:15 +0900 Subject: [PATCH 01/13] add BlittableExternalData.Paused --- .../Components/Vrm10Runtime/Vrm10Runtime.cs | 10 + .../Blittables/BlittableExternalData.cs | 1 + .../System/UpdateFastSpringBoneJob.cs | 12 +- .../VRM10Viewer/VRM10Viewer.unity | 348 +++++++++++++++++- .../VRM10Viewer/VRM10ViewerUI.cs | 26 +- 5 files changed, 372 insertions(+), 25 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs index 52eccc274..b38dd7204 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs @@ -51,6 +51,16 @@ namespace UniVRM10 } } + public bool SpringBonePaused + { + get => m_externalData.Paused; + set + { + m_externalData.Paused = value; + m_fastSpringBoneBuffer.ExternalData = m_externalData; + } + } + public Vrm10Runtime(Vrm10Instance instance, bool useControlRig) { if (!Application.isPlaying) diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableExternalData.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableExternalData.cs index f55dd5d97..637cad71a 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableExternalData.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableExternalData.cs @@ -8,5 +8,6 @@ namespace UniVRM10.FastSpringBones.Blittables public struct BlittableExternalData { public Vector3 ExternalForce; + public bool Paused; } } \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs b/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs index 4c7009d09..b71ec5d67 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs @@ -147,8 +147,16 @@ namespace UniVRM10.FastSpringBones.System headTransform.localRotation = headTransform.rotation; } - // 値をバッファに戻す - Transforms[logic.headTransformIndex + transformIndexOffset] = headTransform; + if (spring.ExternalData->Paused) + { + // SpringBone の結果を Transform に反映しないが logic の更新は継続する。 + // 再開したときに暴れない。 + } + else + { + // SpringBone の結果を Transform に反映する + Transforms[logic.headTransformIndex + transformIndexOffset] = headTransform; + } Logics[logicIndex] = logic; } } diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity b/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity index 1346fb42d..fd4909ed3 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity @@ -232,7 +232,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 339774397} - m_RootOrder: 14 + m_RootOrder: 15 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1240,9 +1240,10 @@ RectTransform: - {fileID: 224350191} - {fileID: 1791103379} - {fileID: 1311520909} - - {fileID: 1557052150} - - {fileID: 1767706907} - {fileID: 974864191} + - {fileID: 1767706907} + - {fileID: 1557052150} + - {fileID: 1728528388} - {fileID: 597950322} - {fileID: 935566651} - {fileID: 634488421} @@ -1822,7 +1823,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 339774397} - m_RootOrder: 10 + m_RootOrder: 11 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1903,7 +1904,7 @@ RectTransform: - {fileID: 154330168} - {fileID: 1954133885} m_Father: {fileID: 339774397} - m_RootOrder: 16 + m_RootOrder: 17 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1990,7 +1991,7 @@ RectTransform: - {fileID: 2010083454} - {fileID: 1081455630} m_Father: {fileID: 339774397} - m_RootOrder: 12 + m_RootOrder: 13 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -3397,7 +3398,7 @@ RectTransform: - {fileID: 175751363} - {fileID: 1904789319} m_Father: {fileID: 339774397} - m_RootOrder: 11 + m_RootOrder: 12 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -3435,7 +3436,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 339774397} - m_RootOrder: 9 + m_RootOrder: 7 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -4600,6 +4601,86 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1242458542} m_CullTransparentMesh: 0 +--- !u!1 &1258907230 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1258907231} + - component: {fileID: 1258907233} + - component: {fileID: 1258907232} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1258907231 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1258907230} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1728528388} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 9, y: -0.5} + m_SizeDelta: {x: -28, y: -3} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1258907232 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1258907230} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: PauseSpringBone +--- !u!222 &1258907233 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1258907230} + m_CullTransparentMesh: 1 --- !u!1 &1268276254 GameObject: m_ObjectHideFlags: 0 @@ -5363,7 +5444,7 @@ RectTransform: - {fileID: 452923209} - {fileID: 2090837017} m_Father: {fileID: 339774397} - m_RootOrder: 15 + m_RootOrder: 16 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -5498,6 +5579,83 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1476033060} m_CullTransparentMesh: 0 +--- !u!1 &1519258557 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1519258558} + - component: {fileID: 1519258560} + - component: {fileID: 1519258559} + m_Layer: 5 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1519258558 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519258557} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 2055567529} + m_Father: {fileID: 1728528388} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 10, y: -10} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1519258559 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519258557} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1519258560 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519258557} + m_CullTransparentMesh: 1 --- !u!1 &1557052149 GameObject: m_ObjectHideFlags: 0 @@ -5510,7 +5668,7 @@ GameObject: - component: {fileID: 1557052152} - component: {fileID: 1557052151} m_Layer: 5 - m_Name: _ + m_Name: _SpringBone_ m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -5529,7 +5687,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 339774397} - m_RootOrder: 7 + m_RootOrder: 9 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -5569,7 +5727,7 @@ MonoBehaviour: m_HorizontalOverflow: 0 m_VerticalOverflow: 0 m_LineSpacing: 1 - m_Text: + m_Text: SpringBone --- !u!222 &1557052152 CanvasRenderer: m_ObjectHideFlags: 0 @@ -5920,6 +6078,93 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1636340563} m_CullTransparentMesh: 0 +--- !u!1 &1728528387 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1728528388} + - component: {fileID: 1728528389} + m_Layer: 5 + m_Name: PauseSpringBone + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1728528388 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1728528387} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1519258558} + - {fileID: 1258907231} + m_Father: {fileID: 339774397} + m_RootOrder: 10 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 160, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1728528389 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1728528387} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1519258559} + toggleTransition: 1 + graphic: {fileID: 2055567530} + m_Group: {fileID: 0} + onValueChanged: + m_PersistentCalls: + m_Calls: [] + m_IsOn: 0 --- !u!1 &1761414315 GameObject: m_ObjectHideFlags: 0 @@ -6199,7 +6444,7 @@ RectTransform: - {fileID: 62367395} - {fileID: 1037763549} m_Father: {fileID: 339774397} - m_RootOrder: 13 + m_RootOrder: 14 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -6373,6 +6618,7 @@ MonoBehaviour: m_openMotion: {fileID: 168425996} m_pastePose: {fileID: 1307084564} m_showBoxMan: {fileID: 1767706908} + m_puaseSpringBone: {fileID: 1728528389} m_enableLipSync: {fileID: 935566650} m_enableAutoBlink: {fileID: 634488422} m_enableAutoExpression: {fileID: 1767738855} @@ -7243,6 +7489,82 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2010083453} m_CullTransparentMesh: 0 +--- !u!1 &2055567528 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2055567529} + - component: {fileID: 2055567531} + - component: {fileID: 2055567530} + m_Layer: 5 + m_Name: Checkmark + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2055567529 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2055567528} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1519258558} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2055567530 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2055567528} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10901, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &2055567531 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2055567528} + m_CullTransparentMesh: 1 --- !u!1 &2090837016 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs index f4ecd3445..8f15e0fcf 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs @@ -27,6 +27,9 @@ namespace UniVRM10.VRM10Viewer [SerializeField] Toggle m_showBoxMan = default; + [SerializeField] + Toggle m_puaseSpringBone = default; + [SerializeField] Toggle m_enableLipSync = default; @@ -259,6 +262,7 @@ namespace UniVRM10.VRM10Viewer var toggles = GameObject.FindObjectsOfType(); #endif m_showBoxMan = toggles.First(x => x.name == "ShowBoxMan"); + m_puaseSpringBone = toggles.First(x => x.name == "PauseSpringBone"); m_enableLipSync = toggles.First(x => x.name == "EnableLipSync"); m_enableAutoBlink = toggles.First(x => x.name == "EnableAutoBlink"); m_enableAutoExpression = toggles.First(x => x.name == "EnableAutoExpression"); @@ -393,18 +397,20 @@ namespace UniVRM10.VRM10Viewer m_loaded.EnableLipSyncValue = m_enableLipSync.isOn; m_loaded.EnableBlinkValue = m_enableAutoBlink.isOn; m_loaded.EnableAutoExpressionValue = m_enableAutoExpression.isOn; - } - if (m_loaded != null) - { - if (m_ui.IsTPose) + if (m_loaded.Runtime != null) { - m_loaded.Runtime.VrmAnimation = TPose; - } - else if (Motion != null) - { - // Automatically retarget in Vrm10Runtime.Process - m_loaded.Runtime.VrmAnimation = Motion; + if (m_ui.IsTPose) + { + m_loaded.Runtime.VrmAnimation = TPose; + } + else if (Motion != null) + { + // Automatically retarget in Vrm10Runtime.Process + m_loaded.Runtime.VrmAnimation = Motion; + } + + m_loaded.Runtime.SpringBonePaused = m_puaseSpringBone.isOn; } } } From 5b47fab89f7f58edcbf190f87364ff2c25472bf5 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 16 Jul 2024 18:51:20 +0900 Subject: [PATCH 02/13] SpringBonePaused to IsSpringBoneEnabled. invert boolean --- .../Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs | 6 +++--- .../Blittables/BlittableExternalData.cs | 6 +++++- .../FastSpringBone/System/UpdateFastSpringBoneJob.cs | 12 ++++++------ Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs | 6 +++--- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs index b38dd7204..e9a80c716 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs @@ -51,12 +51,12 @@ namespace UniVRM10 } } - public bool SpringBonePaused + public bool IsSpringBoneEnabled { - get => m_externalData.Paused; + get => m_externalData.IsSpringBoneEnabled; set { - m_externalData.Paused = value; + m_externalData.IsSpringBoneEnabled = value; m_fastSpringBoneBuffer.ExternalData = m_externalData; } } diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableExternalData.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableExternalData.cs index 637cad71a..d79789c5f 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableExternalData.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableExternalData.cs @@ -8,6 +8,10 @@ namespace UniVRM10.FastSpringBones.Blittables public struct BlittableExternalData { public Vector3 ExternalForce; - public bool Paused; + + /// + /// if false, spring bone is paused. + /// + public bool IsSpringBoneEnabled; } } \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs b/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs index b71ec5d67..cc0694514 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs @@ -147,16 +147,16 @@ namespace UniVRM10.FastSpringBones.System headTransform.localRotation = headTransform.rotation; } - if (spring.ExternalData->Paused) - { - // SpringBone の結果を Transform に反映しないが logic の更新は継続する。 - // 再開したときに暴れない。 - } - else + if (spring.ExternalData->IsSpringBoneEnabled) { // SpringBone の結果を Transform に反映する Transforms[logic.headTransformIndex + transformIndexOffset] = headTransform; } + else + { + // SpringBone の結果を Transform に反映しないが logic の更新は継続する。 + // 再開したときに暴れない。 + } Logics[logicIndex] = logic; } } diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs index 8f15e0fcf..b73892561 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs @@ -28,7 +28,7 @@ namespace UniVRM10.VRM10Viewer Toggle m_showBoxMan = default; [SerializeField] - Toggle m_puaseSpringBone = default; + Toggle m_pauseSpringBone = default; [SerializeField] Toggle m_enableLipSync = default; @@ -262,7 +262,7 @@ namespace UniVRM10.VRM10Viewer var toggles = GameObject.FindObjectsOfType(); #endif m_showBoxMan = toggles.First(x => x.name == "ShowBoxMan"); - m_puaseSpringBone = toggles.First(x => x.name == "PauseSpringBone"); + m_pauseSpringBone = toggles.First(x => x.name == "PauseSpringBone"); m_enableLipSync = toggles.First(x => x.name == "EnableLipSync"); m_enableAutoBlink = toggles.First(x => x.name == "EnableAutoBlink"); m_enableAutoExpression = toggles.First(x => x.name == "EnableAutoExpression"); @@ -410,7 +410,7 @@ namespace UniVRM10.VRM10Viewer m_loaded.Runtime.VrmAnimation = Motion; } - m_loaded.Runtime.SpringBonePaused = m_puaseSpringBone.isOn; + m_loaded.Runtime.IsSpringBoneEnabled = !m_pauseSpringBone.isOn; } } } From 3a37f358837e067b7ab970ce67a54d614a9b2166 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 16 Jul 2024 19:18:31 +0900 Subject: [PATCH 03/13] =?UTF-8?q?Vrm10Runtime=20=E3=81=8B=E3=82=89=20Sprin?= =?UTF-8?q?gBone=20=E9=96=A2=E9=80=A3=E3=82=92=20Vrm10RuntimeSpringBone=20?= =?UTF-8?q?=E3=81=AB=E5=88=86=E9=9B=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Vrm10Runtime/Vrm10Runtime.cs | 139 +--------------- .../Vrm10Runtime/Vrm10RuntimeSpringBone .cs | 154 ++++++++++++++++++ .../Vrm10RuntimeSpringBone .cs.meta | 11 ++ .../VRM10_Samples/VRM10Viewer/VRM10Loaded.cs | 1 - .../VRM10Viewer/VRM10Viewer.unity | 2 +- .../VRM10Viewer/VRM10ViewerUI.cs | 2 +- 6 files changed, 176 insertions(+), 133 deletions(-) create mode 100644 Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs create mode 100644 Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs.meta diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs index e9a80c716..bc33b17e0 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs @@ -1,11 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; -using UniGLTF; -using UniGLTF.Utils; using UnityEngine; -using UniVRM10.FastSpringBones.Blittables; -using UniVRM10.FastSpringBones.System; namespace UniVRM10 { @@ -23,11 +17,6 @@ namespace UniVRM10 { private readonly Vrm10Instance m_instance; private readonly Transform m_head; - private readonly FastSpringBoneService m_fastSpringBoneService; - private readonly IReadOnlyDictionary m_defaultTransformStates; - - private FastSpringBoneBuffer m_fastSpringBoneBuffer; - private BlittableExternalData m_externalData; /// /// Control Rig may be null. @@ -38,27 +27,14 @@ namespace UniVRM10 public IVrm10Constraint[] Constraints { get; } public Vrm10RuntimeExpression Expression { get; } public Vrm10RuntimeLookAt LookAt { get; } - + public Vrm10RuntimeSpringBone SpringBone { get; } public IVrm10Animation VrmAnimation { get; set; } + [Obsolete("use Vrm10Runtime.SpringBone.ExternalForce")] public Vector3 ExternalForce { - get => m_externalData.ExternalForce; - set - { - m_externalData.ExternalForce = value; - m_fastSpringBoneBuffer.ExternalData = m_externalData; - } - } - - public bool IsSpringBoneEnabled - { - get => m_externalData.IsSpringBoneEnabled; - set - { - m_externalData.IsSpringBoneEnabled = value; - m_fastSpringBoneBuffer.ExternalData = m_externalData; - } + get { return SpringBone.ExternalForce; } + set { SpringBone.ExternalForce = value; } } public Vrm10Runtime(Vrm10Instance instance, bool useControlRig) @@ -82,117 +58,20 @@ namespace UniVRM10 Constraints = instance.GetComponentsInChildren(); LookAt = new Vrm10RuntimeLookAt(instance.Vrm.LookAt, instance.Humanoid, ControlRig); Expression = new Vrm10RuntimeExpression(instance, LookAt.EyeDirectionApplicable); - - var gltfInstance = instance.GetComponent(); - if (gltfInstance != null) - { - // ランタイムインポートならここに到達してゼロコストになる - m_defaultTransformStates = gltfInstance.InitialTransformStates; - } - else - { - // エディタでプレハブ配置してる奴ならこっちに到達して収集する - m_defaultTransformStates = instance.GetComponentsInChildren() - .ToDictionary(tf => tf, tf => new TransformState(tf)); - } - - // NOTE: FastSpringBoneService は UnitTest などでは動作しない - if (Application.isPlaying) - { - m_fastSpringBoneService = FastSpringBoneService.Instance; - m_fastSpringBoneBuffer = CreateFastSpringBoneBuffer(m_instance.SpringBone); - m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer); - } + SpringBone = new Vrm10RuntimeSpringBone(instance); } public void Dispose() { ControlRig?.Dispose(); - m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer); - m_fastSpringBoneBuffer.Dispose(); + SpringBone.Dispose(); } - /// - /// このVRMに紐づくSpringBone関連のバッファを再構築する - /// ランタイム実行時にSpringBoneに対して変更を行いたいときは、このメソッドを明示的に呼ぶ必要がある - /// + [Obsolete("use Vrm10Runtime.SpringBone.ReconstructSpringBone")] public void ReconstructSpringBone() { - m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer); - - m_fastSpringBoneBuffer.Dispose(); - m_fastSpringBoneBuffer = CreateFastSpringBoneBuffer(m_instance.SpringBone); - - m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer); + SpringBone.ReconstructSpringBone(); } - - private FastSpringBoneBuffer CreateFastSpringBoneBuffer(Vrm10InstanceSpringBone springBone) - { - return new FastSpringBoneBuffer( - 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 BlittableJoint - { - 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(), - m_externalData); - } - - private TransformState GetOrAddDefaultTransformState(Transform tf) - { - if (m_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(); - } - } - /// /// 毎フレーム関連コンポーネントを解決する /// @@ -251,4 +130,4 @@ namespace UniVRM10 Expression.Process(eyeDirection); } } -} +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs new file mode 100644 index 000000000..23dbfff3b --- /dev/null +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UniGLTF; +using UniGLTF.Utils; +using UnityEngine; +using UniVRM10.FastSpringBones.Blittables; +using UniVRM10.FastSpringBones.System; + +namespace UniVRM10 +{ + public class Vrm10RuntimeSpringBone : IDisposable + { + private readonly Vrm10Instance m_instance; + private readonly IReadOnlyDictionary m_defaultTransformStates; + private readonly FastSpringBoneService m_fastSpringBoneService; + private FastSpringBoneBuffer m_fastSpringBoneBuffer; + private BlittableExternalData m_externalData; + + public Vector3 ExternalForce + { + get => m_externalData.ExternalForce; + set + { + m_externalData.ExternalForce = value; + m_fastSpringBoneBuffer.ExternalData = m_externalData; + } + } + + public bool IsSpringBoneEnabled + { + get => m_externalData.IsSpringBoneEnabled; + set + { + m_externalData.IsSpringBoneEnabled = value; + m_fastSpringBoneBuffer.ExternalData = m_externalData; + } + } + + public Vrm10RuntimeSpringBone(Vrm10Instance instance) + { + m_instance = instance; + + var gltfInstance = instance.GetComponent(); + if (gltfInstance != null) + { + // ランタイムインポートならここに到達してゼロコストになる + m_defaultTransformStates = gltfInstance.InitialTransformStates; + } + else + { + // エディタでプレハブ配置してる奴ならこっちに到達して収集する + m_defaultTransformStates = instance.GetComponentsInChildren() + .ToDictionary(tf => tf, tf => new TransformState(tf)); + } + + // NOTE: FastSpringBoneService は UnitTest などでは動作しない + if (Application.isPlaying) + { + m_fastSpringBoneService = FastSpringBoneService.Instance; + m_fastSpringBoneBuffer = CreateFastSpringBoneBuffer(m_instance.SpringBone); + m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer); + } + + } + + public void Dispose() + { + m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer); + m_fastSpringBoneBuffer.Dispose(); + } + + /// + /// このVRMに紐づくSpringBone関連のバッファを再構築する + /// ランタイム実行時にSpringBoneに対して変更を行いたいときは、このメソッドを明示的に呼ぶ必要がある + /// + public void ReconstructSpringBone() + { + m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer); + + m_fastSpringBoneBuffer.Dispose(); + m_fastSpringBoneBuffer = CreateFastSpringBoneBuffer(m_instance.SpringBone); + + m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer); + } + + private FastSpringBoneBuffer CreateFastSpringBoneBuffer(Vrm10InstanceSpringBone springBone) + { + return new FastSpringBoneBuffer( + 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 BlittableJoint + { + 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(), + m_externalData); + } + + private TransformState GetOrAddDefaultTransformState(Transform tf) + { + if (m_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(); + } + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs.meta new file mode 100644 index 000000000..7772228d7 --- /dev/null +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2f3312577381e824eac9514c892e3cbc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Loaded.cs b/Assets/VRM10_Samples/VRM10Viewer/VRM10Loaded.cs index e5d5882b5..11d47dac9 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10Loaded.cs +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10Loaded.cs @@ -1,6 +1,5 @@ using System; using UniGLTF; -using UniGLTF.Utils; using UnityEngine; namespace UniVRM10.VRM10Viewer diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity b/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity index fd4909ed3..77c4b9464 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity @@ -6618,7 +6618,7 @@ MonoBehaviour: m_openMotion: {fileID: 168425996} m_pastePose: {fileID: 1307084564} m_showBoxMan: {fileID: 1767706908} - m_puaseSpringBone: {fileID: 1728528389} + m_pauseSpringBone: {fileID: 1728528389} m_enableLipSync: {fileID: 935566650} m_enableAutoBlink: {fileID: 634488422} m_enableAutoExpression: {fileID: 1767738855} diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs index b73892561..c3ba3c2ec 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs @@ -410,7 +410,7 @@ namespace UniVRM10.VRM10Viewer m_loaded.Runtime.VrmAnimation = Motion; } - m_loaded.Runtime.IsSpringBoneEnabled = !m_pauseSpringBone.isOn; + m_loaded.Runtime.SpringBone.IsSpringBoneEnabled = !m_pauseSpringBone.isOn; } } } From 7f856bf9453df3906e8b93bbe713cd8f44a56815 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 17 Jul 2024 13:38:40 +0900 Subject: [PATCH 04/13] separate FastSpringBoneBufferBuilder --- .../Vrm10Runtime/Vrm10RuntimeSpringBone .cs | 86 ++++----- .../InputPorts/FastSpringBoneBuffer.cs | 177 ++++-------------- .../InputPorts/FastSpringBoneBufferBuilder.cs | 143 ++++++++++++++ .../FastSpringBoneBufferBuilder.cs.meta | 11 ++ 4 files changed, 229 insertions(+), 188 deletions(-) create mode 100644 Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs.meta diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs index 23dbfff3b..8ede70a88 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs @@ -14,27 +14,17 @@ namespace UniVRM10 private readonly Vrm10Instance m_instance; private readonly IReadOnlyDictionary m_defaultTransformStates; private readonly FastSpringBoneService m_fastSpringBoneService; - private FastSpringBoneBuffer m_fastSpringBoneBuffer; - private BlittableExternalData m_externalData; + private FastSpringBoneBuffer m_fastSpringBoneBuffer; public Vector3 ExternalForce { - get => m_externalData.ExternalForce; - set - { - m_externalData.ExternalForce = value; - m_fastSpringBoneBuffer.ExternalData = m_externalData; - } + get => m_fastSpringBoneBuffer.ExternalForce; + set { m_fastSpringBoneBuffer.ExternalForce = value; } } - public bool IsSpringBoneEnabled { - get => m_externalData.IsSpringBoneEnabled; - set - { - m_externalData.IsSpringBoneEnabled = value; - m_fastSpringBoneBuffer.ExternalData = m_externalData; - } + get => m_fastSpringBoneBuffer.IsSpringBoneEnabled; + set { m_fastSpringBoneBuffer.IsSpringBoneEnabled = value; } } public Vrm10RuntimeSpringBone(Vrm10Instance instance) @@ -86,39 +76,39 @@ namespace UniVRM10 private FastSpringBoneBuffer CreateFastSpringBoneBuffer(Vrm10InstanceSpringBone springBone) { - return new FastSpringBoneBuffer( - 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 BlittableJoint - { - 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(), - m_externalData); + var b = new FastSpringBoneBufferBuilder(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 BlittableJoint + { + 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(), + })); + + return new FastSpringBoneBuffer(b); } private TransformState GetOrAddDefaultTransformState(Transform tf) diff --git a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs index c91391354..3ae2fcbc5 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using UnityEngine; @@ -26,149 +24,48 @@ namespace UniVRM10.FastSpringBones.System // NOTE: これは更新頻度が高くバッチングが難しいため、ランダムアクセスを許容してメモリへ直接アクセスする // 生のヒープ領域は扱いにくいので長さ1のNativeArrayで代用 private NativeArray _externalData; - - public BlittableExternalData ExternalData + public Vector3 ExternalForce { - get => _externalData[0]; - set => _externalData[0] = value; + get => _externalData[0].ExternalForce; + set + { + _externalData[0] = new BlittableExternalData + { + ExternalForce = value, + IsSpringBoneEnabled = _externalData[0].IsSpringBoneEnabled, + }; + } + } + public bool IsSpringBoneEnabled + { + get => _externalData[0].IsSpringBoneEnabled; + set + { + _externalData[0] = new BlittableExternalData + { + ExternalForce = _externalData[0].ExternalForce, + IsSpringBoneEnabled = value, + }; + } + } - public unsafe FastSpringBoneBuffer(IReadOnlyList springs, - BlittableExternalData externalData, - bool simulateLastBone = false) + public unsafe FastSpringBoneBuffer(FastSpringBoneBufferBuilder b) { - Profiler.BeginSample("FastSpringBone.ConstructBuffers"); - - _externalData = new NativeArray(1, Allocator.Persistent); - ExternalData = externalData; - - // Transformの列挙 - Profiler.BeginSample("FastSpringBone.ConstructBuffers.ConstructTransformBuffer"); - 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(); - var transformIndexDictionary = transforms.Select((trs, index) => (trs, index)) - .ToDictionary(tuple => tuple.trs, tuple => tuple.index); - Profiler.EndSample(); - - // 各種bufferの構築 - Profiler.BeginSample("FastSpringBone.ConstructBuffers.ConstructBuffers"); - var blittableColliders = new List(); - var blittableJoints = new List(); - var blittableSprings = new List(); - var blittableLogics = new List(); - - 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 = simulateLastBone ? spring.joints.Length : spring.joints.Length - 1, - }, - centerTransformIndex = spring.center ? transformIndexDictionary[spring.center] : -1, - ExternalData = (BlittableExternalData*) _externalData.GetUnsafePtr() - }; - blittableSprings.Add(blittableSpring); - - blittableColliders.AddRange(spring.colliders.Select(collider => - { - var blittable = collider.Collider; - blittable.transformIndex = transformIndexDictionary[collider.Transform]; - return blittable; - })); - blittableJoints.AddRange(spring.joints - .Take(simulateLastBone ? spring.joints.Length : spring.joints.Length - 1).Select(joint => - { - var blittable = joint.Joint; - return blittable; - })); - - for (var i = 0; i < (simulateLastBone ? spring.joints.Length : 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 = transformIndexDictionary[joint.Transform], - parentTransformIndex = parent != null ? transformIndexDictionary[parent] : -1, - currentTail = currentTail, - prevTail = currentTail, - localRotation = joint.DefaultLocalRotation, - boneAxis = localChildPosition.normalized, - length = localChildPosition.magnitude - }); - } - } - - Profiler.EndSample(); - - // 各種bufferの初期化 Profiler.BeginSample("FastSpringBone.ConstructBuffers.ConstructNativeArrays"); - 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); - Transforms = transforms.ToArray(); - Profiler.EndSample(); - + _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; Profiler.EndSample(); } diff --git a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs new file mode 100644 index 000000000..dc239064b --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs @@ -0,0 +1,143 @@ +using System.Collections.Generic; +using System.Linq; +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 FastSpringBoneBufferBuilder(IEnumerable springs, bool simulateLastBone = false) + { + 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(); + var transformIndexDictionary = Transforms.Select((trs, index) => (trs, index)) + .ToDictionary(tuple => tuple.trs, tuple => tuple.index); + + 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 = simulateLastBone ? spring.joints.Length : spring.joints.Length - 1, + }, + centerTransformIndex = spring.center ? transformIndexDictionary[spring.center] : -1, + }; + BlittableSprings.Add(blittableSpring); + + BlittableColliders.AddRange(spring.colliders.Select(collider => + { + var blittable = collider.Collider; + blittable.transformIndex = transformIndexDictionary[collider.Transform]; + return blittable; + })); + BlittableJoints.AddRange(spring.joints + .Take(simulateLastBone ? spring.joints.Length : spring.joints.Length - 1).Select(joint => + { + var blittable = joint.Joint; + return blittable; + })); + + for (var i = 0; i < (simulateLastBone ? spring.joints.Length : 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 = transformIndexDictionary[joint.Transform], + parentTransformIndex = parent != null ? transformIndexDictionary[parent] : -1, + currentTail = currentTail, + prevTail = currentTail, + localRotation = joint.DefaultLocalRotation, + boneAxis = localChildPosition.normalized, + length = localChildPosition.magnitude + }); + } + } + Profiler.EndSample(); + } + + 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]; + BlittableSprings[i] = new BlittableSpring + { + centerTransformIndex = b.centerTransformIndex, + colliderSpan = b.colliderSpan, + logicSpan = b.logicSpan, + transformIndexOffset = b.transformIndexOffset, + ExternalData = externalData, + }; + } + } + } +} \ 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 new file mode 100644 index 000000000..29bea2967 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 82dbc85cfa7168546b209a51f6342d84 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From b69b3760e31bfd7bdd04575da7fb67edcb635828 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 17 Jul 2024 13:49:42 +0900 Subject: [PATCH 05/13] private FastSpringBoneBufferBuilder m_initialData --- .../Vrm10Runtime/Vrm10RuntimeSpringBone .cs | 29 +++++++++---------- .../InputPorts/FastSpringBoneBufferBuilder.cs | 2 +- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs index 8ede70a88..f3a47dcad 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs @@ -15,6 +15,7 @@ namespace UniVRM10 private readonly IReadOnlyDictionary m_defaultTransformStates; private readonly FastSpringBoneService m_fastSpringBoneService; + private FastSpringBoneBufferBuilder m_initialData; private FastSpringBoneBuffer m_fastSpringBoneBuffer; public Vector3 ExternalForce { @@ -48,10 +49,8 @@ namespace UniVRM10 if (Application.isPlaying) { m_fastSpringBoneService = FastSpringBoneService.Instance; - m_fastSpringBoneBuffer = CreateFastSpringBoneBuffer(m_instance.SpringBone); - m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer); + ReconstructSpringBone(); } - } public void Dispose() @@ -66,17 +65,15 @@ namespace UniVRM10 /// public void ReconstructSpringBone() { - m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer); + // rerelase + if (m_fastSpringBoneBuffer != null) + { + m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer); + m_fastSpringBoneBuffer.Dispose(); + } - m_fastSpringBoneBuffer.Dispose(); - m_fastSpringBoneBuffer = CreateFastSpringBoneBuffer(m_instance.SpringBone); - - m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer); - } - - private FastSpringBoneBuffer CreateFastSpringBoneBuffer(Vrm10InstanceSpringBone springBone) - { - var b = new FastSpringBoneBufferBuilder(springBone.Springs.Select(spring => new FastSpringBoneSpring + // create + var springs = m_instance.SpringBone.Springs.Select(spring => new FastSpringBoneSpring { center = spring.Center, colliders = spring.ColliderGroups @@ -106,9 +103,11 @@ namespace UniVRM10 }, DefaultLocalRotation = GetOrAddDefaultTransformState(joint.transform).LocalRotation, }).ToArray(), - })); + }).ToArray(); - return new FastSpringBoneBuffer(b); + m_initialData = new FastSpringBoneBufferBuilder(springs); + m_fastSpringBoneBuffer = new FastSpringBoneBuffer(m_initialData); + m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer); } private TransformState GetOrAddDefaultTransformState(Transform tf) diff --git a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs index dc239064b..64e47fbdd 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs @@ -14,7 +14,7 @@ namespace UniVRM10.FastSpringBones.System public readonly List BlittableLogics = new(); public readonly Transform[] Transforms; - public FastSpringBoneBufferBuilder(IEnumerable springs, bool simulateLastBone = false) + public FastSpringBoneBufferBuilder(IReadOnlyList springs, bool simulateLastBone = false) { Profiler.BeginSample("FastSpringBone.ConstructBuffers.BufferBuilder"); var transformHashSet = new HashSet(); From a9d645d4ff5730e9c3a515a92cf9a3bf359863f6 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 17 Jul 2024 14:42:58 +0900 Subject: [PATCH 06/13] impl Vrm10RuntimeSpringBone.RestoreInitialTransform --- .../Vrm10Runtime/Vrm10RuntimeSpringBone .cs | 19 ++ .../InputPorts/FastSpringBoneBufferBuilder.cs | 135 +++++----- .../VRM10Viewer/VRM10Viewer.unity | 230 +++++++++++++++++- .../VRM10Viewer/VRM10ViewerUI.cs | 16 ++ 4 files changed, 332 insertions(+), 68 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs index f3a47dcad..06863b2fc 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs @@ -139,5 +139,24 @@ namespace UniVRM10 throw new ArgumentOutOfRangeException(); } } + + public void RestoreInitialTransform() + { + // Spring の joint に対応する transform の回転を初期状態 + foreach (var (k, v) in m_initialData.TransformIndexMap) + { + k.localRotation = v.InitialLocalRotation; + } + + // 初期状態にしたtransformを使って spring logic を構築 + m_initialData.BlittableLogics.Clear(); + foreach (var spring in m_initialData.Springs) + { + m_initialData.AddLogic(spring); + } + + // DOTS バッファーを更新 + m_initialData.SyncAndZeroVelocity(m_fastSpringBoneBuffer.Logics); + } } } \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs index 64e47fbdd..1e0c01ead 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Unity.Collections; using UnityEngine; using UnityEngine.Profiling; using UniVRM10.FastSpringBones.Blittables; @@ -13,9 +14,17 @@ namespace UniVRM10.FastSpringBones.System public readonly List BlittableColliders = new(); public readonly List BlittableLogics = new(); public readonly Transform[] Transforms; - - public FastSpringBoneBufferBuilder(IReadOnlyList springs, bool simulateLastBone = false) + public struct TransformInfo { + public int Index; + public Quaternion InitialLocalRotation; + } + public readonly IDictionary TransformIndexMap; + public readonly FastSpringBoneSpring[] Springs; + + public FastSpringBoneBufferBuilder(FastSpringBoneSpring[] springs, bool simulateLastBone = false) + { + Springs = springs; Profiler.BeginSample("FastSpringBone.ConstructBuffers.BufferBuilder"); var transformHashSet = new HashSet(); foreach (var spring in springs) @@ -34,8 +43,12 @@ namespace UniVRM10.FastSpringBones.System if (spring.center != null) transformHashSet.Add(spring.center); } Transforms = transformHashSet.ToArray(); - var transformIndexDictionary = Transforms.Select((trs, index) => (trs, index)) - .ToDictionary(tuple => tuple.trs, tuple => tuple.index); + TransformIndexMap = Transforms.Select((trs, index) => (trs, index)) + .ToDictionary(tuple => tuple.trs, tuple => new TransformInfo + { + Index = tuple.index, + InitialLocalRotation = tuple.trs.localRotation, + }); foreach (var spring in springs) { @@ -51,14 +64,14 @@ namespace UniVRM10.FastSpringBones.System startIndex = BlittableJoints.Count, count = simulateLastBone ? spring.joints.Length : spring.joints.Length - 1, }, - centerTransformIndex = spring.center ? transformIndexDictionary[spring.center] : -1, + centerTransformIndex = spring.center ? TransformIndexMap[spring.center].Index : -1, }; BlittableSprings.Add(blittableSpring); BlittableColliders.AddRange(spring.colliders.Select(collider => { var blittable = collider.Collider; - blittable.transformIndex = transformIndexDictionary[collider.Transform]; + blittable.transformIndex = TransformIndexMap[collider.Transform].Index; return blittable; })); BlittableJoints.AddRange(spring.joints @@ -68,56 +81,62 @@ namespace UniVRM10.FastSpringBones.System return blittable; })); - for (var i = 0; i < (simulateLastBone ? spring.joints.Length : spring.joints.Length - 1); ++i) + AddLogic(spring, simulateLastBone); + + } + Profiler.EndSample(); + } + + public void AddLogic(FastSpringBoneSpring spring, bool simulateLastBone = false) + { + for (var i = 0; i < (simulateLastBone ? spring.joints.Length : 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) { - 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) { - localPosition = tailJoint.Value.Transform.localPosition; + var delta = joint.Transform.position - parentJoint.Value.Transform.position; + localPosition = + joint.Transform.worldToLocalMatrix.MultiplyPoint(joint.Transform.position + delta); } 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; - } + 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 = transformIndexDictionary[joint.Transform], - parentTransformIndex = parent != null ? transformIndexDictionary[parent] : -1, - currentTail = currentTail, - prevTail = currentTail, - localRotation = joint.DefaultLocalRotation, - boneAxis = localChildPosition.normalized, - length = localChildPosition.magnitude - }); } + + 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 = TransformIndexMap[joint.Transform].Index, + parentTransformIndex = parent != null ? TransformIndexMap[parent].Index : -1, + currentTail = currentTail, + prevTail = currentTail, + localRotation = joint.DefaultLocalRotation, + boneAxis = localChildPosition.normalized, + length = localChildPosition.magnitude + }); } - Profiler.EndSample(); } public unsafe void SetExternalDataPtr(BlittableExternalData* externalData) @@ -129,14 +148,18 @@ namespace UniVRM10.FastSpringBones.System // ExternalData = externalData, // }; var b = BlittableSprings[i]; - BlittableSprings[i] = new BlittableSpring - { - centerTransformIndex = b.centerTransformIndex, - colliderSpan = b.colliderSpan, - logicSpan = b.logicSpan, - transformIndexOffset = b.transformIndexOffset, - ExternalData = externalData, - }; + 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]; } } } diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity b/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity index 77c4b9464..54855ea3b 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity @@ -232,7 +232,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 339774397} - m_RootOrder: 15 + m_RootOrder: 16 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -773,7 +773,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 339774397} - m_RootOrder: 4 + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1236,14 +1236,15 @@ RectTransform: - {fileID: 1621794411} - {fileID: 2009818432} - {fileID: 168425995} - - {fileID: 1307084561} - {fileID: 224350191} - {fileID: 1791103379} - {fileID: 1311520909} + - {fileID: 1307084561} - {fileID: 974864191} - {fileID: 1767706907} - {fileID: 1557052150} - {fileID: 1728528388} + - {fileID: 704896193} - {fileID: 597950322} - {fileID: 935566651} - {fileID: 634488421} @@ -1823,7 +1824,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 339774397} - m_RootOrder: 11 + m_RootOrder: 12 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1904,7 +1905,7 @@ RectTransform: - {fileID: 154330168} - {fileID: 1954133885} m_Father: {fileID: 339774397} - m_RootOrder: 17 + m_RootOrder: 18 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1991,7 +1992,7 @@ RectTransform: - {fileID: 2010083454} - {fileID: 1081455630} m_Father: {fileID: 339774397} - m_RootOrder: 13 + m_RootOrder: 14 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -2247,6 +2248,128 @@ MonoBehaviour: m_ChildScaleWidth: 0 m_ChildScaleHeight: 0 m_ReverseArrangement: 0 +--- !u!1 &704896192 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 704896193} + - component: {fileID: 704896196} + - component: {fileID: 704896195} + - component: {fileID: 704896194} + m_Layer: 5 + m_Name: ResetSpringBone + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &704896193 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 704896192} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 983782643} + m_Father: {fileID: 339774397} + m_RootOrder: 11 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 162, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &704896194 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 704896192} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 704896195} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &704896195 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 704896192} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &704896196 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 704896192} + m_CullTransparentMesh: 0 --- !u!1 &773923918 GameObject: m_ObjectHideFlags: 0 @@ -3398,7 +3521,7 @@ RectTransform: - {fileID: 175751363} - {fileID: 1904789319} m_Father: {fileID: 339774397} - m_RootOrder: 12 + m_RootOrder: 13 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -3485,6 +3608,88 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 974864190} m_CullTransparentMesh: 0 +--- !u!1 &983782642 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 983782643} + - component: {fileID: 983782645} + - component: {fileID: 983782644} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &983782643 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 983782642} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 704896193} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &983782644 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 983782642} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ResetSpring + +' +--- !u!222 &983782645 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 983782642} + m_CullTransparentMesh: 0 --- !u!1 &1007924635 GameObject: m_ObjectHideFlags: 0 @@ -4950,7 +5155,7 @@ RectTransform: m_Children: - {fileID: 910859648} m_Father: {fileID: 339774397} - m_RootOrder: 3 + m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -5147,7 +5352,7 @@ RectTransform: - {fileID: 1866921958} - {fileID: 1767669911} m_Father: {fileID: 339774397} - m_RootOrder: 6 + m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -5444,7 +5649,7 @@ RectTransform: - {fileID: 452923209} - {fileID: 2090837017} m_Father: {fileID: 339774397} - m_RootOrder: 16 + m_RootOrder: 17 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -6444,7 +6649,7 @@ RectTransform: - {fileID: 62367395} - {fileID: 1037763549} m_Father: {fileID: 339774397} - m_RootOrder: 14 + m_RootOrder: 15 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -6619,6 +6824,7 @@ MonoBehaviour: m_pastePose: {fileID: 1307084564} m_showBoxMan: {fileID: 1767706908} m_pauseSpringBone: {fileID: 1728528389} + m_resetSpringBone: {fileID: 704896194} m_enableLipSync: {fileID: 935566650} m_enableAutoBlink: {fileID: 634488422} m_enableAutoExpression: {fileID: 1767738855} @@ -6677,7 +6883,7 @@ RectTransform: - {fileID: 1166391799} - {fileID: 1140410864} m_Father: {fileID: 339774397} - m_RootOrder: 5 + m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs index c3ba3c2ec..f0f842ae2 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs @@ -30,6 +30,9 @@ namespace UniVRM10.VRM10Viewer [SerializeField] Toggle m_pauseSpringBone = default; + [SerializeField] + Button m_resetSpringBone = default; + [SerializeField] Toggle m_enableLipSync = default; @@ -255,6 +258,7 @@ namespace UniVRM10.VRM10Viewer m_openModel = buttons.First(x => x.name == "OpenModel"); m_openMotion = buttons.First(x => x.name == "OpenMotion"); m_pastePose = buttons.First(x => x.name == "PastePose"); + m_resetSpringBone = buttons.First(x => x.name == "ResetSpringBone"); #if UNITY_2022_3_OR_NEWER var toggles = GameObject.FindObjectsByType(FindObjectsSortMode.InstanceID); @@ -351,6 +355,7 @@ namespace UniVRM10.VRM10Viewer m_openModel.onClick.AddListener(OnOpenModelClicked); m_openMotion.onClick.AddListener(OnOpenMotionClicked); m_pastePose.onClick.AddListener(OnPastePoseClicked); + m_resetSpringBone.onClick.AddListener(OnResetSpringBoneClicked); // load initial bvh if (m_motion != null) @@ -490,6 +495,17 @@ namespace UniVRM10.VRM10Viewer } } + void OnResetSpringBoneClicked() + { + if (m_loaded != null) + { + if (m_loaded.Runtime != null) + { + m_loaded.Runtime.SpringBone.RestoreInitialTransform(); + } + } + } + static IMaterialDescriptorGenerator GetVrmMaterialDescriptorGenerator(bool useUrp) { if (useUrp) From d8735d89523d76e96ca37cf0ad40ed073440566a Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 17 Jul 2024 14:48:51 +0900 Subject: [PATCH 07/13] internal Vrm10RuntimeSpringBone.Vrm10RuntimeSpringBone --- .../Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs index 06863b2fc..9e5e82d55 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs @@ -28,7 +28,7 @@ namespace UniVRM10 set { m_fastSpringBoneBuffer.IsSpringBoneEnabled = value; } } - public Vrm10RuntimeSpringBone(Vrm10Instance instance) + internal Vrm10RuntimeSpringBone(Vrm10Instance instance) { m_instance = instance; From 3d00753c83d39ed5ef06b303d3408e22b10da29d Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 18 Jul 2024 12:50:13 +0900 Subject: [PATCH 08/13] remove simulateLastBone --- .../InputPorts/FastSpringBoneBufferBuilder.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs index 1e0c01ead..7c17a0869 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs @@ -22,7 +22,7 @@ namespace UniVRM10.FastSpringBones.System public readonly IDictionary TransformIndexMap; public readonly FastSpringBoneSpring[] Springs; - public FastSpringBoneBufferBuilder(FastSpringBoneSpring[] springs, bool simulateLastBone = false) + public FastSpringBoneBufferBuilder(FastSpringBoneSpring[] springs) { Springs = springs; Profiler.BeginSample("FastSpringBone.ConstructBuffers.BufferBuilder"); @@ -62,7 +62,7 @@ namespace UniVRM10.FastSpringBones.System logicSpan = new BlittableSpan { startIndex = BlittableJoints.Count, - count = simulateLastBone ? spring.joints.Length : spring.joints.Length - 1, + count = spring.joints.Length - 1, }, centerTransformIndex = spring.center ? TransformIndexMap[spring.center].Index : -1, }; @@ -75,21 +75,21 @@ namespace UniVRM10.FastSpringBones.System return blittable; })); BlittableJoints.AddRange(spring.joints - .Take(simulateLastBone ? spring.joints.Length : spring.joints.Length - 1).Select(joint => + .Take(spring.joints.Length - 1).Select(joint => { var blittable = joint.Joint; return blittable; })); - AddLogic(spring, simulateLastBone); + AddLogic(spring); } Profiler.EndSample(); } - public void AddLogic(FastSpringBoneSpring spring, bool simulateLastBone = false) + public void AddLogic(FastSpringBoneSpring spring) { - for (var i = 0; i < (simulateLastBone ? spring.joints.Length : spring.joints.Length - 1); ++i) + 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; @@ -114,8 +114,7 @@ namespace UniVRM10.FastSpringBones.System } var scale = tailJoint.HasValue ? tailJoint.Value.Transform.lossyScale : joint.Transform.lossyScale; - var localChildPosition = - new Vector3( + var localChildPosition = new Vector3( localPosition.x * scale.x, localPosition.y * scale.y, localPosition.z * scale.z From 80c2bb921c1c9b8b005ae6c1e373d5cef662a601 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 18 Jul 2024 12:57:54 +0900 Subject: [PATCH 09/13] TransformIndexMap to Array.IndexOf --- .../Vrm10Runtime/Vrm10RuntimeSpringBone .cs | 5 +++-- .../InputPorts/FastSpringBoneBufferBuilder.cs | 18 +++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs index 9e5e82d55..d55439841 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs @@ -143,9 +143,10 @@ namespace UniVRM10 public void RestoreInitialTransform() { // Spring の joint に対応する transform の回転を初期状態 - foreach (var (k, v) in m_initialData.TransformIndexMap) + for (int i = 0; i < m_initialData.Transforms.Length; ++i) { - k.localRotation = v.InitialLocalRotation; + var transform = m_initialData.Transforms[i]; + transform.localRotation = m_initialData.InitialLocalRotations[i]; } // 初期状態にしたtransformを使って spring logic を構築 diff --git a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs index 7c17a0869..5d348d1aa 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using Unity.Collections; @@ -14,12 +15,12 @@ namespace UniVRM10.FastSpringBones.System 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 IDictionary TransformIndexMap; public readonly FastSpringBoneSpring[] Springs; public FastSpringBoneBufferBuilder(FastSpringBoneSpring[] springs) @@ -43,12 +44,7 @@ namespace UniVRM10.FastSpringBones.System if (spring.center != null) transformHashSet.Add(spring.center); } Transforms = transformHashSet.ToArray(); - TransformIndexMap = Transforms.Select((trs, index) => (trs, index)) - .ToDictionary(tuple => tuple.trs, tuple => new TransformInfo - { - Index = tuple.index, - InitialLocalRotation = tuple.trs.localRotation, - }); + InitialLocalRotations = Transforms.Select(x => x.localRotation).ToArray(); foreach (var spring in springs) { @@ -64,14 +60,14 @@ namespace UniVRM10.FastSpringBones.System startIndex = BlittableJoints.Count, count = spring.joints.Length - 1, }, - centerTransformIndex = spring.center ? TransformIndexMap[spring.center].Index : -1, + centerTransformIndex = Array.IndexOf(Transforms, spring.center), }; BlittableSprings.Add(blittableSpring); BlittableColliders.AddRange(spring.colliders.Select(collider => { var blittable = collider.Collider; - blittable.transformIndex = TransformIndexMap[collider.Transform].Index; + blittable.transformIndex = Array.IndexOf(Transforms, collider.Transform); return blittable; })); BlittableJoints.AddRange(spring.joints @@ -127,8 +123,8 @@ namespace UniVRM10.FastSpringBones.System var parent = joint.Transform.parent; BlittableLogics.Add(new BlittableLogic { - headTransformIndex = TransformIndexMap[joint.Transform].Index, - parentTransformIndex = parent != null ? TransformIndexMap[parent].Index : -1, + headTransformIndex = Array.IndexOf(Transforms, joint.Transform), + parentTransformIndex = Array.IndexOf(Transforms, parent), currentTail = currentTail, prevTail = currentTail, localRotation = joint.DefaultLocalRotation, From 7f089f1dd8aa52aeafed06fbb8fee47fddf0c603 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 18 Jul 2024 13:42:02 +0900 Subject: [PATCH 10/13] =?UTF-8?q?FastSpringBoneBufferBuilder=20=E3=82=92?= =?UTF-8?q?=20FastSpringBoneBuffer.FastSpringBoneBuffer=20=E3=81=AB?= =?UTF-8?q?=E5=90=88=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Vrm10Runtime/Vrm10RuntimeSpringBone .cs | 24 +-- .../InputPorts/FastSpringBoneBuffer.cs | 153 +++++++++++++++-- .../InputPorts/FastSpringBoneBufferBuilder.cs | 161 ------------------ .../FastSpringBoneBufferBuilder.cs.meta | 11 -- 4 files changed, 155 insertions(+), 194 deletions(-) delete mode 100644 Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs delete mode 100644 Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs.meta 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: From 02db0d3ba03e848cdcc3717c7414f4bea227d675 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 18 Jul 2024 13:54:56 +0900 Subject: [PATCH 11/13] setter --- .../Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs index 587fc21d0..b0e4309f8 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs @@ -20,12 +20,12 @@ namespace UniVRM10 public Vector3 ExternalForce { get => m_fastSpringBoneBuffer.ExternalForce; - set { m_fastSpringBoneBuffer.ExternalForce = value; } + set => m_fastSpringBoneBuffer.ExternalForce = value; } public bool IsSpringBoneEnabled { get => m_fastSpringBoneBuffer.IsSpringBoneEnabled; - set { m_fastSpringBoneBuffer.IsSpringBoneEnabled = value; } + set => m_fastSpringBoneBuffer.IsSpringBoneEnabled = value; } internal Vrm10RuntimeSpringBone(Vrm10Instance instance) @@ -72,7 +72,7 @@ namespace UniVRM10 m_fastSpringBoneBuffer.Dispose(); } - // create + // create(Spring情報の再収集。設定変更の反映) m_springs = m_instance.SpringBone.Springs.Select(spring => new FastSpringBoneSpring { center = spring.Center, @@ -105,8 +105,10 @@ namespace UniVRM10 }).ToArray(), }).ToArray(); + // 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(); } @@ -155,7 +157,6 @@ namespace UniVRM10 { FastSpringBoneBuffer.AddLogic(m_fastSpringBoneBuffer.Transforms, blittableLogics, spring); } - // DOTS バッファーを更新 m_fastSpringBoneBuffer.SyncAndZeroVelocity(blittableLogics); } From 1d2fed7e1855bd62e6f3a636703318dfbb12a8fa Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 18 Jul 2024 16:55:48 +0900 Subject: [PATCH 12/13] remove unsafe --- .../Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs index 5e26d473d..e1b8f5027 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs @@ -203,7 +203,7 @@ namespace UniVRM10.FastSpringBones.System _externalData.Dispose(); } - public unsafe void SyncAndZeroVelocity(IReadOnlyList logics) + public void SyncAndZeroVelocity(IReadOnlyList logics) { var dst = Logics; for (int i = 0; i < logics.Count; ++i) From 4dc5aae73cfe2be50bc288ef74d442e405943232 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 18 Jul 2024 17:13:31 +0900 Subject: [PATCH 13/13] AddLogic to LogicFromTransform --- .../Vrm10Runtime/Vrm10RuntimeSpringBone .cs | 3 ++- .../InputPorts/FastSpringBoneBuffer.cs | 21 ++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs index b0e4309f8..2820b1e49 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs @@ -155,7 +155,8 @@ namespace UniVRM10 List blittableLogics = new(); foreach (var spring in m_springs) { - FastSpringBoneBuffer.AddLogic(m_fastSpringBoneBuffer.Transforms, blittableLogics, spring); + blittableLogics.AddRange( + FastSpringBoneBuffer.LogicFromTransform(m_fastSpringBoneBuffer.Transforms, spring)); } // DOTS バッファーを更新 m_fastSpringBoneBuffer.SyncAndZeroVelocity(blittableLogics); diff --git a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs index e1b8f5027..6d1c55c8b 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBuffer.cs @@ -127,7 +127,7 @@ namespace UniVRM10.FastSpringBones.System return blittable; })); - AddLogic(Transforms, blittableLogics, spring); + blittableLogics.AddRange(LogicFromTransform(Transforms, spring)); } Springs = new NativeArray(blittableSprings.ToArray(), Allocator.Persistent); @@ -138,9 +138,17 @@ namespace UniVRM10.FastSpringBones.System Profiler.EndSample(); } - static public void AddLogic(Transform[] Transforms, List BlittableLogics, FastSpringBoneSpring spring) + /// + /// Transform の現状から Logic を作成する。 + /// + /// + /// + /// joint index + /// + public static IEnumerable LogicFromTransform(Transform[] Transforms, FastSpringBoneSpring spring) { - for (var i = 0; i < spring.joints.Length - 1; ++i) + // vrm-1.0 では末端の joint は tail で処理対象でないのに注意! + for (int 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; @@ -177,17 +185,16 @@ namespace UniVRM10.FastSpringBones.System : worldChildPosition; var parent = joint.Transform.parent; - - BlittableLogics.Add(new BlittableLogic + yield return new BlittableLogic { headTransformIndex = Array.IndexOf(Transforms, joint.Transform), parentTransformIndex = Array.IndexOf(Transforms, parent), currentTail = currentTail, - prevTail = currentTail, + prevTail = currentTail, // same with currentTail. velocity zero. localRotation = joint.DefaultLocalRotation, boneAxis = localChildPosition.normalized, length = localChildPosition.magnitude - }); + }; } }