From 9e18ee5bafdbba5fc9dec2af2b1ab968e28a8311 Mon Sep 17 00:00:00 2001 From: Yamo4490 Date: Thu, 15 May 2025 00:19:38 +0900 Subject: [PATCH] =?UTF-8?q?ADD:=20=EC=95=BC=EB=AA=A8=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A6=BD=ED=8A=B8=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Common/Scripts/MagicaCloth2Example.asmdef | 25 + .../Scripts/MagicaCloth2Example.asmdef.meta | 7 + .../Common/Scripts/SimpleInput.cs | 196 ++ .../Common/Scripts/SimpleInput.cs.meta} | 2 +- .../DemoScenes_Unity_6.1_or_Higher.meta} | 2 +- .../HighDefinition3D.meta} | 2 +- .../RuntimeBuild_HighDefinition3D.unity | 3 + .../RuntimeBuild_HighDefinition3D.unity.meta | 7 + .../RuntimeDressUp_HighDefinition3D.unity | 3 + ...RuntimeDressUp_HighDefinition3D.unity.meta | 7 + .../UnityChanKAGURA_HighDefinition3D.unity | 3 + ...nityChanKAGURA_HighDefinition3D.unity.meta | 7 + .../Wind_HighDefinition3D.unity | 3 + .../Wind_HighDefinition3D.unity.meta | 7 + .../Universal3D.meta | 8 + .../RuntimeBuild_Universal3D.unity | 3 + .../RuntimeBuild_Universal3D.unity.meta | 7 + .../RuntimeDressUp_Universal3D.unity | 3 + .../RuntimeDressUp_Universal3D.unity.meta | 7 + .../UnityChanKAGURA_Universal3D.unity | 3 + .../UnityChanKAGURA_Universal3D.unity.meta | 7 + .../Universal3D/Wind_Universal3D.unity | 3 + .../Universal3D/Wind_Universal3D.unity.meta | 7 + .../Res/Preset/MC2_Preset_SoftSkirt.json | 3 + .../Res/Preset/MC2_Preset_SoftSkirt.json.meta | 7 + .../Core/Cloth/ClothInitSerializeData.cs | 211 ++ .../Cloth/ClothInitSerializeData.cs.meta} | 2 +- .../Scripts/Core/Cloth/ClothMeshWriteMode.cs | 25 + .../Core/Cloth/ClothMeshWriteMode.cs.meta | 11 + .../Cloth/Collider/ColliderSymmetryMode.cs | 52 + .../Collider/ColliderSymmetryMode.cs.meta | 11 + .../Cloth/MagicaClothAnimationProperty.cs | 130 + .../MagicaClothAnimationProperty.cs.meta | 11 + .../Core/Manager/Cloth/PreBuildManager.cs | 301 +++ .../Manager/Cloth/PreBuildManager.cs.meta | 11 + .../Render/RenderSetupDataSerialization.cs | 202 ++ .../RenderSetupDataSerialization.cs.meta | 11 + .../Render/RenderSetupSerializeData.cs | 356 +++ .../Render/RenderSetupSerializeData.cs.meta | 11 + .../Simulation/SimulationManagerNormal.cs | 1769 +++++++++++++ .../SimulationManagerNormal.cs.meta | 11 + .../Simulation/SimulationManagerSplit.cs | 2335 +++++++++++++++++ .../Simulation/SimulationManagerSplit.cs.meta | 11 + .../TransformDataSerialization.cs | 117 + .../TransformDataSerialization.cs.meta | 11 + .../TransformRecordSerializeData.cs | 82 + .../TransformRecordSerializeData.cs.meta | 11 + .../MagicaCloth2/Scripts/Core/PreBuild.meta | 8 + .../Core/PreBuild/PreBuildScriptableObject.cs | 64 + .../PreBuild/PreBuildScriptableObject.cs.meta | 11 + .../Core/PreBuild/PreBuildSerializeData.cs | 101 + .../PreBuild/PreBuildSerializeData.cs.meta | 11 + .../Core/PreBuild/SharePreBuildData.cs | 69 + .../Core/PreBuild/SharePreBuildData.cs.meta | 11 + .../Core/PreBuild/UniquePreBuildData.cs | 49 + .../Core/PreBuild/UniquePreBuildData.cs.meta | 11 + .../NativeParallelHashMapExtensions.cs | 30 + .../NativeParallelHashMapExtensions.cs.meta | 11 + .../Function/VirtualMeshSerialization.cs | 291 ++ .../Function/VirtualMeshSerialization.cs.meta | 11 + .../Core/VirtualMesh/VirtualMeshContainer.cs | 60 + .../VirtualMesh/VirtualMeshContainer.cs.meta | 11 + .../Scripts/Editor/Cloth/MagicaEditorBase.cs | 40 + .../Editor/Cloth/MagicaEditorBase.cs.meta | 11 + .../SharePreBuildDataDrawer.cs | 76 + .../SharePreBuildDataDrawer.cs.meta | 11 + .../MagicaCloth2/Scripts/Editor/PreBuild.meta | 8 + .../Editor/PreBuild/PreBuildDataCreation.cs | 514 ++++ .../PreBuild/PreBuildDataCreation.cs.meta | 11 + Assets/External/VRCDeveloperTool.meta | 8 + Assets/External/YAMOScripts.meta | 8 + .../FindUnusedBones/FindUnusedBones.cs | 109 - .../ObjectNameChanger/ObjectNameChanger.cs | 99 - 73 files changed, 7456 insertions(+), 212 deletions(-) create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs rename Assets/{Scripts/Utility/ObjectNameChanger/ObjectNameChanger.cs.meta => External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs.meta} (83%) rename Assets/{Scripts/Utility/FindUnusedBones.meta => External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher.meta} (77%) rename Assets/{Scripts/Utility/ObjectNameChanger.meta => External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D.meta} (77%) create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeBuild_HighDefinition3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeBuild_HighDefinition3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeDressUp_HighDefinition3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeDressUp_HighDefinition3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/UnityChanKAGURA_HighDefinition3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/UnityChanKAGURA_HighDefinition3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/Wind_HighDefinition3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/Wind_HighDefinition3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeBuild_Universal3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeBuild_Universal3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeDressUp_Universal3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeDressUp_Universal3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/UnityChanKAGURA_Universal3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/UnityChanKAGURA_Universal3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/Wind_Universal3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/Wind_Universal3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSkirt.json create mode 100644 Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSkirt.json.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs rename Assets/{Scripts/Utility/FindUnusedBones/FindUnusedBones.cs.meta => External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs.meta} (83%) create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothMeshWriteMode.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothMeshWriteMode.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderSymmetryMode.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderSymmetryMode.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAnimationProperty.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAnimationProperty.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/PreBuildManager.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/PreBuildManager.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupDataSerialization.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupDataSerialization.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupSerializeData.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupSerializeData.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerNormal.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerNormal.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/PreBuild.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs.meta create mode 100644 Assets/External/VRCDeveloperTool.meta create mode 100644 Assets/External/YAMOScripts.meta delete mode 100644 Assets/Scripts/Utility/FindUnusedBones/FindUnusedBones.cs delete mode 100644 Assets/Scripts/Utility/ObjectNameChanger/ObjectNameChanger.cs diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef new file mode 100644 index 0000000..f0713e7 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef @@ -0,0 +1,25 @@ +{ + "name": "MagicaCloth2Example", + "rootNamespace": "", + "references": [ + "MagicaClothV2", + "Unity.InputSystem" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [], + "autoReferenced": false, + "defineConstraints": [ + "MAGICACLOTH2" + ], + "versionDefines": [ + { + "name": "com.unity.inputsystem", + "expression": "1.0.0", + "define": "MC2_INPUTSYSTEM" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef.meta new file mode 100644 index 0000000..89f3e26 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5bc0ea054e216f5498d1a84885db7ab1 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs new file mode 100644 index 0000000..ab3496c --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs @@ -0,0 +1,196 @@ +// Magica Cloth 2. +// Copyright (c) 2025 MagicaSoft. +// https://magicasoft.jp +using UnityEngine; +#if MC2_INPUTSYSTEM +using UnityEngine.InputSystem; +using UnityEngine.InputSystem.EnhancedTouch; +#endif + +namespace MagicaCloth2 +{ + /// + /// InputManager/InputSystem入力切り替えラッパー + /// + public class SimpleInput + { +#if MC2_INPUTSYSTEM + // (New) Imput System + public static void Init() + { + EnhancedTouchSupport.Enable(); + } + + public static int touchCount + { + get + { + return UnityEngine.InputSystem.EnhancedTouch.Touch.activeTouches.Count; + } + } + + public static UnityEngine.Touch GetTouch(int index) + { + var touchData = new UnityEngine.Touch(); + + int count = UnityEngine.InputSystem.EnhancedTouch.Touch.activeTouches.Count; + if (index < count) + { + var touch = UnityEngine.InputSystem.EnhancedTouch.Touch.activeTouches[index]; + + // convert + touchData.fingerId = touch.finger.index; + touchData.position = touch.screenPosition; + touchData.deltaPosition = touch.delta; + switch (touch.phase) + { + case UnityEngine.InputSystem.TouchPhase.Canceled: + touchData.phase = UnityEngine.TouchPhase.Canceled; + break; + case UnityEngine.InputSystem.TouchPhase.Ended: + touchData.phase = UnityEngine.TouchPhase.Ended; + break; + case UnityEngine.InputSystem.TouchPhase.Moved: + touchData.phase = UnityEngine.TouchPhase.Moved; + break; + case UnityEngine.InputSystem.TouchPhase.Began: + touchData.phase = UnityEngine.TouchPhase.Began; + break; + } + } + + return touchData; + } + + public static bool GetKey(KeyCode key) + { + switch (key) + { + case KeyCode.Escape: + return Keyboard.current.escapeKey.isPressed; + default: + return false; + } + } + + public static bool GetKeyDown(KeyCode key) + { + switch (key) + { + case KeyCode.Backspace: + return Keyboard.current.backspaceKey.wasPressedThisFrame; + default: + return false; + } + } + + public static bool GetMouseButtonDown(int button) + { + switch (button) + { + case 0: + return Mouse.current.leftButton.wasPressedThisFrame; + case 1: + return Mouse.current.rightButton.wasPressedThisFrame; + case 2: + return Mouse.current.middleButton.wasPressedThisFrame; + default: + return false; + } + } + + public static bool GetMouseButtonUp(int button) + { + switch (button) + { + case 0: + return Mouse.current.leftButton.wasReleasedThisFrame; + case 1: + return Mouse.current.rightButton.wasReleasedThisFrame; + case 2: + return Mouse.current.middleButton.wasReleasedThisFrame; + default: + return false; + } + } + + public static Vector3 mousePosition + { + get + { + return Mouse.current.position.ReadValue(); + } + } + + public static float GetMouseScrollWheel() + { + // 古いInputSystemに不具合あり + // ホイールデルタがデフォルトでx120されて返ってくる + // これはWindowsのみの挙動でMac/Linuxでは発生しない + // そしてUnity 2023.2以降は修正された + + float value = Mouse.current.scroll.ReadValue().y * 0.12f; // base +#if UNITY_2023_2_OR_NEWER + return value; +#else +#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN + return value / 120.0f; // ホイールデルタの不具合を吸収 +#else + return value; +#endif +#endif + } +#else + // (Old) Imput Manager + public static void Init() + { + } + + public static int touchCount + { + get + { + return Input.touchCount; + } + } + + public static Touch GetTouch(int index) + { + return Input.GetTouch(index); + } + + public static bool GetKey(KeyCode key) + { + return Input.GetKey(key); + } + + public static bool GetKeyDown(KeyCode key) + { + return Input.GetKeyDown(key); + } + + public static bool GetMouseButtonDown(int button) + { + return Input.GetMouseButtonDown(button); + } + + public static bool GetMouseButtonUp(int button) + { + return Input.GetMouseButtonUp(button); + } + + public static Vector3 mousePosition + { + get + { + return Input.mousePosition; + } + } + + public static float GetMouseScrollWheel() + { + return Input.GetAxis("Mouse ScrollWheel"); + } +#endif + } +} diff --git a/Assets/Scripts/Utility/ObjectNameChanger/ObjectNameChanger.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs.meta similarity index 83% rename from Assets/Scripts/Utility/ObjectNameChanger/ObjectNameChanger.cs.meta rename to Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs.meta index f78a9db..fd2c19f 100644 --- a/Assets/Scripts/Utility/ObjectNameChanger/ObjectNameChanger.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9334313e83f924348a48a1da0b4c1cb9 +guid: ab72fcfec8965ae4181307a06400b57b MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/Scripts/Utility/FindUnusedBones.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher.meta similarity index 77% rename from Assets/Scripts/Utility/FindUnusedBones.meta rename to Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher.meta index 849cb88..74824a6 100644 --- a/Assets/Scripts/Utility/FindUnusedBones.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c5abe9243ed7c7545bfe1ccdbaa8c8b7 +guid: 20f694a56cb3ba842b35402189c3b2f6 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/Scripts/Utility/ObjectNameChanger.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D.meta similarity index 77% rename from Assets/Scripts/Utility/ObjectNameChanger.meta rename to Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D.meta index 4a5b6dc..a52c053 100644 --- a/Assets/Scripts/Utility/ObjectNameChanger.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 0c4999626de3e0d4692c31a1511fec66 +guid: 098d9df8397d80f45baed0214420d1cf folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeBuild_HighDefinition3D.unity b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeBuild_HighDefinition3D.unity new file mode 100644 index 0000000..3f6cc57 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeBuild_HighDefinition3D.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1344538bb448c3f15d0aa4c3ccf0527dbe7cea8b115f959fecdb099f9e40c58d +size 35742 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeBuild_HighDefinition3D.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeBuild_HighDefinition3D.unity.meta new file mode 100644 index 0000000..4239d14 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeBuild_HighDefinition3D.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8a0637df5c1ee8a4d8d6c5d2f3807cde +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeDressUp_HighDefinition3D.unity b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeDressUp_HighDefinition3D.unity new file mode 100644 index 0000000..c23bafb --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeDressUp_HighDefinition3D.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:425ee3749faad5217ec23076fe0ec0a8dba02c1e24e64d425f87cab0e1d4ced3 +size 38769 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeDressUp_HighDefinition3D.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeDressUp_HighDefinition3D.unity.meta new file mode 100644 index 0000000..a8717bc --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeDressUp_HighDefinition3D.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 30700d501f109174891f340ae1fc1833 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/UnityChanKAGURA_HighDefinition3D.unity b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/UnityChanKAGURA_HighDefinition3D.unity new file mode 100644 index 0000000..7156452 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/UnityChanKAGURA_HighDefinition3D.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:73cb2e8ccc8c4db1d827759ef27c59305c8e40160b46a3788ae65706ba821f0c +size 35263 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/UnityChanKAGURA_HighDefinition3D.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/UnityChanKAGURA_HighDefinition3D.unity.meta new file mode 100644 index 0000000..36cc847 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/UnityChanKAGURA_HighDefinition3D.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ca2d4f8e19e54d642bbc386701570fd4 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/Wind_HighDefinition3D.unity b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/Wind_HighDefinition3D.unity new file mode 100644 index 0000000..244111f --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/Wind_HighDefinition3D.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7aea3460aabbbee2de0bcb7b926a64e0187975a7e24f265bb57a57252d86e30b +size 44593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/Wind_HighDefinition3D.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/Wind_HighDefinition3D.unity.meta new file mode 100644 index 0000000..07d555c --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/Wind_HighDefinition3D.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8ef5d38bbe84ef44cb76386cf579b78d +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D.meta new file mode 100644 index 0000000..c51f6ec --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ee41de38686ef9b439643dd695fd9f9d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeBuild_Universal3D.unity b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeBuild_Universal3D.unity new file mode 100644 index 0000000..6571ff9 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeBuild_Universal3D.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb85169ab67c2f674187b692f0efe495f7ee2f6f2723132ddec09dc0e6d60fde +size 27478 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeBuild_Universal3D.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeBuild_Universal3D.unity.meta new file mode 100644 index 0000000..627c2af --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeBuild_Universal3D.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9d96bb6c1a7bbf14b95fba198bd36558 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeDressUp_Universal3D.unity b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeDressUp_Universal3D.unity new file mode 100644 index 0000000..18f566a --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeDressUp_Universal3D.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bfc77efbc86c3ba7859690d352fb5b0a81febd4dc8f30d38846819e0d4c6d74a +size 30517 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeDressUp_Universal3D.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeDressUp_Universal3D.unity.meta new file mode 100644 index 0000000..b0bf5a7 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeDressUp_Universal3D.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 01f984873de94d845a6f0dad6e1764ce +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/UnityChanKAGURA_Universal3D.unity b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/UnityChanKAGURA_Universal3D.unity new file mode 100644 index 0000000..c9715c2 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/UnityChanKAGURA_Universal3D.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf136fcfed91b4bf1b09194afdbda5cf3446527584d73ea128f0b86fb8bec9b9 +size 23282 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/UnityChanKAGURA_Universal3D.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/UnityChanKAGURA_Universal3D.unity.meta new file mode 100644 index 0000000..a8d5fa8 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/UnityChanKAGURA_Universal3D.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 54b38eb7d538c7f44b7fd7a9df0478d3 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/Wind_Universal3D.unity b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/Wind_Universal3D.unity new file mode 100644 index 0000000..e0bd9e1 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/Wind_Universal3D.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d36cd32becfcb97c511df00aa9e6f2c9b43a908600d68ffc4de28505eaf19b05 +size 34225 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/Wind_Universal3D.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/Wind_Universal3D.unity.meta new file mode 100644 index 0000000..6eee29f --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/Wind_Universal3D.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 44a8005bc0be2894fb5f7cec86f3eeae +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSkirt.json b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSkirt.json new file mode 100644 index 0000000..4a608d3 --- /dev/null +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSkirt.json @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08cc9455ecf800a606e73203f9c84603701e66a20348127da80a97a40420c9c7 +size 6575 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSkirt.json.meta b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSkirt.json.meta new file mode 100644 index 0000000..666b4a8 --- /dev/null +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSkirt.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 95115815f2f656045acda9f116a05915 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs new file mode 100644 index 0000000..7e3e4ab --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs @@ -0,0 +1,211 @@ +// Magica Cloth 2. +// Copyright (c) 2025 MagicaSoft. +// https://magicasoft.jp +using System.Collections.Generic; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// 初期化データ + /// + [System.Serializable] + public class ClothInitSerializeData : ITransform + { + public const int InitDataVersion = 2; + + public int initVersion; + public int localHash; + public int globalHash; + public ClothProcess.ClothType clothType; + public TransformRecordSerializeData clothTransformRecord; + public TransformRecordSerializeData normalAdjustmentTransformRecord; + public List customSkinningBoneRecords; + public List clothSetupDataList; + + public bool HasData() + { + if (initVersion == 0) + return false; + if (localHash == 0 || globalHash == 0) + return false; + + return true; + } + + public void Clear() + { + initVersion = 0; + localHash = 0; + globalHash = 0; + clothType = ClothProcess.ClothType.MeshCloth; + clothTransformRecord = new TransformRecordSerializeData(); + normalAdjustmentTransformRecord = new TransformRecordSerializeData(); + customSkinningBoneRecords = new List(); + clothSetupDataList = new List(); + } + + public ResultCode DataValidate(ClothProcess cprocess) + { + if (localHash == 0 || globalHash == 0) + return new ResultCode(Define.Result.InitSerializeData_InvalidHash); + if (initVersion == 0) + return new ResultCode(Define.Result.InitSerializeData_InvalidVersion); + + if (clothSetupDataList == null || clothSetupDataList.Count == 0) + return new ResultCode(Define.Result.InitSerializeData_InvalidSetupData); + + var cloth = cprocess.cloth; + var sdata = cloth.SerializeData; + + if (clothType != sdata.clothType) + return new ResultCode(Define.Result.InitSerializeData_ClothTypeMismatch); + + if (clothType == ClothProcess.ClothType.MeshCloth) + { + int rendererCount = sdata.sourceRenderers.Count; + if (clothSetupDataList.Count != rendererCount) + return new ResultCode(Define.Result.InitSerializeData_SetupCountMismatch); + + // 各レンダラー情報の検証 + for (int i = 0; i < rendererCount; i++) + { + if (clothSetupDataList[i].DataValidateMeshCloth(sdata.sourceRenderers[i]) == false) + return new ResultCode(Define.Result.InitSerializeData_MeshClothSetupValidationError); + } + } + else if (clothType == ClothProcess.ClothType.BoneCloth) + { + if (clothSetupDataList.Count != 1) + return new ResultCode(Define.Result.InitSerializeData_SetupCountMismatch); + + if (clothSetupDataList[0].DataValidateBoneCloth(sdata, RenderSetupData.SetupType.BoneCloth) == false) + return new ResultCode(Define.Result.InitSerializeData_BoneClothSetupValidationError); + } + else if (clothType == ClothProcess.ClothType.BoneSpring) + { + if (clothSetupDataList.Count != 1) + return new ResultCode(Define.Result.InitSerializeData_SetupCountMismatch); + + if (clothSetupDataList[0].DataValidateBoneCloth(sdata, RenderSetupData.SetupType.BoneSpring) == false) + return new ResultCode(Define.Result.InitSerializeData_BoneSpringSetupValidationError); + } + + // カスタムスキニングボーン + if (sdata.customSkinningSetting.skinningBones.Count != customSkinningBoneRecords.Count) + return new ResultCode(Define.Result.InitSerializeData_CustomSkinningBoneCountMismatch); + + // V1かつMeshClothかつSkinnedMeshRendererの場合のみ、(Clone)メッシュ利用時は無効とする + // これは(Clone)メッシュを再度加工することによりボーンウエイトなどのデータがおかしくなりエラーが発生するため + if (initVersion <= 1 && clothType == ClothProcess.ClothType.MeshCloth) + { + for (int i = 0; i < sdata.sourceRenderers.Count; i++) + { + SkinnedMeshRenderer sren = sdata.sourceRenderers[i] as SkinnedMeshRenderer; + if (sren && sren.sharedMesh && sren.sharedMesh.name.Contains("(Clone)")) + { + return new ResultCode(Define.Result.InitSerializeData_InvalidCloneMesh); + } + } + } + + return ResultCode.Success; + } + + public bool Serialize( + ClothSerializeData sdata, + TransformRecord clothTransformRecord, + TransformRecord normalAdjustmentTransformRecord, + List setupList + ) + { + initVersion = InitDataVersion; // version + + clothType = sdata.clothType; + + this.clothTransformRecord = new TransformRecordSerializeData(); + this.clothTransformRecord.Serialize(clothTransformRecord); + + this.normalAdjustmentTransformRecord = new TransformRecordSerializeData(); + this.normalAdjustmentTransformRecord.Serialize(normalAdjustmentTransformRecord); + + // カスタムスキニングボーン + customSkinningBoneRecords = new List(); + int bcnt = sdata.customSkinningSetting.skinningBones.Count; + for (int i = 0; i < bcnt; i++) + { + var tr = new TransformRecord(sdata.customSkinningSetting.skinningBones[i], read: true); + var trs = new TransformRecordSerializeData(); + trs.Serialize(tr); + customSkinningBoneRecords.Add(trs); + } + + // setup data + clothSetupDataList = new List(); + if (setupList != null && setupList.Count > 0) + { + foreach (var setup in setupList) + { + var meshSetupData = new RenderSetupSerializeData(); + meshSetupData.Serialize(setup); + clothSetupDataList.Add(meshSetupData); + } + } + + localHash = GetLocalHash(); + globalHash = GetGlobalHash(); + + return true; + } + + + public void GetUsedTransform(HashSet transformSet) + { + clothTransformRecord?.GetUsedTransform(transformSet); + normalAdjustmentTransformRecord?.GetUsedTransform(transformSet); + customSkinningBoneRecords?.ForEach(x => x.GetUsedTransform(transformSet)); + clothSetupDataList?.ForEach(x => x.GetUsedTransform(transformSet)); + } + + public void ReplaceTransform(Dictionary replaceDict) + { + clothTransformRecord?.ReplaceTransform(replaceDict); + normalAdjustmentTransformRecord?.ReplaceTransform(replaceDict); + customSkinningBoneRecords?.ForEach(x => x.ReplaceTransform(replaceDict)); + clothSetupDataList?.ForEach(x => x.ReplaceTransform(replaceDict)); + } + + int GetLocalHash() + { + // ローカルハッシュ + // ・編集用メッシュが再構築されるたびにこのハッシュで保存チェックされる + // ・各種カウント+配列数 + // ・Transformの姿勢は無視する。ただし階層構造の変更は見る + int hash = 0; + hash += initVersion * 9876; + hash += (int)clothType * 5656; + hash += clothTransformRecord?.GetLocalHash() ?? 0; + hash += normalAdjustmentTransformRecord?.GetLocalHash() ?? 0; + customSkinningBoneRecords?.ForEach(x => hash += x?.GetLocalHash() ?? 0); + clothSetupDataList?.ForEach(x => hash += x?.GetLocalHash() ?? 0); + + return hash; + } + + int GetGlobalHash() + { + // グローバルハッシュ + // ・頂点ペイント終了時にこのハッシュで保存チェックされる + // ・保存チェックにはローカルハッシュも含まれる + // ・Transformのローカル姿勢を見る(localPosition/localRotation/localScale) + // ・ただしSetupDataのinitRenderScaleのみワールドスケールをチェックする + int hash = 0; + hash += clothTransformRecord?.GetGlobalHash() ?? 0; + hash += normalAdjustmentTransformRecord?.GetGlobalHash() ?? 0; + customSkinningBoneRecords?.ForEach(x => hash += x?.GetGlobalHash() ?? 0); + clothSetupDataList?.ForEach(x => hash += x?.GetGlobalHash() ?? 0); + + return hash; + } + } +} diff --git a/Assets/Scripts/Utility/FindUnusedBones/FindUnusedBones.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs.meta similarity index 83% rename from Assets/Scripts/Utility/FindUnusedBones/FindUnusedBones.cs.meta rename to Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs.meta index 97ddfc1..aafa827 100644 --- a/Assets/Scripts/Utility/FindUnusedBones/FindUnusedBones.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 893eb3d42574b394d82065f5781ac45f +guid: 87cb8cdfb6686334d904a1e0c0536944 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothMeshWriteMode.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothMeshWriteMode.cs new file mode 100644 index 0000000..f32a33a --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothMeshWriteMode.cs @@ -0,0 +1,25 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp + +namespace MagicaCloth2 +{ + /// + /// メッシュへの書き込み対象 + /// Write target to mesh. + /// + public enum ClothMeshWriteMode + { + /// + /// 位置と法線 + /// Position, Normal + /// + PositionAndNormal = 0, + + /// + /// 位置と法線と接線 + /// Position, Normal, Tangent + /// + PositionAndNormalTangent = 1, + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothMeshWriteMode.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothMeshWriteMode.cs.meta new file mode 100644 index 0000000..54e6476 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothMeshWriteMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c89429b06b0fde045af1104d0fe4d6b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderSymmetryMode.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderSymmetryMode.cs new file mode 100644 index 0000000..7be93a1 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderSymmetryMode.cs @@ -0,0 +1,52 @@ +// Magica Cloth 2. +// Copyright (c) 2025 MagicaSoft. +// https://magicasoft.jp +namespace MagicaCloth2 +{ + /// + /// シンメトリーモード + /// Symmetry mode. + /// + public enum ColliderSymmetryMode + { + None = 0, + + /// + /// 人体の骨格を参照しすべて自動設定する + /// キャラクターにAnimatorコンポーネントが必要です + /// Automatically set everything based on the human skeleton. + /// Character must have an Animator component. + /// + AutomaticHumanBody = 1, + + /// + /// SymmetryTargetの姿勢から自動設定します + /// Automatically set based on the SymmetryTarget's posture. + /// + AutomaticTarget = 2, + + /// + /// X軸を左右対称 + /// Symmetry on the X axis. + /// + X_Symmetry = 100, + + /// + /// Y軸を左右対称 + /// Symmetry on the Y axis. + /// + Y_Symmetry = 101, + + /// + /// Z軸を左右対称 + /// Symmetry on the Z axis. + /// + Z_Symmetry = 102, + + /// + /// XYZ軸を左右対称 + /// Symmetry on the XYZ axis. + /// + XYZ_Symmetry = 200, + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderSymmetryMode.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderSymmetryMode.cs.meta new file mode 100644 index 0000000..e95b05f --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderSymmetryMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 02f9b444838ae8a41916aab95109474e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAnimationProperty.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAnimationProperty.cs new file mode 100644 index 0000000..88e3882 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAnimationProperty.cs @@ -0,0 +1,130 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp + +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// プロパティをアニメーションから制御するためのラッパー. + /// Wrapper for controlling properties from animation. + /// + public partial class MagicaCloth + { + [HideInInspector] + public float animationPoseRatioProperty; + float _animationPoseRatioProperty; + + [HideInInspector] + public float gravityProperty; + float _gravityProperty; + + [HideInInspector] + public float dampingProperty; + float _dampingProperty; + + [HideInInspector] + public float worldInertiaProperty; + float _worldInertiaProperty; + + [HideInInspector] + public float localInertiaProperty; + float _localInertiaProperty; + + [HideInInspector] + public float windInfluenceProperty; + float _windInfluenceProperty; + + [HideInInspector] + public float blendWeightProperty; + float _blendWeightProperty; + + //========================================================================================= + internal void InitAnimationProperty() + { + animationPoseRatioProperty = serializeData.animationPoseRatio; + _animationPoseRatioProperty = animationPoseRatioProperty; + + gravityProperty = serializeData.gravity; + _gravityProperty = gravityProperty; + + dampingProperty = serializeData.damping.value; + _dampingProperty = dampingProperty; + + worldInertiaProperty = serializeData.inertiaConstraint.worldInertia; + _worldInertiaProperty = worldInertiaProperty; + + localInertiaProperty = serializeData.inertiaConstraint.localInertia; + _localInertiaProperty = localInertiaProperty; + + windInfluenceProperty = serializeData.wind.influence; + _windInfluenceProperty = windInfluenceProperty; + + blendWeightProperty = serializeData.blendWeight; + _blendWeightProperty = blendWeightProperty; + } + + /// + /// アニメーションによりMagicaClothのプロパティが変更されたときに呼び出される. + /// Called when a property of MagicaCloth changes due to animation. + /// + void OnDidApplyAnimationProperties() + { + if (Application.isPlaying) + { + //Debug.Log($"Animated property changes. F:{Time.frameCount}"); + + if (animationPoseRatioProperty != _animationPoseRatioProperty) + { + _animationPoseRatioProperty = animationPoseRatioProperty; + serializeData.animationPoseRatio = animationPoseRatioProperty; + SetParameterChange(); + } + + if (gravityProperty != _gravityProperty) + { + _gravityProperty = gravityProperty; + serializeData.gravity = gravityProperty; + SetParameterChange(); + } + + if (dampingProperty != _dampingProperty) + { + _dampingProperty = dampingProperty; + serializeData.damping.value = dampingProperty; + SetParameterChange(); + } + + if (worldInertiaProperty != _worldInertiaProperty) + { + _worldInertiaProperty = worldInertiaProperty; + serializeData.inertiaConstraint.worldInertia = worldInertiaProperty; + SetParameterChange(); + } + + if (localInertiaProperty != _localInertiaProperty) + { + _localInertiaProperty = localInertiaProperty; + serializeData.inertiaConstraint.localInertia = localInertiaProperty; + SetParameterChange(); + } + + if (windInfluenceProperty != _windInfluenceProperty) + { + _windInfluenceProperty = windInfluenceProperty; + serializeData.wind.influence = windInfluenceProperty; + SetParameterChange(); + } + + if (blendWeightProperty != _blendWeightProperty) + { + _blendWeightProperty = blendWeightProperty; + serializeData.blendWeight = blendWeightProperty; + SetParameterChange(); + } + } + } + } +} + diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAnimationProperty.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAnimationProperty.cs.meta new file mode 100644 index 0000000..7a473fc --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAnimationProperty.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fea7c53425d793a44b3d484072c68bde +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/PreBuildManager.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/PreBuildManager.cs new file mode 100644 index 0000000..a4436f7 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/PreBuildManager.cs @@ -0,0 +1,301 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using System.Collections.Generic; +using System.Text; +using Unity.Profiling; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// PreBuildの管理マネージャ + /// + public class PreBuildManager : IManager, IValid + { + /// + /// 共有ビルドデータの復元データ + /// + internal class ShareDeserializationData : IDisposable + { + internal string buildId; + internal ResultCode result; + internal int referenceCount; + + internal List renderSetupDataList = new List(); + internal VirtualMesh proxyMesh = null; + internal List renderMeshList = new List(); + + internal DistanceConstraint.ConstraintData distanceConstraintData; + internal TriangleBendingConstraint.ConstraintData bendingConstraintData; + internal InertiaConstraint.ConstraintData inertiaConstraintData; + + public void Dispose() + { + foreach (var data in renderSetupDataList) + { + if (data != null) + { + data.isManaged = false; + data.Dispose(); + } + } + renderSetupDataList.Clear(); + + if (proxyMesh != null) + { + proxyMesh.isManaged = false; + proxyMesh.Dispose(); + proxyMesh = null; + } + + foreach (var rmesh in renderMeshList) + { + if (rmesh != null) + { + rmesh.isManaged = false; + rmesh.Dispose(); + } + } + renderMeshList.Clear(); + + distanceConstraintData = null; + bendingConstraintData = null; + inertiaConstraintData = null; + + buildId = string.Empty; + result.Clear(); + referenceCount = 0; + } + + public void Deserialize(SharePreBuildData sharePreBuilddata) + { + result.SetProcess(); + + try + { + // データ検証 + var validataResult = sharePreBuilddata.DataValidate(); + if (validataResult.IsFaild()) + { + result.Merge(validataResult); + throw new MagicaClothProcessingException(); + } + + // Deserialize + foreach (var sdata in sharePreBuilddata.renderSetupDataList) + { + renderSetupDataList.Add(RenderSetupData.ShareDeserialize(sdata)); + } + proxyMesh = VirtualMesh.ShareDeserialize(sharePreBuilddata.proxyMesh); + foreach (var sdata in sharePreBuilddata.renderMeshList) + { + renderMeshList.Add(VirtualMesh.ShareDeserialize(sdata)); + } + distanceConstraintData = sharePreBuilddata.distanceConstraintData; + bendingConstraintData = sharePreBuilddata.bendingConstraintData; + inertiaConstraintData = sharePreBuilddata.inertiaConstraintData; + + result.SetSuccess(); + } + catch (MagicaClothProcessingException) + { + } + catch (Exception exception) + { + Debug.LogException(exception); + result.SetError(Define.Result.Deserialization_Exception); + } + } + + public int RenderMeshCount => renderMeshList?.Count ?? 0; + + public VirtualMeshContainer GetProxyMeshContainer() + { + return new VirtualMeshContainer() + { + shareVirtualMesh = proxyMesh, + uniqueData = null, + }; + } + + public VirtualMeshContainer GetRenderMeshContainer(int index) + { + if (index >= RenderMeshCount) + return null; + + return new VirtualMeshContainer() + { + shareVirtualMesh = renderMeshList[index], + uniqueData = null, + }; + } + } + + Dictionary deserializationDict = new Dictionary(); + bool isValid = false; + + //========================================================================================= + public void Dispose() + { + foreach (var kv in deserializationDict) + { + kv.Value.Dispose(); + } + deserializationDict.Clear(); + + isValid = false; + } + + public void EnterdEditMode() + { + Dispose(); + } + + public void Initialize() + { + isValid = true; + } + + public bool IsValid() + { + return isValid; + } + + public void InformationLog(StringBuilder allsb) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine($"========== PreBuild Manager =========="); + if (IsValid() == false) + { + sb.AppendLine($"PreBuild Manager. Invalid."); + } + else + { + int cnt = deserializationDict.Count; + sb.AppendLine($"Count:{cnt}"); + + foreach (var kv in deserializationDict) + { + sb.AppendLine($"[{kv.Key.buildId}] refcnt:{kv.Value.referenceCount}, result:{kv.Value.result.GetResultString()}, proxyMesh:{kv.Value.proxyMesh != null}"); + } + } + + sb.AppendLine(); + Debug.Log(sb.ToString()); + allsb.Append(sb); + } + + //========================================================================================= + static readonly ProfilerMarker deserializationProfiler = new ProfilerMarker("PreBuild.Deserialization"); + + /// + /// PreBuildDataをデシリアライズし登録する + /// すでに登録されていた場合は参照カウンタを加算する + /// + /// + /// + /// + internal ShareDeserializationData RegisterPreBuildData(SharePreBuildData sdata, bool referenceIncrement) + { + if (isValid == false) + return null; + if (sdata == null) + return null; + + if (deserializationDict.ContainsKey(sdata) == false) + { + deserializationProfiler.Begin(); + //var span = new TimeSpan($"Deserialization [{sdata.buildId}]"); + + // new + var data = new ShareDeserializationData(); + data.buildId = sdata.buildId; + + data.Deserialize(sdata); + + deserializationDict.Add(sdata, data); + + deserializationProfiler.End(); + //span.Log(); + + Develop.DebugLog($"RegisterPreBuildData.Deserialize [{sdata.buildId}] F:{Time.frameCount}"); + } + + var ddata = deserializationDict[sdata]; + + // reference counter + if (referenceIncrement) + ddata.referenceCount++; + + Develop.DebugLog($"RegisterPreBuildData [{sdata.buildId}] C:{ddata.referenceCount} F:{Time.frameCount}"); + + return ddata; + } + + internal ShareDeserializationData GetPreBuildData(SharePreBuildData sdata) + { + if (sdata == null) + return null; + + if (deserializationDict.ContainsKey(sdata)) + return deserializationDict[sdata]; + + return null; + } + + /// + /// PreBuildDataのデシリアライズデータを解除する + /// 参照カウンタが0でも破棄はしない + /// + /// + internal void UnregisterPreBuildData(SharePreBuildData sdata) + { + if (isValid == false) + return; + if (sdata == null) + return; + + if (deserializationDict.ContainsKey(sdata)) + { + var ddata = deserializationDict[sdata]; + + // reference counter + ddata.referenceCount--; + + Develop.DebugLog($"UnregisterPreBuildData [{sdata.buildId}] C:{ddata.referenceCount} F:{Time.frameCount}"); + } + else + { + Develop.DebugLogWarning($"UnregisterPreBuildData not found! [{sdata.buildId}]"); + } + } + + /// + /// 未使用のデシリアライズデータをすべて破棄する + /// + internal void UnloadUnusedData() + { + var removeKeys = new List(); + + foreach (var kv in deserializationDict) + { + if (kv.Value.referenceCount <= 0) + removeKeys.Add(kv.Key); + } + + foreach (var key in removeKeys) + { + var ddata = deserializationDict[key]; + ddata.Dispose(); + deserializationDict.Remove(key); + + Develop.DebugLog($"Unload pre-build deserialization data [{key.buildId}] F:{Time.frameCount}"); + } + removeKeys.Clear(); + + Develop.DebugLog($"Unload pre-build deserialization data count:{deserializationDict.Count} F:{Time.frameCount}"); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/PreBuildManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/PreBuildManager.cs.meta new file mode 100644 index 0000000..9cf8bc5 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/PreBuildManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 800b8846d5572fe438974d4af951c076 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupDataSerialization.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupDataSerialization.cs new file mode 100644 index 0000000..13e1cc1 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupDataSerialization.cs @@ -0,0 +1,202 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using System.Collections.Generic; +using Unity.Collections; +using UnityEngine; + +namespace MagicaCloth2 +{ + public partial class RenderSetupData + { + /// + /// PreBuildの共有部分保存データ + /// + [System.Serializable] + public class ShareSerializationData + { + public ResultCode result; + public string name; + public SetupType setupType; + + // Mesh --------------------------------------------------------------- + public Mesh originalMesh; + public int vertexCount; + public bool hasSkinnedMesh; + public bool hasBoneWeight; + public int skinRootBoneIndex; + public int skinBoneCount; + // MeshDataでは取得できないメッシュ情報 + public List bindPoseList; + public byte[] bonesPerVertexArray; + public byte[] boneWeightArray; + public Vector3[] localPositions; + public Vector3[] localNormals; + public Vector4[] localTangents; // option + + // Bone --------------------------------------------------------------- + public BoneConnectionMode boneConnectionMode; + + // Common ------------------------------------------------------------- + public int renderTransformIndex; + + // -------------------------------------------------------------------- + public bool HasTangent => localTangents?.Length > 0; + } + + public ShareSerializationData ShareSerialize() + { + var sdata = new ShareSerializationData(); + try + { + sdata.result = result; + sdata.name = name; + sdata.setupType = setupType; + + // Mesh + sdata.originalMesh = originalMesh; + sdata.vertexCount = vertexCount; + sdata.hasSkinnedMesh = hasSkinnedMesh; + sdata.hasBoneWeight = hasBoneWeight; + sdata.skinRootBoneIndex = skinRootBoneIndex; + sdata.skinBoneCount = skinBoneCount; + sdata.bindPoseList = new List(bindPoseList); + sdata.bonesPerVertexArray = bonesPerVertexArray.MC2ToRawBytes(); + sdata.boneWeightArray = boneWeightArray.MC2ToRawBytes(); + sdata.localPositions = originalMesh.vertices; + sdata.localNormals = originalMesh.normals; + if (originalMesh.HasVertexAttribute(UnityEngine.Rendering.VertexAttribute.Tangent)) + sdata.localTangents = originalMesh.tangents; + + // Bone + sdata.boneConnectionMode = boneConnectionMode; + + // Common + sdata.renderTransformIndex = renderTransformIndex; + } + catch (Exception exception) + { + Debug.LogException(exception); + } + + return sdata; + } + + public static RenderSetupData ShareDeserialize(ShareSerializationData sdata) + { + var setup = new RenderSetupData(); + setup.isManaged = true; + + try + { + setup.name = sdata.name; + setup.setupType = sdata.setupType; + + // Mesh + setup.originalMesh = sdata.originalMesh; + setup.vertexCount = sdata.vertexCount; + setup.hasSkinnedMesh = sdata.hasSkinnedMesh; + setup.hasBoneWeight = sdata.hasBoneWeight; + setup.skinRootBoneIndex = sdata.skinRootBoneIndex; + setup.skinBoneCount = sdata.skinBoneCount; + setup.bindPoseList = new List(sdata.bindPoseList); + setup.bonesPerVertexArray = NativeArrayExtensions.MC2FromRawBytes(sdata.bonesPerVertexArray, Allocator.Persistent); + setup.boneWeightArray = NativeArrayExtensions.MC2FromRawBytes(sdata.boneWeightArray, Allocator.Persistent); + + // PreBuildではmeshDataArrayを生成しない + // その代わりに保存したlocalPositions/Normalsを復元する + setup.localPositions = new NativeArray(sdata.localPositions, Allocator.Persistent); + setup.localNormals = new NativeArray(sdata.localNormals, Allocator.Persistent); + if (sdata.HasTangent) + setup.localTangents = new NativeArray(sdata.localTangents, Allocator.Persistent); + + // Bone + setup.boneConnectionMode = sdata.boneConnectionMode; + + // Common + setup.renderTransformIndex = sdata.renderTransformIndex; + + setup.result.SetSuccess(); + } + catch (Exception exception) + { + Debug.LogException(exception); + setup.result.SetError(Define.Result.PreBuild_InvalidRenderSetupData); + } + + return setup; + } + + //========================================================================================= + /// + /// PreBuild固有部分の保存データ + /// + [System.Serializable] + public class UniqueSerializationData : ITransform + { + public ResultCode result; + + // Mesh --------------------------------------------------------------- + public Renderer renderer; + public SkinnedMeshRenderer skinRenderer; + public MeshFilter meshFilter; + public Mesh originalMesh; + + // Common ------------------------------------------------------------- + public List transformList; + + public void GetUsedTransform(HashSet transformSet) + { + transformList?.ForEach(x => + { + if (x) + transformSet.Add(x); + }); + } + + public void ReplaceTransform(Dictionary replaceDict) + { + if (transformList != null) + { + for (int i = 0; i < transformList.Count; i++) + { + var t = transformList[i]; + if (t) + { + int id = t.GetInstanceID(); + if (id != 0 && replaceDict.ContainsKey(id)) + { + transformList[i] = replaceDict[id]; + } + } + } + } + } + } + + public UniqueSerializationData UniqueSerialize() + { + var sdata = new UniqueSerializationData(); + try + { + sdata.result = result; + + // Mesh + sdata.renderer = renderer; + sdata.skinRenderer = skinRenderer; + sdata.meshFilter = meshFilter; + sdata.originalMesh = originalMesh; + + // Common + sdata.transformList = new List(transformList); + } + catch (Exception exception) + { + Debug.LogException(exception); + } + + return sdata; + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupDataSerialization.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupDataSerialization.cs.meta new file mode 100644 index 0000000..da42a8c --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupDataSerialization.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15097613d7348214ca528d3986504ece +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupSerializeData.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupSerializeData.cs new file mode 100644 index 0000000..b725ea1 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupSerializeData.cs @@ -0,0 +1,356 @@ +// Magica Cloth 2. +// Copyright (c) 2025 MagicaSoft. +// https://magicasoft.jp +using System; +using System.Collections.Generic; +using Unity.Burst; +using Unity.Collections; +using Unity.Jobs; +using Unity.Mathematics; +using UnityEngine; + +namespace MagicaCloth2 +{ + [System.Serializable] + public class RenderSetupSerializeData : ITransform + { + public RenderSetupData.SetupType setupType; + + public int vertexCount; + public bool hasSkinnedMesh; + public bool hasBoneWeight; + public int skinRootBoneIndex; + public int renderTransformIndex; + public int skinBoneCount; + public int transformCount; + public int useTransformCount; + + public int[] useTransformIndexArray; + + public Transform[] transformArray; + public float3[] transformPositions; + public quaternion[] transformRotations; + public float3[] transformLocalPositions; + public quaternion[] transformLocalRotations; + public float3[] transformScales; + + public float4x4 initRenderLocalToWorld; // 初期化時の基準マトリックス(LtoW) + public float4x4 initRenderWorldtoLocal; // 初期化時の基準マトリックス(WtoL) + public quaternion initRenderRotation; // 初期化時の基準回転 + public float3 initRenderScale; // 初期化時の基準スケール + + public Mesh originalMesh; // 変更前のオリジナル共有メッシュ(SkinnedMeshRender利用時のみ) + + public bool DataValidateMeshCloth(Renderer ren) + { + if (setupType != RenderSetupData.SetupType.MeshCloth) + return false; + if (ren == null) + return false; + + if (useTransformIndexArray == null || useTransformIndexArray.Length == 0) + return false; + + if (ren is SkinnedMeshRenderer) + { + if (hasSkinnedMesh == false) + return false; + + var sren = ren as SkinnedMeshRenderer; + var smesh = sren.sharedMesh; + if (smesh == null) + return false; + + // 重いか? + //int bcnt = smesh.bindposes?.Length ?? 0; + //if (skinBoneCount != bcnt) + // return false; + } + else + { + if (hasSkinnedMesh) + return false; + + var filter = ren.GetComponent(); + if (filter == null) + return false; + + var smesh = filter.sharedMesh; + if (smesh == null) + return false; + } + + if (DataValidateTransform() == false) + return false; + + return true; + } + + public bool DataValidateBoneCloth(ClothSerializeData sdata, RenderSetupData.SetupType clothType) + { + if (setupType != clothType) + return false; + if (hasSkinnedMesh) + return false; + if (hasBoneWeight) + return false; + + if (DataValidateTransform() == false) + return false; + + // root bone + foreach (var rootBone in sdata.rootBones) + { + if (rootBone == null || Array.FindIndex(transformArray, x => x == rootBone) < 0) + return false; + } + + return true; + } + + public bool DataValidateTransform() + { + if (transformCount == 0) + return false; + if (useTransformCount == 0) + return false; + + int ucnt = useTransformCount; + + if (ucnt != (useTransformIndexArray?.Length ?? 0)) + return false; + if (ucnt != (transformArray?.Length ?? 0)) + return false; + if (Array.FindIndex(transformArray, x => x == null) >= 0) + return false; + + if (ucnt != (transformPositions?.Length ?? 0)) + return false; + if (ucnt != (transformRotations?.Length ?? 0)) + return false; + if (ucnt != (transformLocalPositions?.Length ?? 0)) + return false; + if (ucnt != (transformLocalRotations?.Length ?? 0)) + return false; + if (ucnt != (transformScales?.Length ?? 0)) + return false; + + return true; + } + + public bool Serialize(RenderSetupData sd) + { + Debug.Assert(sd != null); + Debug.Assert(sd.TransformCount > 0); + + setupType = sd.setupType; + vertexCount = sd.vertexCount; + hasSkinnedMesh = sd.hasSkinnedMesh; + hasBoneWeight = sd.hasBoneWeight; + skinRootBoneIndex = sd.skinRootBoneIndex; + renderTransformIndex = sd.renderTransformIndex; + skinBoneCount = sd.skinBoneCount; + transformCount = sd.TransformCount; + useTransformCount = 0; + originalMesh = null; + + if (sd.TransformCount > 0) + { + int tcnt = sd.TransformCount; + + using var useTransformIndexList = new NativeList(tcnt, Allocator.TempJob); + if (setupType == RenderSetupData.SetupType.MeshCloth) + { + // MeshClothではウエイトとして利用されているボーンのみパックする + if (hasBoneWeight) + { + var job = new CalcUseBoneArrayJob2() + { + boneCount = skinBoneCount, + boneWeightArray = sd.boneWeightArray, + useBoneIndexList = useTransformIndexList, + }; + job.Run(); + if (skinRootBoneIndex >= skinBoneCount) + useTransformIndexList.Add(skinRootBoneIndex); + useTransformIndexList.Add(renderTransformIndex); + } + else + { + // 通常メッシュはそのまま + for (int i = 0; i < tcnt; i++) + useTransformIndexList.Add(i); + } + + // オリジナルメッシュを記録 + if (sd.originalMesh && sd.originalMesh.name.Contains("(Clone)") == false) + { + originalMesh = sd.originalMesh; + } + } + else + { + // BoneCloth系はそのまま + for (int i = 0; i < tcnt; i++) + useTransformIndexList.Add(i); + } + + using var tempArray = useTransformIndexList.ToArray(Allocator.TempJob); + useTransformIndexArray = tempArray.ToArray(); + + int ucnt = useTransformIndexArray.Length; + + useTransformCount = ucnt; + + transformArray = new Transform[ucnt]; + transformPositions = new float3[ucnt]; + transformRotations = new quaternion[ucnt]; + transformLocalPositions = new float3[ucnt]; + transformLocalRotations = new quaternion[ucnt]; + transformScales = new float3[ucnt]; + + for (int i = 0; i < ucnt; i++) + { + int tindex = useTransformIndexArray[i]; + + transformArray[i] = sd.transformList[tindex]; + transformPositions[i] = sd.transformPositions[tindex]; + transformRotations[i] = sd.transformRotations[tindex]; + transformLocalPositions[i] = sd.transformLocalPositions[tindex]; + transformLocalRotations[i] = sd.transformLocalRotations[tindex]; + transformScales[i] = sd.transformScales[tindex]; + } + } + + initRenderLocalToWorld = sd.initRenderLocalToWorld; + initRenderWorldtoLocal = sd.initRenderWorldtoLocal; + initRenderRotation = sd.initRenderRotation; + initRenderScale = sd.initRenderScale; + + return true; + } + + [BurstCompile] + struct CalcUseBoneArrayJob2 : IJob + { + public int boneCount; + + [Unity.Collections.ReadOnly] + public NativeArray boneWeightArray; + public NativeList useBoneIndexList; + + public void Execute() + { + var useBoneArray = new NativeArray(boneCount, Allocator.Temp); + int cnt = boneWeightArray.Length; + int packCnt = 0; + for (int i = 0; i < cnt; i++) + { + var bw1 = boneWeightArray[i]; + if (bw1.weight > 0.0f) + { + byte oldFlag = useBoneArray[bw1.boneIndex]; + if (oldFlag == 0) + packCnt++; + useBoneArray[bw1.boneIndex] = 1; + } + } + + // 利用Boneのインデックスをパックする + for (int i = 0; i < boneCount; i++) + { + byte flag = useBoneArray[i]; + if (flag != 0) + { + useBoneIndexList.Add(i); + } + } + useBoneArray.Dispose(); + } + } + + public int GetLocalHash() + { + int hash = 0; + + hash += (int)setupType * 100; + hash += vertexCount; + hash += hasSkinnedMesh ? 1 : 0; + hash += hasBoneWeight ? 1 : 0; + hash += skinRootBoneIndex; + hash += renderTransformIndex; + hash += skinBoneCount; + hash += transformCount; + hash += useTransformCount; + + hash += useTransformIndexArray?.Length ?? 0; + hash += transformArray?.Length ?? 0; + hash += transformPositions?.Length ?? 0; + hash += transformRotations?.Length ?? 0; + hash += transformLocalPositions?.Length ?? 0; + hash += transformLocalRotations?.Length ?? 0; + hash += transformScales?.Length ?? 0; + + if (transformArray != null) + foreach (var t in transformArray) + hash += t != null ? (456 + t.childCount * 789) : 0; + + if (originalMesh != null) + hash += originalMesh.vertexCount; + + return hash; + } + + public int GetGlobalHash() + { + int hash = 0; + + if (transformArray != null) + { + foreach (var t in transformArray) + { + if (t) + { + hash += t.localPosition.GetHashCode(); + hash += t.localRotation.GetHashCode(); + hash += t.localScale.GetHashCode(); + } + } + } + + // レンダーワールドスケールのみ監視する + // ワールドスケールはちょっとした移動や回転などで浮動小数点誤差が出るので少数3桁まででハッシュ化する + int3 intScale = (int3)math.round(initRenderScale * 1000); + //Debug.Log($"★initScale:{intScale}"); + hash += intScale.GetHashCode(); + + return hash; + } + + public void GetUsedTransform(HashSet transformSet) + { + if (transformArray != null) + { + foreach (var t in transformArray) + { + if (t) + transformSet.Add(t); + } + } + } + + public void ReplaceTransform(Dictionary replaceDict) + { + if (transformArray == null) + return; + for (int i = 0; i < transformArray.Length; i++) + { + var t = transformArray[i]; + if (t && replaceDict.ContainsKey(t.GetInstanceID())) + { + transformArray[i] = replaceDict[t.GetInstanceID()]; + } + } + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupSerializeData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupSerializeData.cs.meta new file mode 100644 index 0000000..41865c9 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupSerializeData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 98f83594b09a8c5469b78d1d22047ecd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerNormal.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerNormal.cs new file mode 100644 index 0000000..ed19e8f --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerNormal.cs @@ -0,0 +1,1769 @@ +// Magica Cloth 2. +// Copyright (c) 2025 MagicaSoft. +// https://magicasoft.jp +using Unity.Burst; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Jobs; +using Unity.Mathematics; + +namespace MagicaCloth2 +{ + /// + /// Normal + /// セルフコリジョンなし、かつプロキシメッシュの頂点数が一定値未満のジョブ + /// 1つの巨大なジョブ内ですべてを完結させる + /// + public partial class SimulationManager + { + [BurstCompile] + unsafe struct SimulationNormalJob : IJobParallelFor + { + [Unity.Collections.ReadOnly] + public NativeList batchNormalTeamList; + public float4 simulationPower; + public float simulationDeltaTime; + public int mappingCount; + + // team + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray teamDataArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray centerDataArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray teamWindArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // wind + public int windZoneCount; + [Unity.Collections.ReadOnly] + public NativeArray windDataArray; + + // transform + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray transformPositionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray transformRotationArray; + [Unity.Collections.ReadOnly] + public NativeArray transformScaleArray; + [Unity.Collections.ReadOnly] + public NativeArray transformLocalToWorldMatrixArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray transformLocalPositionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray transformLocalRotationArray; + [Unity.Collections.ReadOnly] + public NativeArray transformLocalScaleArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + [Unity.Collections.ReadOnly] + public NativeArray localPositions; + [Unity.Collections.ReadOnly] + public NativeArray localNormals; + [Unity.Collections.ReadOnly] + public NativeArray localTangents; + [Unity.Collections.ReadOnly] + public NativeArray boneWeights; + [Unity.Collections.ReadOnly] + public NativeArray skinBoneTransformIndices; + [Unity.Collections.ReadOnly] + public NativeArray skinBoneBindPoses; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray positions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexBindPoseRotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexDepths; + [Unity.Collections.ReadOnly] + public NativeArray vertexRootIndices; + [Unity.Collections.ReadOnly] + public NativeArray vertexParentIndices; + [Unity.Collections.ReadOnly] + public NativeArray baseLineStartDataIndices; + [Unity.Collections.ReadOnly] + public NativeArray baseLineDataCounts; + [Unity.Collections.ReadOnly] + public NativeArray baseLineData; + [Unity.Collections.ReadOnly] + public NativeArray vertexLocalPositions; + [Unity.Collections.ReadOnly] + public NativeArray vertexLocalRotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexChildIndexArray; + [Unity.Collections.ReadOnly] + public NativeArray vertexChildDataArray; + [Unity.Collections.ReadOnly] + public NativeArray baseLineFlags; + [Unity.Collections.ReadOnly] + public NativeArray triangles; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray triangleNormals; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray triangleTangents; + [Unity.Collections.ReadOnly] + public NativeArray uvs; + [Unity.Collections.ReadOnly] + public NativeArray> vertexToTriangles; + [Unity.Collections.ReadOnly] + public NativeArray normalAdjustmentRotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexToTransformRotations; + [Unity.Collections.ReadOnly] + public NativeArray edges; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldRotArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray basePosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray baseRotArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldPositionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldRotationArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray dispPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray realVelocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray frictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray staticFrictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray collisionNormalArray; + + // collider + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderFlagArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderCenterArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderSizeArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderFramePositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderFrameRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderFrameScales; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldFramePositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldFrameRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderNowPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderNowRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderWorkDataArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderMainColliderIndices; + + // inertia + [Unity.Collections.ReadOnly] + public NativeArray fixedArray; + + // distance + [Unity.Collections.ReadOnly] + public NativeArray distanceIndexArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDataArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDistanceArray; + + // triangleBending + [Unity.Collections.ReadOnly] + public NativeArray bendingTrianglePairArray; + [Unity.Collections.ReadOnly] + public NativeArray bendingRestAngleOrVolumeArray; + [Unity.Collections.ReadOnly] + public NativeArray bendingSignOrVolumeArray; + + // buffer + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray stepBasicPositionBuffer; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray stepBasicRotationBuffer; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferB; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempCountBuffer; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempFloatBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempRotationBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempRotationBufferB; + + // バッチチームのローカルインデックスごと + public void Execute(int localIndex) + { + //Debug.Log(localIndex); + // チームID + int teamId = batchNormalTeamList[localIndex]; + + // !通常タイプではセルフコリジョンが無いため、相互参照を考えずに該当チームを処理すれば良い + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafePtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafePtr(); + TeamWindData* windPt = (TeamWindData*)teamWindArray.GetUnsafePtr(); + + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + ref var wdata = ref *(windPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // ■プロキシメッシュをスキニングし基本姿勢を求める + VirtualMeshManager.SimulationPreProxyMeshUpdate( + new DataChunk(0, tdata.proxyCommonChunk.dataLength), + // team + teamId, + ref tdata, + // vmesh + attributes, + localPositions, + localNormals, + localTangents, + boneWeights, + skinBoneTransformIndices, + skinBoneBindPoses, + ref positions, + ref rotations, + // transform + transformLocalToWorldMatrixArray + ); + + // チームのセンター姿勢の決定とテレポート判定および慣性用の移動量計算 + TeamManager.SimulationCalcCenterAndInertiaAndWind( + simulationDeltaTime, + // team + teamId, + ref tdata, + ref cdata, + ref wdata, + ref param, + // vmesh + positions, + rotations, + vertexBindPoseRotations, + // inertia + fixedArray, + // transform + transformPositionArray, + transformRotationArray, + transformScaleArray, + // wind + windZoneCount, + windDataArray + ); + + // パーティクルの全体慣性およびリセットの適用 + SimulationPreTeamUpdate( + new DataChunk(0, tdata.particleChunk.dataLength), + // team + ref tdata, + param, + cdata, + // vmesh + positions, + rotations, + vertexDepths, + // particle + ref nextPosArray, + ref oldPosArray, + ref oldRotArray, + ref basePosArray, + ref baseRotArray, + ref oldPositionArray, + ref oldRotationArray, + ref velocityPosArray, + ref dispPosArray, + ref velocityArray, + ref realVelocityArray, + ref frictionArray, + ref staticFrictionArray, + ref collisionNormalArray + ); + + // ■コライダーのローカル姿勢を求める、および全体慣性とリセットの適用 + if (tdata.colliderCount > 0) + { + ColliderManager.SimulationPreUpdate( + new DataChunk(0, tdata.colliderChunk.dataLength), + // team + ref tdata, + ref cdata, + // collider + ref colliderFlagArray, + ref colliderCenterArray, + ref colliderFramePositions, + ref colliderFrameRotations, + ref colliderFrameScales, + ref colliderOldFramePositions, + ref colliderOldFrameRotations, + ref colliderNowPositions, + ref colliderNowRotations, + ref colliderOldPositions, + ref colliderOldRotations, + ref colliderMainColliderIndices, + // transform + ref transformPositionArray, + ref transformRotationArray, + ref transformScaleArray, + ref transformLocalPositionArray, + ref transformLocalRotationArray, + ref transformLocalScaleArray + ); + } + + // ステップ実行 + for (int updateIndex = 0; updateIndex < tdata.updateCount; updateIndex++) + { + // ステップごとのチーム更新 + TeamManager.SimulationStepTeamUpdate( + updateIndex, + simulationDeltaTime, + // team + teamId, + ref tdata, + ref param, + ref cdata, + ref wdata + ); + + // コライダーの更新 + if (tdata.colliderCount > 0) + { + ColliderManager.SimulationStartStep( + // team + ref tdata, + ref cdata, + // collider + ref colliderFlagArray, + ref colliderSizeArray, + ref colliderFramePositions, + ref colliderFrameRotations, + ref colliderFrameScales, + ref colliderOldFramePositions, + ref colliderOldFrameRotations, + ref colliderNowPositions, + ref colliderNowRotations, + ref colliderOldPositions, + ref colliderOldRotations, + ref colliderWorkDataArray + ); + } + + // 速度更新、外力の影響、慣性シフト + SimulationStepUpdateParticles( + new DataChunk(0, tdata.particleChunk.dataLength), + simulationPower, + simulationDeltaTime, + // team + teamId, + ref tdata, + ref cdata, + ref param, + ref wdata, + // wind + ref windDataArray, + // vmesh + ref attributes, + ref depthArray, + ref positions, + ref rotations, + ref vertexRootIndices, + // particle + ref nextPosArray, + ref oldPosArray, + ref basePosArray, + ref baseRotArray, + ref oldPositionArray, + ref oldRotationArray, + ref velocityPosArray, + ref velocityArray, + ref frictionArray, + // buffer + ref stepBasicPositionBuffer, + ref stepBasicRotationBuffer + ); + + // 制約解決のためのステップごとの基準姿勢を計算 + // ベースラインごと + // アニメーションポーズ使用の有無 + // 初期姿勢の計算が不要なら抜ける + SimulationStepUpdateBaseLinePose( + new DataChunk(0, tdata.baseLineChunk.dataLength), + // team + ref tdata, + // vmesh + ref attributes, + ref vertexParentIndices, + ref baseLineStartDataIndices, + ref baseLineDataCounts, + ref baseLineData, + ref vertexLocalPositions, + ref vertexLocalRotations, + // particle + ref basePosArray, + ref baseRotArray, + // buffer + ref stepBasicPositionBuffer, + ref stepBasicRotationBuffer + ); + + // 制約の解決 ================================================================ + TetherConstraint.SolverConstraint( + new DataChunk(0, tdata.particleChunk.dataLength), + // team + ref tdata, + ref param, + ref cdata, + // vmesh + ref attributes, + ref depthArray, + ref vertexRootIndices, + // particle + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + // buffer + ref stepBasicPositionBuffer + ); + + DistanceConstraint.SolverConstraint( + new DataChunk(0, tdata.particleChunk.dataLength), + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref basePosArray, + ref velocityPosArray, + ref frictionArray, + // constraint + ref distanceIndexArray, + ref distanceDataArray, + ref distanceDistanceArray + ); + + AngleConstraint.SolverConstraint( + new DataChunk(0, tdata.baseLineChunk.dataLength), + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + ref vertexParentIndices, + ref baseLineStartDataIndices, + ref baseLineDataCounts, + ref baseLineData, + // particle + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + // buffer + ref stepBasicPositionBuffer, + ref stepBasicRotationBuffer, + // buffer2 + ref tempFloatBufferA, + ref tempVectorBufferA, + ref tempRotationBufferA, + ref tempRotationBufferB, + ref tempVectorBufferB + ); + + // バッファクリア + SimulationClearTempBuffer( + new DataChunk(0, tdata.particleChunk.dataLength), + // team + ref tdata, + // buffer2 + ref tempVectorBufferA, + ref tempVectorBufferB, + ref tempCountBuffer, + ref tempFloatBufferA + ); + + TriangleBendingConstraint.SolverConstraint( + new DataChunk(0, tdata.bendingPairChunk.dataLength), + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref frictionArray, + // constraints + ref bendingTrianglePairArray, + ref bendingRestAngleOrVolumeArray, + ref bendingSignOrVolumeArray, + // buffer2 + ref tempVectorBufferA, + ref tempCountBuffer + ); + + TriangleBendingConstraint.SumConstraint( + new DataChunk(0, tdata.particleChunk.dataLength), + // team + ref tdata, + ref param, + // vmesh + ref attributes, + // particle + ref nextPosArray, + // buffer2 + ref tempVectorBufferA, + ref tempCountBuffer + ); + + // コライダーコリジョン + if (param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Point) + { + ColliderCollisionConstraint.SolverPointConstraint( + new DataChunk(0, tdata.particleChunk.dataLength), + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref frictionArray, + ref collisionNormalArray, + ref velocityPosArray, + ref basePosArray, + // collider + ref colliderFlagArray, + ref colliderWorkDataArray + ); + } + else if (param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Edge) + { + ColliderCollisionConstraint.SolverEdgeConstraint( + new DataChunk(0, tdata.proxyEdgeChunk.dataLength), + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + ref edges, + // particle + ref nextPosArray, + // collider + ref colliderFlagArray, + ref colliderWorkDataArray, + // buffer2 + ref tempVectorBufferA, + ref tempVectorBufferB, + ref tempCountBuffer, + ref tempFloatBufferA + ); + ColliderCollisionConstraint.SumEdgeConstraint( + new DataChunk(0, tdata.particleChunk.dataLength), + // team + ref tdata, + ref param, + // particle + ref nextPosArray, + ref frictionArray, + ref collisionNormalArray, + // buffer2 + ref tempVectorBufferA, + ref tempVectorBufferB, + ref tempCountBuffer, + ref tempFloatBufferA + ); + } + + // コライダー衝突後はパーティクルが乱れる可能性があるためもう一度距離制約で整える。 + // これは裏返り防止などに効果大。 + DistanceConstraint.SolverConstraint( + new DataChunk(0, tdata.particleChunk.dataLength), + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref basePosArray, + ref velocityPosArray, + ref frictionArray, + // constraint + ref distanceIndexArray, + ref distanceDataArray, + ref distanceDistanceArray + ); + + // モーション制約はコライダーより優先 + MotionConstraint.SolverConstraint( + new DataChunk(0, tdata.particleChunk.dataLength), + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref basePosArray, + ref baseRotArray, + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + ref collisionNormalArray + ); + + // 座標確定 + SimulationStepPostTeam( + new DataChunk(0, tdata.particleChunk.dataLength), + simulationDeltaTime, + // team + teamId, + ref tdata, + ref cdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref oldPosArray, + ref velocityArray, + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + ref staticFrictionArray, + ref collisionNormalArray, + ref realVelocityArray + ); + + // コライダーの後更新 + ColliderManager.SimulationEndStep( + new DataChunk(0, tdata.colliderChunk.dataLength), + // team + ref tdata, + // collider + ref colliderNowPositions, + ref colliderNowRotations, + ref colliderOldPositions, + ref colliderOldRotations + ); + } + + // ■表示位置の決定 + SimulationCalcDisplayPosition( + new DataChunk(0, tdata.particleChunk.dataLength), + simulationDeltaTime, + // team + ref tdata, + // particle + ref oldPosArray, + ref realVelocityArray, + ref oldPositionArray, + ref oldRotationArray, + ref dispPosArray, + // vmesh + ref attributes, + ref positions, + ref rotations, + ref vertexRootIndices + + ); + + // ■クロスシミュレーション後の頂点姿勢計算 + // プロキシメッシュの頂点から法線接線を求め姿勢を確定させる + // ラインがある場合はベースラインごとに姿勢を整える + // BoneClothの場合は頂点姿勢を連動するトランスフォームデータにコピーする + VirtualMeshManager.SimulationPostProxyMeshUpdateLine( + new DataChunk(0, tdata.baseLineChunk.dataLength), + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref positions, + ref rotations, + ref vertexLocalPositions, + ref vertexLocalRotations, + ref vertexChildIndexArray, + ref vertexChildDataArray, + ref baseLineFlags, + ref baseLineStartDataIndices, + ref baseLineDataCounts, + ref baseLineData + ); + VirtualMeshManager.SimulationPostProxyMeshUpdateTriangle( + new DataChunk(0, tdata.proxyTriangleChunk.dataLength), + // team + ref tdata, + // vmesh + ref positions, + ref triangles, + ref triangleNormals, + ref triangleTangents, + ref uvs + ); + VirtualMeshManager.SimulationPostProxyMeshUpdateTriangleSum( + new DataChunk(0, tdata.proxyCommonChunk.dataLength), + // team + ref tdata, + // vmesh + ref rotations, + ref triangleNormals, + ref triangleTangents, + ref vertexToTriangles, + ref normalAdjustmentRotations + ); + VirtualMeshManager.SimulationPostProxyMeshUpdateWorldTransform( + new DataChunk(0, tdata.proxyCommonChunk.dataLength), + // team + ref tdata, + // vmesh + ref positions, + ref rotations, + ref vertexToTransformRotations, + // transform + ref transformPositionArray, + ref transformRotationArray + ); + VirtualMeshManager.SimulationPostProxyMeshUpdateLocalTransform( + // team + ref tdata, + // vmesh + ref attributes, + ref vertexParentIndices, + // transform + ref transformPositionArray, + ref transformRotationArray, + ref transformScaleArray, + ref transformLocalPositionArray, + ref transformLocalRotationArray + ); + + // ■コライダー更新後処理 + ColliderManager.SimulationPostUpdate( + // team + ref tdata, + // collider + ref colliderFramePositions, + ref colliderFrameRotations, + ref colliderOldFramePositions, + ref colliderOldFrameRotations + ); + + // ■チーム更新後処理 + TeamManager.SimulationPostTeamUpdate( + // team + ref tdata, + ref cdata + ); + } + } + + //========================================================================================= + /// + /// シミュレーション実行前処理 + /// -リセット + /// -移動影響 + /// + static void SimulationPreTeamUpdate( + DataChunk chunk, + // team + ref TeamManager.TeamData tdata, + in ClothParameters param, + in InertiaConstraint.CenterData cdata, + // vmesh + in NativeArray positions, + in NativeArray rotations, + in NativeArray vertexDepths, + // particle + ref NativeArray nextPosArray, + ref NativeArray oldPosArray, + ref NativeArray oldRotArray, + ref NativeArray basePosArray, + ref NativeArray baseRotArray, + ref NativeArray oldPositionArray, + ref NativeArray oldRotationArray, + ref NativeArray velocityPosArray, + ref NativeArray dispPosArray, + ref NativeArray velocityArray, + ref NativeArray realVelocityArray, + ref NativeArray frictionArray, + ref NativeArray staticFrictionArray, + ref NativeArray collisionNormalArray + ) + { + // パーティクルごと + var pc = tdata.particleChunk; + //int pindex = pc.startIndex; + int pindex = pc.startIndex + chunk.startIndex; + //int vindex = tdata.proxyCommonChunk.startIndex; + int vindex = tdata.proxyCommonChunk.startIndex + chunk.startIndex; + if (tdata.IsReset) + { + // リセット + //for (int i = 0; i < pc.dataLength; i++, pindex++, vindex++) + for (int i = 0; i < chunk.dataLength; i++, pindex++, vindex++) + { + var pos = positions[vindex]; + var rot = rotations[vindex]; + + nextPosArray[pindex] = pos; + oldPosArray[pindex] = pos; + oldRotArray[pindex] = rot; + basePosArray[pindex] = pos; + baseRotArray[pindex] = rot; + oldPositionArray[pindex] = pos; + oldRotationArray[pindex] = rot; + velocityPosArray[pindex] = pos; + dispPosArray[pindex] = pos; + velocityArray[pindex] = 0; + realVelocityArray[pindex] = 0; + frictionArray[pindex] = 0; + staticFrictionArray[pindex] = 0; + collisionNormalArray[pindex] = 0; + } + } + else if (tdata.IsInertiaShift || tdata.IsNegativeScaleTeleport) + { + // シフト、テレポート + //for (int i = 0; i < pc.dataLength; i++, pindex++, vindex++) + for (int i = 0; i < chunk.dataLength; i++, pindex++, vindex++) + { + var oldPos = oldPosArray[pindex]; + var oldRot = oldRotArray[pindex]; + var oldPosition = oldPositionArray[pindex]; + var oldRotation = oldRotationArray[pindex]; + var dispPos = dispPosArray[pindex]; + var velocity = velocityArray[pindex]; + var realVelocity = realVelocityArray[pindex]; + + // ■マイナススケール + if (tdata.IsNegativeScaleTeleport) + { + // 本体のスケール反転に合わせてシミュレーションに影響が出ないように必要な座標系を同様に軸反転させる + // パーティクルはセンター空間で軸反転させる + // 軸反転用マトリックス + float4x4 negativeM = cdata.negativeScaleMatrix; + + oldPos = MathUtility.TransformPoint(oldPos, negativeM); + oldRot = MathUtility.TransformRotation(oldRot, negativeM, 1); + + oldPosition = MathUtility.TransformPoint(oldPosition, negativeM); + oldRotation = MathUtility.TransformRotation(oldRotation, negativeM, 1); + + dispPos = MathUtility.TransformPoint(dispPos, negativeM); + + velocity = MathUtility.TransformVector(velocity, negativeM); + realVelocity = MathUtility.TransformVector(realVelocity, negativeM); + } + + // ■慣性全体シフト + if (tdata.IsInertiaShift) + { + // cdata.frameComponentShiftVector : 全体シフトベクトル + // cdata.frameComponentShiftRotation : 全体シフト回転 + // cdata.oldComponentWorldPosition : フレーム移動前のコンポーネント中心位置 + + oldPos = MathUtility.ShiftPosition(oldPos, cdata.oldComponentWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); + oldRot = math.mul(cdata.frameComponentShiftRotation, oldRot); + + oldPosition = MathUtility.ShiftPosition(oldPosition, cdata.oldComponentWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); + oldRotation = math.mul(cdata.frameComponentShiftRotation, oldRotation); + + dispPos = MathUtility.ShiftPosition(dispPos, cdata.oldComponentWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); + + velocity = math.mul(cdata.frameComponentShiftRotation, velocity); + realVelocity = math.mul(cdata.frameComponentShiftRotation, realVelocity); + } + + oldPosArray[pindex] = oldPos; + oldRotArray[pindex] = oldRot; + oldPositionArray[pindex] = oldPosition; + oldRotationArray[pindex] = oldRotation; + dispPosArray[pindex] = dispPos; + velocityArray[pindex] = velocity; + realVelocityArray[pindex] = realVelocity; + } + } + } + + static float3 WindBatchJob( + int teamId, + in WindParams windParams, + int vindex, + int pindex, + float depth, + ref NativeArray vertexRootIndices, + ref TeamWindData teamWindData, + ref NativeArray windDataArray, + ref NativeArray frictionArray + ) + { + float3 windForce = 0; + + // 基準ルート座標 + // (1)チームごとにずらす + // (2)同期率によりルートラインごとにずらす + // (3)チームの座標やパーティクルの座標は計算に入れない + int rootIndex = vertexRootIndices[vindex]; + float3 windPos = (teamId + 1) * 4.19230645f + (rootIndex * 0.0023963f * (1.0f - windParams.synchronization) * 100); + + // ゾーンごとの風影響計算 + int cnt = teamWindData.ZoneCount; + for (int i = 0; i < cnt; i++) + { + var windInfo = teamWindData.windZoneList[i]; + var windData = windDataArray[windInfo.windId]; + windForce += WindForceBlendBatchJob(windInfo, windParams, windPos, windData.turbulence); + } + +#if true + // 移動風影響計算 + if (windParams.movingWind > 0.01f) + { + windForce += WindForceBlendBatchJob(teamWindData.movingWind, windParams, windPos, 1.0f); + } +#endif + + //Debug.Log($"windForce:{windForce}"); + + // その他影響 + // チーム風影響 + float influence = windParams.influence; // 0.0 ~ 2.0 + + // 摩擦による影響 + float friction = frictionArray[pindex]; + influence *= (1.0f - friction); + + // 深さ影響 + float depthScale = depth * depth; + influence *= math.lerp(1.0f, depthScale, windParams.depthWeight); + + // 最終影響 + windForce *= influence; + + //Debug.Log($"windForce:{windForce}"); + + return windForce; + } + + static void SimulationStepUpdateParticles( + DataChunk chunk, + float4 simulationPower, + float simulationDeltaTime, + // team + int teamId, + ref TeamManager.TeamData tdata, + ref InertiaConstraint.CenterData cdata, + ref ClothParameters param, + ref TeamWindData wdata, + // wind + ref NativeArray windDataArray, + // vmesh + ref NativeArray attributes, + ref NativeArray depthArray, + ref NativeArray positions, + ref NativeArray rotations, + ref NativeArray vertexRootIndices, + // particle + ref NativeArray nextPosArray, + ref NativeArray oldPosArray, + ref NativeArray basePosArray, + ref NativeArray baseRotArray, + ref NativeArray oldPositionArray, + ref NativeArray oldRotationArray, + ref NativeArray velocityPosArray, + ref NativeArray velocityArray, + ref NativeArray frictionArray, + // buffer + ref NativeArray stepBasicPositionBuffer, + ref NativeArray stepBasicRotationBuffer + ) + { + // 速度更新、外力の影響、慣性シフト + //int pindex = tdata.particleChunk.startIndex; + //int vindex = tdata.proxyCommonChunk.startIndex; + int pindex = tdata.particleChunk.startIndex + chunk.startIndex; + int vindex = tdata.proxyCommonChunk.startIndex + chunk.startIndex; + //for (int i = 0; i < tdata.particleChunk.dataLength; i++, pindex++, vindex++) + for (int i = 0; i < chunk.dataLength; i++, pindex++, vindex++) + { + // nextPosSwap + var attr = attributes[vindex]; + float depth = depthArray[vindex]; + var oldPos = oldPosArray[pindex]; + + var nextPos = oldPos; + var velocityPos = oldPos; + + // 基準姿勢のステップ補間 + var oldPosition = oldPositionArray[pindex]; + var oldRotation = oldRotationArray[pindex]; + var position = positions[vindex]; + var rotation = rotations[vindex]; + + // ベース位置補間 + float3 basePos = math.lerp(oldPosition, position, tdata.frameInterpolation); + quaternion baseRot = math.slerp(oldRotation, rotation, tdata.frameInterpolation); + baseRot = math.normalize(baseRot); // 必要 + basePosArray[pindex] = basePos; + baseRotArray[pindex] = baseRot; + + // ステップ基本位置 + stepBasicPositionBuffer[pindex] = basePos; + stepBasicRotationBuffer[pindex] = baseRot; + + // 移動パーティクル + if (attr.IsMove() || tdata.IsSpring) + { + // 重量 + //float mass = MathUtility.CalcMass(depth); + + // 速度 + var velocity = velocityArray[pindex]; + +#if true + // ■ローカル慣性シフト + // シフト量 + float3 inertiaVector = cdata.inertiaVector; + quaternion inertiaRotation = cdata.inertiaRotation; + + // 慣性の深さ影響 + float inertiaDepth = param.inertiaConstraint.depthInertia * (1.0f - depth * depth); // 二次曲線 + //Debug.Log($"[{pindex}] inertiaDepth:{inertiaDepth}"); + inertiaVector = math.lerp(inertiaVector, cdata.stepVector, inertiaDepth); + inertiaRotation = math.slerp(inertiaRotation, cdata.stepRotation, inertiaDepth); + + // たぶんこっちが正しい + float3 lpos = oldPos - cdata.oldWorldPosition; + lpos = math.mul(inertiaRotation, lpos); + lpos += inertiaVector; + float3 wpos = cdata.oldWorldPosition + lpos; + var inertiaOffset = wpos - nextPos; + + // nextPos + nextPos = wpos; + + // 速度位置も調整 + velocityPos += inertiaOffset; + + // 速度に慣性回転を加える + velocity = math.mul(inertiaRotation, velocity); +#endif + + // 安定化用の速度割合 + velocity *= tdata.velocityWeight; + + // 抵抗 + // 重力に影響させたくないので先に計算する(※通常はforce適用後に行うのが一般的) + float damping = param.dampingCurveData.MC2EvaluateCurveClamp01(depth); + velocity *= math.saturate(1.0f - damping * simulationPower.z); + + // 外力 + float3 force = 0; + + // 重力 + float3 gforce = param.worldGravityDirection * (param.gravity * tdata.gravityRatio); + force += gforce; + + // 外力 + float3 exForce = 0; + float mass = MathUtility.CalcMass(depth); + switch (tdata.forceMode) + { + case ClothForceMode.VelocityAdd: + exForce = tdata.impactForce / mass; + break; + case ClothForceMode.VelocityAddWithoutDepth: + exForce = tdata.impactForce; + break; + case ClothForceMode.VelocityChange: + exForce = tdata.impactForce / mass; + velocity = 0; + break; + case ClothForceMode.VelocityChangeWithoutDepth: + exForce = tdata.impactForce; + velocity = 0; + break; + } + force += exForce; + + // 風力 + force += WindBatchJob( + teamId, + //tdata, + param.wind, + //cdata, + vindex, + pindex, + depth, + ref vertexRootIndices, + ref wdata, + ref windDataArray, + ref frictionArray + ); + + // 外力チームスケール倍率 + force *= tdata.scaleRatio; + + // 速度更新 + velocity += force * simulationDeltaTime; + + // 予測位置更新 + nextPos += velocity * simulationDeltaTime; + } + else + { + // 固定パーティクル + nextPos = basePos; + velocityPos = basePos; + } + + // スプリング(固定パーティクルのみ) + if (tdata.IsSpring && attr.IsFixed()) + { + // ノイズ用に時間を不規則にずらす + //Spring(param.springConstraint, param.normalAxis, ref nextPos, basePos, baseRot, (tdata.time + index * 49.6198f) * 2.4512f + math.csum(nextPos), tdata.scaleRatio); + SpringBatchJob(param.springConstraint, param.normalAxis, ref nextPos, basePos, baseRot, (tdata.time + pindex * 49.6198f) * 2.4512f + math.csum(nextPos), tdata.scaleRatio); + } + + // 速度計算用の移動前の位置 + velocityPosArray[pindex] = velocityPos; + + // 予測位置格納 + nextPosArray[pindex] = nextPos; + } + } + + static void SpringBatchJob( + in SpringConstraint.SpringConstraintParams springParams, + ClothNormalAxis normalAxis, + ref float3 nextPos, + in float3 basePos, + in quaternion baseRot, + float noiseTime, + float scaleRatio + ) + { + // clamp distance + var v = nextPos - basePos; + float3 dir = math.up(); + switch (normalAxis) + { + case ClothNormalAxis.Right: + dir = math.right(); + break; + case ClothNormalAxis.Up: + dir = math.up(); + break; + case ClothNormalAxis.Forward: + dir = math.forward(); + break; + case ClothNormalAxis.InverseRight: + dir = -math.right(); + break; + case ClothNormalAxis.InverseUp: + dir = -math.up(); + break; + case ClothNormalAxis.InverseForward: + dir = -math.forward(); + break; + } + dir = math.mul(baseRot, dir); + float limitDistance = springParams.limitDistance * scaleRatio; // スケール倍率 + + if (limitDistance > 1e-08f) + { + // 球クランプ + var len = math.length(v); + if (len > limitDistance) + { + v *= (limitDistance / len); + } + + // 楕円クランプ + if (springParams.normalLimitRatio < 1.0f) + { + // もっとスマートにならないか.. + float ylen = math.dot(dir, v); + float3 vx = v - dir * ylen; + float xlen = math.length(vx); + float t = xlen / limitDistance; + float y = math.cos(math.asin(t)); + y *= limitDistance * springParams.normalLimitRatio; + + if (math.abs(ylen) > y) + { + v -= dir * (math.abs(ylen) - y) * math.sign(ylen); + } + } + } + else + { + v = float3.zero; + } + + // スプリング力 + float power = springParams.springPower; + + // ノイズ + if (springParams.springNoise > 0.0f) + { + float noise = math.sin(noiseTime); // -1.0~+1.0 + //Debug.Log(noise); + noise *= springParams.springNoise * 0.6f; // スケーリング + power = math.max(power + power * noise, 0.0f); + } + + // スプリング適用 + v -= v * power; + nextPos = basePos + v; + } + + static void SimulationStepUpdateBaseLinePose( + DataChunk chunk, + // team + ref TeamManager.TeamData tdata, + // vmesh + ref NativeArray attributes, + ref NativeArray vertexParentIndices, + ref NativeArray baseLineStartDataIndices, + ref NativeArray baseLineDataCounts, + ref NativeArray baseLineData, + ref NativeArray vertexLocalPositions, + ref NativeArray vertexLocalRotations, + // particle + ref NativeArray basePosArray, + ref NativeArray baseRotArray, + // buffer + ref NativeArray stepBasicPositionBuffer, + ref NativeArray stepBasicRotationBuffer + ) + { + // 制約解決のためのステップごとの基準姿勢を計算 + // ベースラインごと + // アニメーションポーズ使用の有無 + // 初期姿勢の計算が不要なら抜ける + float blendRatio = tdata.animationPoseRatio; + if (blendRatio <= 0.99f) + { + int b_datastart = tdata.baseLineDataChunk.startIndex; + int p_start = tdata.particleChunk.startIndex; + int v_start = tdata.proxyCommonChunk.startIndex; + + // チームスケール + float3 scl = tdata.initScale * tdata.scaleRatio; + + //int bindex = tdata.baseLineChunk.startIndex; + int bindex = tdata.baseLineChunk.startIndex + chunk.startIndex; + //for (int k = 0; k < tdata.baseLineChunk.dataLength; k++, bindex++) + for (int k = 0; k < chunk.dataLength; k++, bindex++) + { + int b_start = baseLineStartDataIndices[bindex]; + int b_cnt = baseLineDataCounts[bindex]; + int b_dataindex = b_start + b_datastart; + { + for (int i = 0; i < b_cnt; i++, b_dataindex++) + { + int l_index = baseLineData[b_dataindex]; + int pindex = p_start + l_index; + int vindex = v_start + l_index; + + // 親 + int p_index = vertexParentIndices[vindex]; + int p_pindex = p_index + p_start; + + var attr = attributes[vindex]; + if (attr.IsMove() && p_index >= 0) + { + // 移動 + // 親から姿勢を算出する + var lpos = vertexLocalPositions[vindex]; + var lrot = vertexLocalRotations[vindex]; + var ppos = stepBasicPositionBuffer[p_pindex]; + var prot = stepBasicRotationBuffer[p_pindex]; + + // マイナススケール + lpos *= tdata.negativeScaleDirection; + lrot = lrot.value * tdata.negativeScaleQuaternionValue; + + stepBasicPositionBuffer[pindex] = math.mul(prot, lpos * scl) + ppos; + stepBasicRotationBuffer[pindex] = math.mul(prot, lrot); + } + else + { + // マイナススケール + var prot = stepBasicRotationBuffer[pindex]; + var lw = float4x4.TRS(0, prot, tdata.negativeScaleDirection); + quaternion rot = MathUtility.ToRotation(lw.c1.xyz, lw.c2.xyz); + stepBasicRotationBuffer[pindex] = rot; + } + } + } + + // アニメーション姿勢とブレンド + if (blendRatio > Define.System.Epsilon) + { + b_dataindex = b_start + b_datastart; + for (int i = 0; i < b_cnt; i++, b_dataindex++) + { + int l_index = baseLineData[b_dataindex]; + int pindex = p_start + l_index; + + var bpos = basePosArray[pindex]; + var brot = baseRotArray[pindex]; + + stepBasicPositionBuffer[pindex] = math.lerp(stepBasicPositionBuffer[pindex], bpos, blendRatio); + stepBasicRotationBuffer[pindex] = math.slerp(stepBasicRotationBuffer[pindex], brot, blendRatio); + } + } + } + } + } + + static float3 WindForceBlendBatchJob( + in TeamWindInfo windInfo, + in WindParams windParams, + in float3 windPos, + float windTurbulence + ) + { + float windMain = windInfo.main; + if (windMain < 0.01f) + return 0; + + //Debug.Log($"windMain:{windMain}"); + + // 風速係数 + float mainRatio = windMain / Define.System.WindBaseSpeed; // 0.0 ~ + + // Sin波形 + var sinPos = windPos + windInfo.time * 10.0f; + float2 sinXY = math.sin(sinPos.xy); + + // Noise波形 + var noisePos = windPos + windInfo.time * 2.3132f; // Sin波形との調整用 + float2 noiseXY = new float2(noise.cnoise(noisePos.xy), noise.cnoise(noisePos.yx)); + noiseXY *= 2.3f; // cnoiseは弱いので補強 2.0? + + // 波形ブレンド + float2 waveXY = math.lerp(sinXY, noiseXY, windParams.blend); + + // 基本乱流率 + windTurbulence *= windParams.turbulence; // 0.0 ~ 2.0 + + // 風向き + const float rangAng = 45.0f; // 乱流角度 + var ang = math.radians(waveXY * rangAng); + ang.y *= math.lerp(0.1f, 0.5f, windParams.blend); // 横方向は抑える。そうしないと円運動になってしまうため。0.3 - 0.5? + ang *= windTurbulence; // 乱流率 + var rq = quaternion.Euler(ang.x, ang.y, 0.0f); // XY + var dirq = MathUtility.AxisQuaternion(windInfo.direction); + float3 wdir = math.forward(math.mul(dirq, rq)); + + // 風速 + // 風速が低いと大きくなり、風速が高いと0.0になる + float mainScale = math.saturate(1.0f - mainRatio * 1.0f); + float mainWave = math.unlerp(-1.0f, 1.0f, waveXY.x); // 0.0 ~ 1.0 + mainWave *= mainScale * windTurbulence; + windMain -= windMain * mainWave; + + // 合成 + float3 windForce = wdir * windMain; + + return windForce; + } + + /// + /// 座標確定 + /// + static void SimulationStepPostTeam( + DataChunk chunk, + float simulationDeltaTime, + // team + int teamId, + ref TeamManager.TeamData tdata, + ref InertiaConstraint.CenterData cdata, + ref ClothParameters param, + // vmesh + ref NativeArray attributes, + ref NativeArray depthArray, + // particle + ref NativeArray oldPosArray, + ref NativeArray velocityArray, + ref NativeArray nextPosArray, + ref NativeArray velocityPosArray, + ref NativeArray frictionArray, + ref NativeArray staticFrictionArray, + ref NativeArray collisionNormalArray, + ref NativeArray realVelocityArray + ) + { + // 座標確定 + //int pindex = tdata.particleChunk.startIndex; + //int vindex = tdata.proxyCommonChunk.startIndex; + int pindex = tdata.particleChunk.startIndex + chunk.startIndex; + int vindex = tdata.proxyCommonChunk.startIndex + chunk.startIndex; + //for (int k = 0; k < tdata.particleChunk.dataLength; k++, pindex++, vindex++) + for (int k = 0; k < chunk.dataLength; k++, pindex++, vindex++) + { + var attr = attributes[vindex]; + var depth = depthArray[vindex]; + var nextPos = nextPosArray[pindex]; + var oldPos = oldPosArray[pindex]; + + if (attr.IsMove() || tdata.IsSpring) + { + // 移動パーティクル + var velocityOldPos = velocityPosArray[pindex]; + +#if true + // ■摩擦 + float friction = frictionArray[pindex]; + float3 cn = collisionNormalArray[pindex]; + bool isCollision = math.lengthsq(cn) > Define.System.Epsilon; // 接触の有無 + float staticFrictionParam = param.colliderCollisionConstraint.staticFriction * tdata.scaleRatio; + float dynamicFrictionParam = param.colliderCollisionConstraint.dynamicFriction; +#endif + +#if true + // ■静止摩擦 + float staticFriction = staticFrictionArray[pindex]; + if (isCollision && friction > 0.0f && staticFrictionParam > 0.0f) + { + // 接線方向の移動速度から計算する + var v = nextPos - oldPos; + var tanv = v - MathUtility.Project(v, cn); // 接線方向の移動ベクトル + float tangentVelocity = math.length(tanv) / simulationDeltaTime; // 接線方向の移動速度 + + // 静止速度以下ならば係数を上げる + if (tangentVelocity < staticFrictionParam) + { + staticFriction = math.saturate(staticFriction + 0.04f); // 係数増加(0.02?) + } + else + { + // 接線速度に応じて係数を減少 + var vel = tangentVelocity - staticFrictionParam; + var value = math.max(vel / 0.2f, 0.05f); + staticFriction = math.saturate(staticFriction - value); + } + + // 接線方向に位置を巻き戻す + tanv *= staticFriction; + nextPos -= tanv; + velocityOldPos -= tanv; + } + else + { + // 減衰 + staticFriction = math.saturate(staticFriction - 0.05f); + } + staticFrictionArray[pindex] = staticFriction; +#endif + + // ■速度更新(m/s) ------------------------------------------ + // 速度計算用の位置から割り出す(制約ごとの速度調整用) + float3 velocity = (nextPos - velocityOldPos) / simulationDeltaTime; + float sqVel = math.lengthsq(velocity); + float3 normalVelocity = sqVel > Define.System.Epsilon ? math.normalize(velocity) : 0; + +#if true + // ■動摩擦 + // 衝突面との角度が大きいほど減衰が強くなる(MC1) + if (friction > Define.System.Epsilon && isCollision && dynamicFrictionParam > 0.0f && sqVel >= Define.System.Epsilon) + { + //float dot = math.dot(cn, math.normalize(velocity)); + float dot = math.dot(cn, normalVelocity); + dot = 0.5f + 0.5f * dot; // 1.0(front) - 0.5(side) - 0.0(back) + dot *= dot; // サイドを強めに + dot = 1.0f - dot; // 0.0(front) - 0.75(side) - 1.0(back) + velocity -= velocity * (dot * math.saturate(friction * dynamicFrictionParam)); + } + + // 摩擦減衰 + friction *= Define.System.FrictionDampingRate; + frictionArray[pindex] = friction; +#endif + +#if true + // 最大速度 + // 最大速度はある程度制限したほうが動きが良くなるので入れるべき。 + // 特に回転時の髪などの動きが柔らかくなる。 + // しかし制限しすぎるとコライダーの押し出し制度がさがるので注意。 + if (param.inertiaConstraint.particleSpeedLimit >= 0.0f) + { + velocity = MathUtility.ClampVector(velocity, param.inertiaConstraint.particleSpeedLimit * tdata.scaleRatio); + } +#endif +#if true + // ■遠心力加速 --------------------------------------------- + if (cdata.angularVelocity > Define.System.Epsilon && param.inertiaConstraint.centrifualAcceleration > Define.System.Epsilon && sqVel >= Define.System.Epsilon) + { + // 回転中心のローカル座標 + var lpos = nextPos - cdata.nowWorldPosition; + + // 回転軸平面に投影 + var v = MathUtility.ProjectOnPlane(lpos, cdata.rotationAxis); + var r = math.length(v); + if (r > Define.System.Epsilon) + { + float3 n = v / r; + + // 角速度(rad/s) + float w = cdata.angularVelocity; + + // 重量(重いほど遠心力は強くなる) + // ここでは末端に行くほど軽くする + //float m = (1.0f - depth) * 3.0f; + //float m = 1.0f + (1.0f - depth) * 2.0f; + float m = 1.0f + (1.0f - depth); // fix + //float m = 1.0f + depth * 3.0f; + //const float m = 1; + + // 遠心力 + var f = m * w * w * r; + + // 回転方向uと速度方向が同じ場合のみ力を加える(内積による乗算) + // 実際の物理では遠心力は紐が張った状態でなければ発生しないがこの状態を判別する方法は簡単ではない + // そのためこのような近似で代用する + // 回転と速度が逆方向の場合は紐が緩んでいると判断し遠心力の増強を適用しない + float3 u = math.normalize(math.cross(cdata.rotationAxis, n)); + f *= math.saturate(math.dot(normalVelocity, u)); + + // 遠心力を速度に加算する + velocity += n * (f * param.inertiaConstraint.centrifualAcceleration * 0.02f); + } + } +#endif + // 安定化用の速度割合 + velocity *= tdata.velocityWeight; + + // 書き戻し + velocityArray[pindex] = velocity; + } + + // 実速度 + float3 realVelocity = (nextPos - oldPos) / simulationDeltaTime; + realVelocityArray[pindex] = realVelocity; + + // 今回の予測位置を記録 + oldPosArray[pindex] = nextPos; + } + } + + /// + /// シミュレーション完了後の表示位置の計算 + /// - 未来予測 + /// + static void SimulationCalcDisplayPosition( + DataChunk chunk, + float simulationDeltaTime, + // team + ref TeamManager.TeamData tdata, + // particle + ref NativeArray oldPosArray, + ref NativeArray realVelocityArray, + ref NativeArray oldPositionArray, + ref NativeArray oldRotationArray, + ref NativeArray dispPosArray, + // vmesh + ref NativeArray attributes, + ref NativeArray positions, + ref NativeArray rotations, + ref NativeArray vertexRootIndices + ) + { + //int pindex = tdata.particleChunk.startIndex; + int pindex = tdata.particleChunk.startIndex + chunk.startIndex; + int v_start = tdata.proxyCommonChunk.startIndex; + //int vindex = v_start; + int vindex = v_start + chunk.startIndex; + //for (int k = 0; k < tdata.particleChunk.dataLength; k++, pindex++, vindex++) + for (int k = 0; k < chunk.dataLength; k++, pindex++, vindex++) + { + var attr = attributes[vindex]; + + var pos = positions[vindex]; + var rot = rotations[vindex]; + //Debug.Log($"DispRot [{vindex}] nor:{MathUtility.ToNormal(rot)}, tan:{MathUtility.ToTangent(rot)}"); + + if (attr.IsMove() || tdata.IsSpring) + { + // 移動パーティクル + var dpos = oldPosArray[pindex]; + +#if !MC2_DISABLE_FUTURE + // 未来予測 + // 最終計算位置と実速度から次のステップ位置を予測し、その間のフレーム時間位置を表示位置とする + float3 velocity = realVelocityArray[pindex] * simulationDeltaTime; + float3 fpos = dpos + velocity; + float interval = (tdata.nowUpdateTime + simulationDeltaTime) - tdata.oldTime; + float t = interval > 0.0f ? (tdata.time - tdata.oldTime) / interval : 0.0f; + fpos = math.lerp(dispPosArray[pindex], fpos, t); + // ルートからの距離クランプ(安全対策) + int rootIndex = vertexRootIndices[vindex]; + if (rootIndex >= 0) + { + var rootPos = positions[v_start + rootIndex]; + float originalDist = math.distance(rootPos, pos); + float clampDist = originalDist * Define.System.MaxDistanceRatioFutuerPrediction; // 許容限界距離 + var v = fpos - rootPos; + v = MathUtility.ClampVector(v, clampDist); + fpos = rootPos + v; + } + + dpos = fpos; +#endif + + // 表示位置 + var dispPos = dpos; + + // 表示位置を記録 + dispPosArray[pindex] = dispPos; + + // ブレンドウエイト + var vpos = math.lerp(positions[vindex], dispPos, tdata.blendWeight); + + // vmeshに反映 + positions[vindex] = vpos; + } + else + { + // 固定パーティクル + // 表示位置は常にオリジナル位置 + var dispPos = positions[vindex]; + dispPosArray[pindex] = dispPos; + } + + // 1つ前の原点位置を記録 + if (tdata.IsRunning) + { + oldPositionArray[pindex] = pos; + oldRotationArray[pindex] = rot; + } + + // マイナススケール + // 回転をマイナススケールを適用した表示計算用の回転に変換する + if (tdata.IsNegativeScale) + { + var lw = float4x4.TRS(0, rot, tdata.negativeScaleDirection); + rot = MathUtility.ToRotation(lw.c1.xyz, lw.c2.xyz); + rotations[vindex] = rot; + } + } + } + + unsafe static void SimulationClearTempBuffer( + DataChunk chunk, + // team + ref TeamManager.TeamData tdata, + // buffer2 + ref NativeArray tempVectorBufferA, + ref NativeArray tempVectorBufferB, + ref NativeArray tempCountBuffer, + ref NativeArray tempFloatBufferA + //ref NativeArray tempRotationBufferA, + //ref NativeArray tempRotationBufferB, + ) + { + int pindex = tdata.particleChunk.startIndex + chunk.startIndex; + for (int i = 0; i < chunk.dataLength; i++, pindex++) + { + tempVectorBufferA[pindex] = 0; + tempVectorBufferB[pindex] = 0; + tempCountBuffer[pindex] = 0; + tempFloatBufferA[pindex] = 0; + } + } + } +} + diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerNormal.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerNormal.cs.meta new file mode 100644 index 0000000..ae680c1 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerNormal.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1678d975c7bf0f343bf9eb89afc158fe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs new file mode 100644 index 0000000..6ae4887 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs @@ -0,0 +1,2335 @@ +// Magica Cloth 2. +// Copyright (c) 2025 MagicaSoft. +// https://magicasoft.jp +using Unity.Burst; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Jobs; +using Unity.Mathematics; + +namespace MagicaCloth2 +{ + /// + /// Split + /// セルフコリジョンあり、もしくはプロキシメッシュの頂点数が一定値以上のジョブ + /// オリジナルと同様にジョブを分割し同期しながら実行する + /// ただし最適化を行いオリジナルより軽量化している + /// + public partial class SimulationManager + { + /// + /// プロキシメッシュをスキニングし基本姿勢を求める + /// + [BurstCompile] + unsafe struct SplitPre_A_Job : IJobParallelFor + { + public int workerCount; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + + // transform + [Unity.Collections.ReadOnly] + public NativeArray transformLocalToWorldMatrixArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray localPositions; + [Unity.Collections.ReadOnly] + public NativeArray localNormals; + [Unity.Collections.ReadOnly] + public NativeArray localTangents; + [Unity.Collections.ReadOnly] + public NativeArray boneWeights; + [Unity.Collections.ReadOnly] + public NativeArray skinBoneTransformIndices; + [Unity.Collections.ReadOnly] + public NativeArray skinBoneBindPoses; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray positions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray rotations; + + // バッチ内のローカルチームインデックスごと + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + //Debug.Log(localIndex); + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + + //Debug.Log($"{localIndex}, {teamId}"); + + ref var tdata = ref *(teamPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.proxyCommonChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + // ■プロキシメッシュをスキニングし基本姿勢を求める + VirtualMeshManager.SimulationPreProxyMeshUpdate( + //new DataChunk(0, tdata.proxyCommonChunk.dataLength), + chunk, + // team + teamId, + ref tdata, + // vmesh + attributes, + localPositions, + localNormals, + localTangents, + boneWeights, + skinBoneTransformIndices, + skinBoneBindPoses, + ref positions, + ref rotations, + // transform + transformLocalToWorldMatrixArray + ); + } + } + + /// + /// チームのセンター姿勢の決定と慣性用の移動量計算 + /// + [BurstCompile] + unsafe struct SplitPre_B_Job : IJobParallelFor + { + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray teamDataArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray centerDataArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray teamWindArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // wind + public int windZoneCount; + [Unity.Collections.ReadOnly] + public NativeArray windDataArray; + + // transform + [Unity.Collections.ReadOnly] + public NativeArray transformPositionArray; + [Unity.Collections.ReadOnly] + public NativeArray transformRotationArray; + [Unity.Collections.ReadOnly] + public NativeArray transformScaleArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray positions; + [Unity.Collections.ReadOnly] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexBindPoseRotations; + + + // inertia + [Unity.Collections.ReadOnly] + public NativeArray fixedArray; + + // バッチ内のローカルチームインデックスごと + public void Execute(int localIndex) + { + //Debug.Log(localIndex); + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafePtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafePtr(); + TeamWindData* windPt = (TeamWindData*)teamWindArray.GetUnsafePtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + ref var wdata = ref *(windPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // チームのセンター姿勢の決定と慣性用の移動量計算 + TeamManager.SimulationCalcCenterAndInertiaAndWind( + simulationDeltaTime, + // team + teamId, + ref tdata, + ref cdata, + ref wdata, + ref param, + // vmesh + positions, + rotations, + vertexBindPoseRotations, + // inertia + fixedArray, + // transform + transformPositionArray, + transformRotationArray, + transformScaleArray, + // wind + windZoneCount, + windDataArray + ); + } + } + + /// + /// パーティクルの全体慣性およびリセットの適用 + /// コライダーのローカル姿勢を求める、および全体慣性とリセットの適用 + /// + [BurstCompile] + unsafe struct SplitPre_C_Job : IJobParallelFor + { + public int workerCount; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray centerDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // transform + [Unity.Collections.ReadOnly] + public NativeArray transformPositionArray; + [Unity.Collections.ReadOnly] + public NativeArray transformRotationArray; + [Unity.Collections.ReadOnly] + public NativeArray transformScaleArray; + [Unity.Collections.ReadOnly] + public NativeArray transformLocalPositionArray; + [Unity.Collections.ReadOnly] + public NativeArray transformLocalRotationArray; + [Unity.Collections.ReadOnly] + public NativeArray transformLocalScaleArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray positions; + [Unity.Collections.ReadOnly] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexDepths; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldRotArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray basePosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray baseRotArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldPositionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldRotationArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray dispPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray realVelocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray frictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray staticFrictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray collisionNormalArray; + + // collider + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderFlagArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderCenterArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderFramePositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderFrameRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderFrameScales; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldFramePositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldFrameRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderNowPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderNowRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldRotations; + [Unity.Collections.ReadOnly] + public NativeArray colliderMainColliderIndices; + + // バッチ内のローカルチームインデックスごと + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + //Debug.Log(localIndex); + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // パーティクルの全体慣性およびリセットの適用 + var p_chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (p_chunk.IsValid) + { + SimulationPreTeamUpdate( + p_chunk, + // team + ref tdata, + param, + cdata, + // vmesh + positions, + rotations, + vertexDepths, + // particle + ref nextPosArray, + ref oldPosArray, + ref oldRotArray, + ref basePosArray, + ref baseRotArray, + ref oldPositionArray, + ref oldRotationArray, + ref velocityPosArray, + ref dispPosArray, + ref velocityArray, + ref realVelocityArray, + ref frictionArray, + ref staticFrictionArray, + ref collisionNormalArray + ); + } + + // ■コライダーのローカル姿勢を求める、および全体慣性とリセットの適用 + if (tdata.colliderCount > 0) + { + var c_chunk = MathUtility.GetWorkerChunk(tdata.colliderChunk.dataLength, workerCount, workerIndex); + if (c_chunk.IsValid) + { + ColliderManager.SimulationPreUpdate( + c_chunk, + // team + ref tdata, + ref cdata, + // collider + ref colliderFlagArray, + ref colliderCenterArray, + ref colliderFramePositions, + ref colliderFrameRotations, + ref colliderFrameScales, + ref colliderOldFramePositions, + ref colliderOldFrameRotations, + ref colliderNowPositions, + ref colliderNowRotations, + ref colliderOldPositions, + ref colliderOldRotations, + ref colliderMainColliderIndices, + // transform + ref transformPositionArray, + ref transformRotationArray, + ref transformScaleArray, + ref transformLocalPositionArray, + ref transformLocalRotationArray, + ref transformLocalScaleArray + ); + } + } + } + } + + /// + /// チーム更新 + /// コライダーの更新 + /// + [BurstCompile] + unsafe struct SplitStep_A_Job : IJobParallelFor + { + public int updateIndex; + public float4 simulationPower; + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray teamDataArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray centerDataArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray teamWindArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // collider + [Unity.Collections.ReadOnly] + public NativeArray colliderFlagArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderSizeArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderFramePositions; + [Unity.Collections.ReadOnly] + public NativeArray colliderFrameRotations; + [Unity.Collections.ReadOnly] + public NativeArray colliderFrameScales; + [Unity.Collections.ReadOnly] + public NativeArray colliderOldFramePositions; + [Unity.Collections.ReadOnly] + public NativeArray colliderOldFrameRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderNowPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderNowRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderWorkDataArray; + + // バッチ内のローカルチームインデックスごと + public void Execute(int localIndex) + { + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafePtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafePtr(); + TeamWindData* windPt = (TeamWindData*)teamWindArray.GetUnsafePtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + ref var wdata = ref *(windPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // ステップ実行 + // ステップごとのチーム更新 + TeamManager.SimulationStepTeamUpdate( + updateIndex, + simulationDeltaTime, + // team + teamId, + ref tdata, + ref param, + ref cdata, + ref wdata + ); + + // コライダーの更新 + if (tdata.colliderCount > 0) + { + ColliderManager.SimulationStartStep( + // team + ref tdata, + ref cdata, + // collider + ref colliderFlagArray, + ref colliderSizeArray, + ref colliderFramePositions, + ref colliderFrameRotations, + ref colliderFrameScales, + ref colliderOldFramePositions, + ref colliderOldFrameRotations, + ref colliderNowPositions, + ref colliderNowRotations, + ref colliderOldPositions, + ref colliderOldRotations, + ref colliderWorkDataArray + ); + } + } + } + + /// + /// 速度更新、外力の影響、慣性シフト + /// + [BurstCompile] + unsafe struct SplitStep_B_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray centerDataArray; + [Unity.Collections.ReadOnly] + public NativeArray teamWindArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // wind + public int windZoneCount; + [Unity.Collections.ReadOnly] + public NativeArray windDataArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + [Unity.Collections.ReadOnly] + public NativeArray positions; + [Unity.Collections.ReadOnly] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexRootIndices; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [Unity.Collections.ReadOnly] + public NativeArray oldPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray basePosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray baseRotArray; + [Unity.Collections.ReadOnly] + public NativeArray oldPositionArray; + [Unity.Collections.ReadOnly] + public NativeArray oldRotationArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [Unity.Collections.ReadOnly] + public NativeArray velocityArray; + [Unity.Collections.ReadOnly] + public NativeArray frictionArray; + + // buffer + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray stepBasicPositionBuffer; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray stepBasicRotationBuffer; + + // バッチ内のローカルチームインデックスごと + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafeReadOnlyPtr(); + TeamWindData* windPt = (TeamWindData*)teamWindArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + ref var wdata = ref *(windPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + // 速度更新、外力の影響、慣性シフト + SimulationStepUpdateParticles( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + simulationPower, + simulationDeltaTime, + // team + teamId, + ref tdata, + ref cdata, + ref param, + ref wdata, + // wind + ref windDataArray, + // vmesh + ref attributes, + ref depthArray, + ref positions, + ref rotations, + ref vertexRootIndices, + // particle + ref nextPosArray, + ref oldPosArray, + ref basePosArray, + ref baseRotArray, + ref oldPositionArray, + ref oldRotationArray, + ref velocityPosArray, + ref velocityArray, + ref frictionArray, + // buffer + ref stepBasicPositionBuffer, + ref stepBasicRotationBuffer + ); + } + } + + /// + /// ベースラインの基準姿勢を計算 + /// + [BurstCompile] + unsafe struct SplitStep_C_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray vertexRootIndices; + [Unity.Collections.ReadOnly] + public NativeArray vertexParentIndices; + [Unity.Collections.ReadOnly] + public NativeArray baseLineStartDataIndices; + [Unity.Collections.ReadOnly] + public NativeArray baseLineDataCounts; + [Unity.Collections.ReadOnly] + public NativeArray baseLineData; + [Unity.Collections.ReadOnly] + public NativeArray vertexLocalPositions; + [Unity.Collections.ReadOnly] + public NativeArray vertexLocalRotations; + + // particle + [Unity.Collections.ReadOnly] + public NativeArray basePosArray; + [Unity.Collections.ReadOnly] + public NativeArray baseRotArray; + + // buffer + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray stepBasicPositionBuffer; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray stepBasicRotationBuffer; + + // バッチ内のローカルチームインデックスごと + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.baseLineChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + // 制約解決のためのステップごとの基準姿勢を計算 + // ベースラインごと + // アニメーションポーズ使用の有無 + SimulationStepUpdateBaseLinePose( + //new DataChunk(0, tdata.baseLineChunk.dataLength), + chunk, + // team + ref tdata, + // vmesh + ref attributes, + ref vertexParentIndices, + ref baseLineStartDataIndices, + ref baseLineDataCounts, + ref baseLineData, + ref vertexLocalPositions, + ref vertexLocalRotations, + // particle + ref basePosArray, + ref baseRotArray, + // buffer + ref stepBasicPositionBuffer, + ref stepBasicRotationBuffer + ); + } + } + + /// + /// テザー + /// 距離 + /// + [BurstCompile] + unsafe struct SplitStep_D_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray centerDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + [Unity.Collections.ReadOnly] + public NativeArray vertexRootIndices; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [Unity.Collections.ReadOnly] + public NativeArray basePosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [Unity.Collections.ReadOnly] + public NativeArray frictionArray; + + // distance + [Unity.Collections.ReadOnly] + public NativeArray distanceIndexArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDataArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDistanceArray; + + // buffer + [Unity.Collections.ReadOnly] + public NativeArray stepBasicPositionBuffer; + + // バッチ内のローカルチームインデックスごと + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + TetherConstraint.SolverConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + ref cdata, + // vmesh + ref attributes, + ref depthArray, + ref vertexRootIndices, + // particle + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + // buffer + ref stepBasicPositionBuffer + ); + + DistanceConstraint.SolverConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref basePosArray, + ref velocityPosArray, + ref frictionArray, + // constraint + ref distanceIndexArray, + ref distanceDataArray, + ref distanceDistanceArray + ); + } + } + + /// + /// アングル + /// + [BurstCompile] + unsafe struct SplitStep_Angle_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + [Unity.Collections.ReadOnly] + public NativeArray vertexRootIndices; + [Unity.Collections.ReadOnly] + public NativeArray vertexParentIndices; + [Unity.Collections.ReadOnly] + public NativeArray baseLineStartDataIndices; + [Unity.Collections.ReadOnly] + public NativeArray baseLineDataCounts; + [Unity.Collections.ReadOnly] + public NativeArray baseLineData; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [Unity.Collections.ReadOnly] + public NativeArray frictionArray; + + // distance + [Unity.Collections.ReadOnly] + public NativeArray distanceIndexArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDataArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDistanceArray; + + // buffer + [Unity.Collections.ReadOnly] + public NativeArray stepBasicPositionBuffer; + [Unity.Collections.ReadOnly] + public NativeArray stepBasicRotationBuffer; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferB; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempFloatBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempRotationBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempRotationBufferB; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.baseLineChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + AngleConstraint.SolverConstraint( + chunk, + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + ref vertexParentIndices, + ref baseLineStartDataIndices, + ref baseLineDataCounts, + ref baseLineData, + // particle + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + // buffer + ref stepBasicPositionBuffer, + ref stepBasicRotationBuffer, + // buffer2 + ref tempFloatBufferA, + ref tempVectorBufferA, + ref tempRotationBufferA, + ref tempRotationBufferB, + ref tempVectorBufferB + ); + } + } + + /// + /// トライアングルベンド + /// + [BurstCompile] + unsafe struct SplitStep_Triangle_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [Unity.Collections.ReadOnly] + public NativeArray frictionArray; + + // triangle bending + [Unity.Collections.ReadOnly] + public NativeArray bendingTrianglePairArray; + [Unity.Collections.ReadOnly] + public NativeArray bendingRestAngleOrVolumeArray; + [Unity.Collections.ReadOnly] + public NativeArray bendingSignOrVolumeArray; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempCountBuffer; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.bendingPairChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + TriangleBendingConstraint.SolverConstraint( + chunk, + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref frictionArray, + // constraints + ref bendingTrianglePairArray, + ref bendingRestAngleOrVolumeArray, + ref bendingSignOrVolumeArray, + // buffer2 + ref tempVectorBufferA, + ref tempCountBuffer + ); + } + } + + /// + /// トライアングルベンド集計 + /// コライダーコリジョンPoint + /// + [BurstCompile] + unsafe struct SplitStep_E_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [Unity.Collections.ReadOnly] + public NativeArray basePosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray frictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray collisionNormalArray; + + // collider + [Unity.Collections.ReadOnly] + public NativeArray colliderFlagArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderWorkDataArray; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempCountBuffer; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + TriangleBendingConstraint.SumConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + // particle + ref nextPosArray, + // buffer2 + ref tempVectorBufferA, + ref tempCountBuffer + ); + + // コライダーコリジョン + if (tdata.UseColliderCount > 0 && param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Point) + { + // Pointコリジョン + ColliderCollisionConstraint.SolverPointConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref frictionArray, + ref collisionNormalArray, + ref velocityPosArray, + ref basePosArray, + // collider + ref colliderFlagArray, + ref colliderWorkDataArray + ); + } + } + } + + /// + /// コライダーコリジョンEdge + /// + [BurstCompile] + unsafe struct SplitStep_Edge_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + [Unity.Collections.ReadOnly] + public NativeArray edges; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + + // collider + [Unity.Collections.ReadOnly] + public NativeArray colliderFlagArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderWorkDataArray; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferB; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempCountBuffer; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempFloatBufferA; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // コライダーコリジョン + if (tdata.UseColliderCount > 0 && param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Edge) + { + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.proxyEdgeChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + // Edgeコリジョン + ColliderCollisionConstraint.SolverEdgeConstraint( + //new DataChunk(0, tdata.proxyEdgeChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + ref edges, + // particle + ref nextPosArray, + // collider + ref colliderFlagArray, + ref colliderWorkDataArray, + // buffer2 + ref tempVectorBufferA, + ref tempVectorBufferB, + ref tempCountBuffer, + ref tempFloatBufferA + ); + } + } + } + + /// + /// ■セルフコリジョンあり + /// コライダーコリジョンEdge集計 + /// 距離 + /// モーション + /// + [BurstCompile] + unsafe struct SplitStep_F_Self_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [Unity.Collections.ReadOnly] + public NativeArray basePosArray; + [Unity.Collections.ReadOnly] + public NativeArray baseRotArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray frictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray collisionNormalArray; + + // distance + [Unity.Collections.ReadOnly] + public NativeArray distanceIndexArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDataArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDistanceArray; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferB; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempCountBuffer; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempFloatBufferA; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + // コライダーコリジョン + if (tdata.UseColliderCount > 0 && param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Edge) + { + // Edgeコリジョン集計 + ColliderCollisionConstraint.SumEdgeConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // particle + ref nextPosArray, + ref frictionArray, + ref collisionNormalArray, + // buffer2 + ref tempVectorBufferA, + ref tempVectorBufferB, + ref tempCountBuffer, + ref tempFloatBufferA + ); + } + + // コライダー衝突後はパーティクルが乱れる可能性があるためもう一度距離制約で整える。 + // これは裏返り防止などに効果大。 + DistanceConstraint.SolverConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref basePosArray, + ref velocityPosArray, + ref frictionArray, + // constraint + ref distanceIndexArray, + ref distanceDataArray, + ref distanceDistanceArray + ); + + // モーション制約はコライダーより優先 + MotionConstraint.SolverConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref basePosArray, + ref baseRotArray, + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + ref collisionNormalArray + ); + } + } + + /// + /// ■セルフコリジョンあり + /// 座標確定 + /// コライダーの後更新 + /// + [BurstCompile] + unsafe struct SplitStep_G_Self_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray centerDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + + // particle + [Unity.Collections.ReadOnly] + public NativeArray nextPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldPosArray; + [Unity.Collections.ReadOnly] + public NativeArray velocityPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray realVelocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray frictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray staticFrictionArray; + [Unity.Collections.ReadOnly] + public NativeArray collisionNormalArray; + + // collider + [Unity.Collections.ReadOnly] + public NativeArray colliderNowPositions; + [Unity.Collections.ReadOnly] + public NativeArray colliderNowRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldRotations; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid) + { + // 座標確定 + SimulationStepPostTeam( + chunk, + simulationDeltaTime, + // team + teamId, + ref tdata, + ref cdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref oldPosArray, + ref velocityArray, + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + ref staticFrictionArray, + ref collisionNormalArray, + ref realVelocityArray + ); + } + + // コライダーの後更新 + var colChunk = MathUtility.GetWorkerChunk(tdata.colliderChunk.dataLength, workerCount, workerIndex); + if (colChunk.IsValid) + { + ColliderManager.SimulationEndStep( + colChunk, + // team + ref tdata, + // collider + ref colliderNowPositions, + ref colliderNowRotations, + ref colliderOldPositions, + ref colliderOldRotations + ); + } + } + } + + /// + /// ■セルフコリジョンなし + /// コライダーコリジョンEdge集計 + /// 距離 + /// モーション + /// 座標確定 + /// コライダーの後更新 + /// + [BurstCompile] + unsafe struct SplitStep_FG_NoSelf_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray centerDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldPosArray; + [Unity.Collections.ReadOnly] + public NativeArray basePosArray; + [Unity.Collections.ReadOnly] + public NativeArray baseRotArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray realVelocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray frictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray staticFrictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray collisionNormalArray; + + // collider + [Unity.Collections.ReadOnly] + public NativeArray colliderNowPositions; + [Unity.Collections.ReadOnly] + public NativeArray colliderNowRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldRotations; + + // distance + [Unity.Collections.ReadOnly] + public NativeArray distanceIndexArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDataArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDistanceArray; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferB; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempCountBuffer; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempFloatBufferA; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid) + { + // コライダーコリジョン + if (tdata.UseColliderCount > 0 && param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Edge) + { + // Edgeコリジョン集計 + ColliderCollisionConstraint.SumEdgeConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // particle + ref nextPosArray, + ref frictionArray, + ref collisionNormalArray, + // buffer2 + ref tempVectorBufferA, + ref tempVectorBufferB, + ref tempCountBuffer, + ref tempFloatBufferA + ); + } + + // コライダー衝突後はパーティクルが乱れる可能性があるためもう一度距離制約で整える。 + // これは裏返り防止などに効果大。 + DistanceConstraint.SolverConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref basePosArray, + ref velocityPosArray, + ref frictionArray, + // constraint + ref distanceIndexArray, + ref distanceDataArray, + ref distanceDistanceArray + ); + + // モーション制約はコライダーより優先 + MotionConstraint.SolverConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref basePosArray, + ref baseRotArray, + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + ref collisionNormalArray + ); + + // 座標確定 + SimulationStepPostTeam( + chunk, + simulationDeltaTime, + // team + teamId, + ref tdata, + ref cdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref oldPosArray, + ref velocityArray, + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + ref staticFrictionArray, + ref collisionNormalArray, + ref realVelocityArray + ); + } + + // コライダーの後更新 + var colChunk = MathUtility.GetWorkerChunk(tdata.colliderChunk.dataLength, workerCount, workerIndex); + if (colChunk.IsValid) + { + ColliderManager.SimulationEndStep( + colChunk, + // team + ref tdata, + // collider + ref colliderNowPositions, + ref colliderNowRotations, + ref colliderOldPositions, + ref colliderOldRotations + ); + } + } + } + + /// + /// 表示位置の計算 + /// + [BurstCompile] + unsafe struct SplitPost_DisplayPos_Job : IJobParallelFor + { + public int workerCount; + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray positions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexRootIndices; + + // particle + [Unity.Collections.ReadOnly] + public NativeArray oldPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldPositionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldRotationArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray dispPosArray; + [Unity.Collections.ReadOnly] + public NativeArray realVelocityArray; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // ■表示位置の決定 + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + //Debug.Log($"localIndex:{localIndex}, workerIndex:{workerIndex}, workerCount:{workerCount}, chun.s:{chunk.startIndex}, chun.l:{chunk.dataLength}"); + if (chunk.IsValid) + { + SimulationCalcDisplayPosition( + chunk, + simulationDeltaTime, + // team + ref tdata, + // particle + ref oldPosArray, + ref realVelocityArray, + ref oldPositionArray, + ref oldRotationArray, + ref dispPosArray, + // vmesh + ref attributes, + ref positions, + ref rotations, + ref vertexRootIndices + + ); + } + } + } + + /// + /// クロスシミュレーションの結果をProxyMeshへ反映させる + /// ラインがある場合はベースラインごとに姿勢を整える + /// + [BurstCompile] + unsafe struct SplitPost_CalcProxy_Job : IJobParallelFor + { + public int workerCount; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray positions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray baseLineStartDataIndices; + [Unity.Collections.ReadOnly] + public NativeArray baseLineDataCounts; + [Unity.Collections.ReadOnly] + public NativeArray baseLineData; + [Unity.Collections.ReadOnly] + public NativeArray vertexLocalPositions; + [Unity.Collections.ReadOnly] + public NativeArray vertexLocalRotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexChildIndexArray; + [Unity.Collections.ReadOnly] + public NativeArray vertexChildDataArray; + [Unity.Collections.ReadOnly] + public NativeArray baseLineFlags; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // ■クロスシミュレーション後の頂点姿勢計算 + // ラインがある場合はベースラインごとに姿勢を整える + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.baseLineChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid) + { + VirtualMeshManager.SimulationPostProxyMeshUpdateLine( + chunk, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref positions, + ref rotations, + ref vertexLocalPositions, + ref vertexLocalRotations, + ref vertexChildIndexArray, + ref vertexChildDataArray, + ref baseLineFlags, + ref baseLineStartDataIndices, + ref baseLineDataCounts, + ref baseLineData + ); + } + } + } + + /// + /// トライアングルの法線接線を求める + /// + [BurstCompile] + unsafe struct SplitPost_CalcProxyTriangle_Job : IJobParallelFor + { + public int workerCount; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray positions; + [Unity.Collections.ReadOnly] + public NativeArray triangles; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray triangleNormals; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray triangleTangents; + [Unity.Collections.ReadOnly] + public NativeArray uvs; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // ■クロスシミュレーション後の頂点姿勢計算 + // トライアングルの法線接線を求める + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.proxyTriangleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid) + { + VirtualMeshManager.SimulationPostProxyMeshUpdateTriangle( + chunk, + // team + ref tdata, + // vmesh + ref positions, + ref triangles, + ref triangleNormals, + ref triangleTangents, + ref uvs + ); + } + } + } + + /// + /// トライアングルの法線接線から頂点の姿勢を求める + /// BoneClothの場合は頂点姿勢から連動するトランスフォームのワールド姿勢を計算する + /// + [BurstCompile] + unsafe struct SplitPost_SumProxyTriangleAndTransform_Job : IJobParallelFor + { + public int workerCount; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + + // transform + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray transformPositionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray transformRotationArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray positions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray triangleNormals; + [Unity.Collections.ReadOnly] + public NativeArray triangleTangents; + [Unity.Collections.ReadOnly] + public NativeArray> vertexToTriangles; + [Unity.Collections.ReadOnly] + public NativeArray normalAdjustmentRotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexToTransformRotations; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.proxyCommonChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid) + { + // ■クロスシミュレーション後の頂点姿勢計算 + // トライアングルの法線接線から頂点の姿勢を求める + VirtualMeshManager.SimulationPostProxyMeshUpdateTriangleSum( + chunk, + // team + ref tdata, + // vmesh + ref rotations, + ref triangleNormals, + ref triangleTangents, + ref vertexToTriangles, + ref normalAdjustmentRotations + ); + // BoneClothの場合は頂点姿勢から連動するトランスフォームのワールド姿勢を計算する + VirtualMeshManager.SimulationPostProxyMeshUpdateWorldTransform( + chunk, + // team + ref tdata, + // vmesh + ref positions, + ref rotations, + ref vertexToTransformRotations, + // transform + ref transformPositionArray, + ref transformRotationArray + ); + } + } + } + + /// + /// チーム更新後処理 + /// BoneClothの場合はTransformのローカル姿勢を計算する + /// コライダー更新後処理 + /// + [BurstCompile] + unsafe struct SplitPost_TeamCollider_Job : IJobParallelFor + { + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray teamDataArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray centerDataArray; + + // collider + [Unity.Collections.ReadOnly] + public NativeArray colliderFramePositions; + [Unity.Collections.ReadOnly] + public NativeArray colliderFrameRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldFramePositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldFrameRotations; + + // transform + [Unity.Collections.ReadOnly] + public NativeArray transformPositionArray; + [Unity.Collections.ReadOnly] + public NativeArray transformRotationArray; + [Unity.Collections.ReadOnly] + public NativeArray transformScaleArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray transformLocalPositionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray transformLocalRotationArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray vertexParentIndices; + + // バッチ内のローカルチームインデックスごと + public void Execute(int localIndex) + { + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafePtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafePtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // BoneClothの場合はTransformのローカル姿勢を計算する + VirtualMeshManager.SimulationPostProxyMeshUpdateLocalTransform( + // team + ref tdata, + // vmesh + ref attributes, + ref vertexParentIndices, + // transform + ref transformPositionArray, + ref transformRotationArray, + ref transformScaleArray, + ref transformLocalPositionArray, + ref transformLocalRotationArray + ); + + // ■コライダー更新後処理 + ColliderManager.SimulationPostUpdate( + // team + ref tdata, + // collider + ref colliderFramePositions, + ref colliderFrameRotations, + ref colliderOldFramePositions, + ref colliderOldFrameRotations + ); + + // ■チーム更新後処理 + TeamManager.SimulationPostTeamUpdate( + // team + ref tdata, + ref cdata + ); + } + } + } +} + diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs.meta new file mode 100644 index 0000000..fa92479 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2dd0faec9645ac1499b7eceb32ba4f10 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs new file mode 100644 index 0000000..79d9f30 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs @@ -0,0 +1,117 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using System.Collections.Generic; +using Unity.Mathematics; +using UnityEngine; + +namespace MagicaCloth2 +{ + public partial class TransformData + { + /// + /// PreBuildの共有部分保存データ + /// + [System.Serializable] + public class ShareSerializationData + { + public ExSimpleNativeArray.SerializationData flagArray; + public ExSimpleNativeArray.SerializationData initLocalPositionArray; + public ExSimpleNativeArray.SerializationData initLocalRotationArray; + } + + public ShareSerializationData ShareSerialize() + { + var sdata = new ShareSerializationData(); + try + { + sdata.flagArray = flagArray.Serialize(); + sdata.initLocalPositionArray = initLocalPositionArray.Serialize(); + sdata.initLocalRotationArray = initLocalRotationArray.Serialize(); + } + catch (Exception exception) + { + Debug.LogException(exception); + } + + return sdata; + } + + public static TransformData ShareDeserialize(ShareSerializationData sdata) + { + if (sdata == null) + return null; + + var tdata = new TransformData(); + try + { + tdata.flagArray = new ExSimpleNativeArray(sdata.flagArray); + tdata.initLocalPositionArray = new ExSimpleNativeArray(sdata.initLocalPositionArray); + tdata.initLocalRotationArray = new ExSimpleNativeArray(sdata.initLocalRotationArray); + } + catch (Exception exception) + { + Debug.LogException(exception); + } + + return tdata; + } + + //========================================================================================= + /// + /// PreBuild固有部分の保存データ + /// + [System.Serializable] + public class UniqueSerializationData : ITransform + { + public Transform[] transformArray; + + public void GetUsedTransform(HashSet transformSet) + { + if (transformArray != null) + { + foreach (var t in transformArray) + { + if (t) + transformSet.Add(t); + } + } + } + + public void ReplaceTransform(Dictionary replaceDict) + { + if (transformArray != null) + { + for (int i = 0; i < transformArray.Length; i++) + { + var t = transformArray[i]; + if (t) + { + int id = t.GetInstanceID(); + if (id != 0 && replaceDict.ContainsKey(id)) + { + transformArray[i] = replaceDict[id]; + } + } + } + } + } + } + + public UniqueSerializationData UniqueSerialize() + { + var sdata = new UniqueSerializationData(); + try + { + sdata.transformArray = transformList.ToArray(); + } + catch (Exception exception) + { + Debug.LogException(exception); + } + + return sdata; + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs.meta new file mode 100644 index 0000000..214dd16 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7ae8000d77bdbae4b86315fcc83b2518 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs new file mode 100644 index 0000000..df3990c --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs @@ -0,0 +1,82 @@ +// Magica Cloth 2. +// Copyright (c) 2025 MagicaSoft. +// https://magicasoft.jp +using System.Collections.Generic; +using UnityEngine; + +namespace MagicaCloth2 +{ + [System.Serializable] + public class TransformRecordSerializeData : ITransform + { + public Transform transform; // 利用しないが念の為に記録 + public Vector3 localPosition; + public Quaternion localRotation; + public Vector3 position; + public Quaternion rotation; + public Vector3 scale; // lossy scale + public Matrix4x4 localToWorldMatrix; + public Matrix4x4 worldToLocalMatrix; + + public void Serialize(TransformRecord tr) + { + Debug.Assert(tr != null); + + transform = tr.transform; + localPosition = tr.localPosition; + localRotation = tr.localRotation; + position = tr.position; + rotation = tr.rotation; + scale = tr.scale; + localToWorldMatrix = tr.localToWorldMatrix; + worldToLocalMatrix = tr.worldToLocalMatrix; + } + + public void Deserialize(TransformRecord tr) + { + Debug.Assert(tr != null); + + // 座標系のみ復元する + tr.localPosition = localPosition; + tr.localRotation = localRotation; + tr.position = position; + tr.rotation = rotation; + tr.scale = scale; + tr.localToWorldMatrix = localToWorldMatrix; + tr.worldToLocalMatrix = worldToLocalMatrix; + } + + public int GetLocalHash() + { + int hash = 0; + if (transform) + hash += (123 + transform.childCount * 345); + + return hash; + } + + public int GetGlobalHash() + { + int hash = 0; + + // ローカル姿勢のみ + hash += localPosition.GetHashCode(); + hash += localRotation.GetHashCode(); + + return hash; + } + + public void GetUsedTransform(HashSet transformSet) + { + if (transform) + transformSet.Add(transform); + } + + public void ReplaceTransform(Dictionary replaceDict) + { + int id = transform != null ? transform.GetInstanceID() : 0; + if (id != 0 && replaceDict.ContainsKey(id)) + transform = replaceDict[id]; + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs.meta new file mode 100644 index 0000000..499360b --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f4930f42a38b269439caa19e9603c9aa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild.meta b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild.meta new file mode 100644 index 0000000..d9315f5 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1f85ba9270154ec4ea99adc777266a0f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs new file mode 100644 index 0000000..99c105c --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs @@ -0,0 +1,64 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System.Collections.Generic; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// PreBuildの保存アセットデータ + /// + [CreateAssetMenu(fileName = "Data", menuName = "MagicaCloth2/PreBuildScriptableObject")] + public class PreBuildScriptableObject : ScriptableObject + { + /// + /// 複数のPreBuildデータを格納可能 + /// + public List sharePreBuildDataList = new List(); + + //========================================================================================= + public bool HasPreBuildData(string buildId) + { + return GetPreBuildData(buildId) != null; + } + + public SharePreBuildData GetPreBuildData(string buildId) + { + foreach (var sdata in sharePreBuildDataList) + { + if (sdata.CheckBuildId(buildId)) + return sdata; + } + + return null; + } + + public void AddPreBuildData(SharePreBuildData sdata) + { + int index = sharePreBuildDataList.FindIndex(x => x.buildId == sdata.buildId); + if (index >= 0) + sharePreBuildDataList[index] = sdata; + else + sharePreBuildDataList.Add(sdata); + } + + //========================================================================================= + /// + /// すべてのPreBuildデータをデシリアライズしてマネージャに登録します + /// この処理は負荷が高いため事前に実行しておくことでクロスデータ利用時の負荷を軽減できます + /// Deserialize all PreBuild data and register it with the manager. + /// This process requires a high load, so running it in advance can reduce the load when using cross data. + /// + public void Warmup() + { + if (Application.isPlaying == false) + return; + + sharePreBuildDataList.ForEach(sdata => + { + MagicaManager.PreBuild.RegisterPreBuildData(sdata, false); + }); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs.meta new file mode 100644 index 0000000..a2cc961 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45b12b58fd27b9a4bae4f50db55b4459 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs new file mode 100644 index 0000000..78f7656 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs @@ -0,0 +1,101 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// PreBuildの保存データ + /// + [System.Serializable] + public class PreBuildSerializeData : ITransform + { + /// + /// 有効状態 + /// Valid state. + /// + public bool enabled = false; + + /// + /// ビルド識別ID + /// + public string buildId; + + /// + /// ビルドデータの共有部分 + /// このデータは複数のインスタンスで共有されるためScriptableObjectとして外部アセットとして保存される + /// + public PreBuildScriptableObject preBuildScriptableObject = null; + + /// + /// ビルドデータの固有部分 + /// このデータはインスタンスごとに固有となる + /// + public UniquePreBuildData uniquePreBuildData; + + //========================================================================================= + /// + /// PreBuild利用の有無 + /// + /// + public bool UsePreBuild() => enabled; + + /// + /// PreBuildデータの検証 + /// + /// + public ResultCode DataValidate() + { + if (uniquePreBuildData == null) + return new ResultCode(Define.Result.PreBuildData_Empty); + + var preBuildData = GetSharePreBuildData(); + if (preBuildData == null) + return new ResultCode(Define.Result.PreBuildData_Empty); + + var result = preBuildData.DataValidate(); + if (result.IsFaild()) + return result; + + result = uniquePreBuildData.DataValidate(); + if (result.IsFaild()) + return result; + + return ResultCode.Success; + } + + public SharePreBuildData GetSharePreBuildData() + { + if (preBuildScriptableObject == null) + return null; + + if (string.IsNullOrEmpty(buildId)) + return null; + + return preBuildScriptableObject.GetPreBuildData(buildId); ; + } + + /// + /// ビルドIDを生成する(英数字8文字) + /// + /// + public static string GenerateBuildID() + { + Guid g = Guid.NewGuid(); + return g.ToString().Substring(0, 8); + } + + public void GetUsedTransform(HashSet transformSet) + { + uniquePreBuildData.GetUsedTransform(transformSet); + } + + public void ReplaceTransform(Dictionary replaceDict) + { + uniquePreBuildData.ReplaceTransform(replaceDict); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs.meta new file mode 100644 index 0000000..2fa6bc0 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c7522d5a2a34f84c9588683c5574fa9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs new file mode 100644 index 0000000..c8cc032 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs @@ -0,0 +1,69 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System.Collections.Generic; +using System.Text; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// PreBuildデータの共有部分 + /// + [System.Serializable] + public class SharePreBuildData + { + public int version; + public string buildId; + public ResultCode buildResult; + public Vector3 buildScale; + + public List renderSetupDataList = new List(); + + public VirtualMesh.ShareSerializationData proxyMesh; + public List renderMeshList = new List(); + + public DistanceConstraint.ConstraintData distanceConstraintData; + public TriangleBendingConstraint.ConstraintData bendingConstraintData; + public InertiaConstraint.ConstraintData inertiaConstraintData; + + //========================================================================================= + public ResultCode DataValidate() + { + if (version != Define.System.LatestPreBuildVersion) + return new ResultCode(Define.Result.PreBuildData_VersionMismatch); + + if (buildScale.x < Define.System.Epsilon) + return new ResultCode(Define.Result.PreBuildData_InvalidScale); + + if (buildResult.IsFaild()) + return buildResult; + + return ResultCode.Success; + } + + public bool CheckBuildId(string buildId) + { + if (string.IsNullOrEmpty(buildId)) + return false; + + return this.buildId == buildId; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(1024); + + sb.AppendLine("<<<<< PreBuildData >>>>>"); + sb.AppendLine($"Version:{version}"); + sb.AppendLine($"BuildID:{buildId}"); + sb.AppendLine($"BuildResult:{buildResult.GetResultString()}"); + sb.AppendLine($"BuildScale:{buildScale}"); + sb.AppendLine(proxyMesh.ToString()); + sb.AppendLine($"renderMeshList:{renderMeshList.Count}"); + sb.AppendLine($"renderSetupDataList:{renderSetupDataList.Count}"); + + return sb.ToString(); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs.meta new file mode 100644 index 0000000..5d3135c --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 280185e34f035f44d999fc83fffe8ab9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs new file mode 100644 index 0000000..af90e07 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs @@ -0,0 +1,49 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System.Collections.Generic; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// PreBuildデータの固有部分 + /// + [System.Serializable] + public class UniquePreBuildData : ITransform + { + public int version; + public ResultCode buildResult; + + public List renderSetupDataList = new List(); + + public VirtualMesh.UniqueSerializationData proxyMesh; + public List renderMeshList = new List(); + + //========================================================================================= + public ResultCode DataValidate() + { + if (version != Define.System.LatestPreBuildVersion) + return new ResultCode(Define.Result.PreBuildData_VersionMismatch); + + if (buildResult.IsFaild()) + return buildResult; + + return ResultCode.Success; + } + + public void GetUsedTransform(HashSet transformSet) + { + renderSetupDataList.ForEach(x => x?.GetUsedTransform(transformSet)); + proxyMesh?.GetUsedTransform(transformSet); + renderMeshList.ForEach(x => x?.GetUsedTransform(transformSet)); + } + + public void ReplaceTransform(Dictionary replaceDict) + { + renderSetupDataList.ForEach(x => x?.ReplaceTransform(replaceDict)); + proxyMesh?.ReplaceTransform(replaceDict); + renderMeshList.ForEach(x => x?.ReplaceTransform(replaceDict)); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs.meta new file mode 100644 index 0000000..0d0e2f2 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0cee094d81395864ba3ef342016a8de6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs new file mode 100644 index 0000000..2ca0e18 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs @@ -0,0 +1,30 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using Unity.Collections; + +namespace MagicaCloth2 +{ + /// + /// NativeParallelHashMapの拡張メソッド + /// + public static class NativeParallelHashMap + { + /// + /// NativeParallelMultiHashMapが確保されている場合のみDispose()する + /// + /// + /// + /// +#if MC2_COLLECTIONS_200 + public static void MC2DisposeSafe(ref this NativeParallelHashMap map) where TKey : unmanaged, IEquatable where TValue : unmanaged, IEquatable +#else + public static void MC2DisposeSafe(ref this NativeParallelHashMap map) where TKey : struct, IEquatable where TValue : struct, IEquatable +#endif + { + if (map.IsCreated) + map.Dispose(); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs.meta new file mode 100644 index 0000000..978ad31 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f6dcd839c56f63b42af8231ec3cb1841 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs new file mode 100644 index 0000000..5d77592 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs @@ -0,0 +1,291 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using System.Collections.Generic; +using System.Text; +using Unity.Collections; +using Unity.Mathematics; +using UnityEngine; + +namespace MagicaCloth2 +{ + public partial class VirtualMesh + { + /// + /// PreBuildの共有部分データ + /// + [System.Serializable] + public class ShareSerializationData + { + public string name; + public MeshType meshType; + public bool isBoneCloth; + + // 基本 + public ExSimpleNativeArray.SerializationData referenceIndices; + public ExSimpleNativeArray.SerializationData attributes; + public ExSimpleNativeArray.SerializationData localPositions; + public ExSimpleNativeArray.SerializationData localNormals; + public ExSimpleNativeArray.SerializationData localTangents; + public ExSimpleNativeArray.SerializationData uv; + public ExSimpleNativeArray.SerializationData boneWeights; + public ExSimpleNativeArray.SerializationData triangles; + public ExSimpleNativeArray.SerializationData lines; + public int centerTransformIndex; + public float4x4 initLocalToWorld; + public float4x4 initWorldToLocal; + public quaternion initRotation; + public quaternion initInverseRotation; + public float3 initScale; + public int skinRootIndex; + public ExSimpleNativeArray.SerializationData skinBoneTransformIndices; + public ExSimpleNativeArray.SerializationData skinBoneBindPoses; + public TransformData.ShareSerializationData transformData; + public AABB boundingBox; + public float averageVertexDistance; + public float maxVertexDistance; + + // プロキシメッシュ + public byte[] vertexToTriangles; + public byte[] vertexToVertexIndexArray; + public byte[] vertexToVertexDataArray; + public byte[] edges; + public byte[] edgeFlags; + public int2[] edgeToTrianglesKeys; + public ushort[] edgeToTrianglesValues; + public byte[] vertexBindPosePositions; + public byte[] vertexBindPoseRotations; + public byte[] vertexToTransformRotations; + public byte[] vertexDepths; + public byte[] vertexRootIndices; + public byte[] vertexParentIndices; + public byte[] vertexChildIndexArray; + public byte[] vertexChildDataArray; + public byte[] vertexLocalPositions; + public byte[] vertexLocalRotations; + public byte[] normalAdjustmentRotations; + public byte[] baseLineFlags; + public byte[] baseLineStartDataIndices; + public byte[] baseLineDataCounts; + public byte[] baseLineData; + public int[] customSkinningBoneIndices; + public ushort[] centerFixedList; + public float3 localCenterPosition; + + // マッピングメッシュ + public float3 centerWorldPosition; + public quaternion centerWorldRotation; + public float3 centerWorldScale; + public float4x4 toProxyMatrix; + public quaternion toProxyRotation; + + public override string ToString() + { + StringBuilder sb = new StringBuilder(1024); + + sb.AppendLine("===== VirtualMesh.SerializeData ====="); + sb.AppendLine($"name:{name}"); + sb.AppendLine($"meshType:{meshType}"); + sb.AppendLine($"isBoneCloth:{isBoneCloth}"); + sb.AppendLine($"VertexCount:{attributes.count}"); + sb.AppendLine($"TriangleCount:{triangles.count}"); + sb.AppendLine($"LineCount:{lines.count}"); + + return sb.ToString(); + } + } + + public ShareSerializationData ShareSerialize() + { + var sdata = new ShareSerializationData(); + try + { + sdata.name = name; + sdata.meshType = meshType; + sdata.isBoneCloth = isBoneCloth; + + // 基本 + sdata.referenceIndices = referenceIndices.Serialize(); + sdata.attributes = attributes.Serialize(); + sdata.localPositions = localPositions.Serialize(); + sdata.localNormals = localNormals.Serialize(); + sdata.localTangents = localTangents.Serialize(); + sdata.uv = uv.Serialize(); + sdata.boneWeights = boneWeights.Serialize(); + sdata.triangles = triangles.Serialize(); + sdata.lines = lines.Serialize(); + sdata.centerTransformIndex = centerTransformIndex; + sdata.initLocalToWorld = initLocalToWorld; + sdata.initWorldToLocal = initWorldToLocal; + sdata.initRotation = initRotation; + sdata.initInverseRotation = initInverseRotation; + sdata.initScale = initScale; + sdata.skinRootIndex = skinRootIndex; + sdata.skinBoneTransformIndices = skinBoneTransformIndices.Serialize(); + sdata.skinBoneBindPoses = skinBoneBindPoses.Serialize(); + sdata.transformData = transformData?.ShareSerialize(); + if (boundingBox.IsCreated) + sdata.boundingBox = boundingBox.Value; + if (averageVertexDistance.IsCreated) + sdata.averageVertexDistance = averageVertexDistance.Value; + if (maxVertexDistance.IsCreated) + sdata.maxVertexDistance = maxVertexDistance.Value; + + // プロキシメッシュ + sdata.vertexToTriangles = vertexToTriangles.MC2ToRawBytes(); + sdata.vertexToVertexIndexArray = vertexToVertexIndexArray.MC2ToRawBytes(); + sdata.vertexToVertexDataArray = vertexToVertexDataArray.MC2ToRawBytes(); + sdata.edges = edges.MC2ToRawBytes(); + sdata.edgeFlags = edgeFlags.MC2ToRawBytes(); + (sdata.edgeToTrianglesKeys, sdata.edgeToTrianglesValues) = edgeToTriangles.MC2Serialize(); + sdata.vertexBindPosePositions = vertexBindPosePositions.MC2ToRawBytes(); + sdata.vertexBindPoseRotations = vertexBindPoseRotations.MC2ToRawBytes(); + sdata.vertexToTransformRotations = vertexToTransformRotations.MC2ToRawBytes(); + sdata.vertexDepths = vertexDepths.MC2ToRawBytes(); + sdata.vertexRootIndices = vertexRootIndices.MC2ToRawBytes(); + sdata.vertexParentIndices = vertexParentIndices.MC2ToRawBytes(); + sdata.vertexChildIndexArray = vertexChildIndexArray.MC2ToRawBytes(); + sdata.vertexChildDataArray = vertexChildDataArray.MC2ToRawBytes(); + sdata.vertexLocalPositions = vertexLocalPositions.MC2ToRawBytes(); + sdata.vertexLocalRotations = vertexLocalRotations.MC2ToRawBytes(); + sdata.normalAdjustmentRotations = normalAdjustmentRotations.MC2ToRawBytes(); + sdata.baseLineFlags = baseLineFlags.MC2ToRawBytes(); + sdata.baseLineStartDataIndices = baseLineStartDataIndices.MC2ToRawBytes(); + sdata.baseLineDataCounts = baseLineDataCounts.MC2ToRawBytes(); + sdata.baseLineData = baseLineData.MC2ToRawBytes(); + DataUtility.ArrayCopy(customSkinningBoneIndices, ref sdata.customSkinningBoneIndices); + DataUtility.ArrayCopy(centerFixedList, ref sdata.centerFixedList); + if (localCenterPosition.IsCreated) + sdata.localCenterPosition = localCenterPosition.Value; + + // マッピングメッシュ + sdata.centerWorldPosition = centerWorldPosition; + sdata.centerWorldRotation = centerWorldRotation; + sdata.centerWorldScale = centerWorldScale; + sdata.toProxyMatrix = toProxyMatrix; + sdata.toProxyRotation = toProxyRotation; + } + catch (Exception exception) + { + Debug.LogException(exception); + } + + return sdata; + } + + public static VirtualMesh ShareDeserialize(ShareSerializationData sdata) + { + var vmesh = new VirtualMesh(); + vmesh.isManaged = true; + + try + { + vmesh.name = sdata.name; + vmesh.meshType = sdata.meshType; + vmesh.isBoneCloth = sdata.isBoneCloth; + + // 基本 + vmesh.referenceIndices.Deserialize(sdata.referenceIndices); + vmesh.attributes.Deserialize(sdata.attributes); + vmesh.localPositions.Deserialize(sdata.localPositions); + vmesh.localNormals.Deserialize(sdata.localNormals); + vmesh.localTangents.Deserialize(sdata.localTangents); + vmesh.uv.Deserialize(sdata.uv); + vmesh.boneWeights.Deserialize(sdata.boneWeights); + vmesh.triangles.Deserialize(sdata.triangles); + vmesh.lines.Deserialize(sdata.lines); + vmesh.centerTransformIndex = sdata.centerTransformIndex; + vmesh.initLocalToWorld = sdata.initLocalToWorld; + vmesh.initWorldToLocal = sdata.initWorldToLocal; + vmesh.initRotation = sdata.initRotation; + vmesh.initInverseRotation = sdata.initInverseRotation; + vmesh.initScale = sdata.initScale; + vmesh.skinRootIndex = sdata.skinRootIndex; + vmesh.skinBoneTransformIndices.Deserialize(sdata.skinBoneTransformIndices); + vmesh.skinBoneBindPoses.Deserialize(sdata.skinBoneBindPoses); + vmesh.transformData = TransformData.ShareDeserialize(sdata.transformData); + vmesh.boundingBox = new NativeReference(sdata.boundingBox, Allocator.Persistent); + vmesh.averageVertexDistance = new NativeReference(sdata.averageVertexDistance, Allocator.Persistent); + vmesh.maxVertexDistance = new NativeReference(sdata.maxVertexDistance, Allocator.Persistent); + + // プロキシメッシュ + vmesh.vertexToTriangles = NativeArrayExtensions.MC2FromRawBytes>(sdata.vertexToTriangles); + vmesh.vertexToVertexIndexArray = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexToVertexIndexArray); + vmesh.vertexToVertexDataArray = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexToVertexDataArray); + vmesh.edges = NativeArrayExtensions.MC2FromRawBytes(sdata.edges); + vmesh.edgeFlags = NativeArrayExtensions.MC2FromRawBytes(sdata.edgeFlags); + vmesh.edgeToTriangles = NativeMultiHashMapExtensions.MC2Deserialize(sdata.edgeToTrianglesKeys, sdata.edgeToTrianglesValues); + vmesh.vertexBindPosePositions = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexBindPosePositions); + vmesh.vertexBindPoseRotations = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexBindPoseRotations); + vmesh.vertexToTransformRotations = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexToTransformRotations); + vmesh.vertexDepths = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexDepths); + vmesh.vertexRootIndices = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexRootIndices); + vmesh.vertexParentIndices = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexParentIndices); + vmesh.vertexChildIndexArray = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexChildIndexArray); + vmesh.vertexChildDataArray = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexChildDataArray); + vmesh.vertexLocalPositions = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexLocalPositions); + vmesh.vertexLocalRotations = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexLocalRotations); + vmesh.normalAdjustmentRotations = NativeArrayExtensions.MC2FromRawBytes(sdata.normalAdjustmentRotations); + vmesh.baseLineFlags = NativeArrayExtensions.MC2FromRawBytes(sdata.baseLineFlags); + vmesh.baseLineStartDataIndices = NativeArrayExtensions.MC2FromRawBytes(sdata.baseLineStartDataIndices); + vmesh.baseLineDataCounts = NativeArrayExtensions.MC2FromRawBytes(sdata.baseLineDataCounts); + vmesh.baseLineData = NativeArrayExtensions.MC2FromRawBytes(sdata.baseLineData); + DataUtility.ArrayCopy(sdata.customSkinningBoneIndices, ref vmesh.customSkinningBoneIndices); + DataUtility.ArrayCopy(sdata.centerFixedList, ref vmesh.centerFixedList); + vmesh.localCenterPosition = new NativeReference(sdata.localCenterPosition, Allocator.Persistent); + + // マッピングメッシュ + vmesh.centerWorldPosition = sdata.centerWorldPosition; + vmesh.centerWorldRotation = sdata.centerWorldRotation; + vmesh.centerWorldScale = sdata.centerWorldScale; + vmesh.toProxyMatrix = sdata.toProxyMatrix; + vmesh.toProxyRotation = sdata.toProxyRotation; + + vmesh.result.SetSuccess(); + } + catch (Exception exception) + { + Debug.LogException(exception); + vmesh.result.SetError(Define.Result.PreBuildData_VirtualMeshDeserializationException); + } + + return vmesh; + } + + //========================================================================================= + /// + /// PreBuildの固有部分データ + /// + [System.Serializable] + public class UniqueSerializationData : ITransform + { + public TransformData.UniqueSerializationData transformData; + + public void GetUsedTransform(HashSet transformSet) + { + transformData?.GetUsedTransform(transformSet); + } + + public void ReplaceTransform(Dictionary replaceDict) + { + transformData?.ReplaceTransform(replaceDict); + } + } + + public UniqueSerializationData UniqueSerialize() + { + var sdata = new UniqueSerializationData(); + try + { + sdata.transformData = transformData?.UniqueSerialize(); + } + catch (Exception exception) + { + Debug.LogException(exception); + } + + return sdata; + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs.meta new file mode 100644 index 0000000..392ec21 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0d0b2768c9c7600468b9f1a7b39dd80d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs new file mode 100644 index 0000000..2a68af9 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs @@ -0,0 +1,60 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// VirtualMeshの共有部分と固有部分を1つにまとめた情報 + /// + public class VirtualMeshContainer : IDisposable + { + public VirtualMesh shareVirtualMesh; + public VirtualMesh.UniqueSerializationData uniqueData; + + public VirtualMeshContainer() + { + } + + public VirtualMeshContainer(VirtualMesh vmesh) + { + shareVirtualMesh = vmesh; + uniqueData = null; + } + + public void Dispose() + { + shareVirtualMesh?.Dispose(); + } + + //========================================================================================= + public bool hasUniqueData => uniqueData != null; + + //========================================================================================= + public int GetTransformCount() + { + if (hasUniqueData) + return uniqueData.transformData.transformArray.Length; + else + return shareVirtualMesh.TransformCount; + } + + public Transform GetTransformFromIndex(int index) + { + if (hasUniqueData) + return uniqueData.transformData.transformArray[index]; + else + return shareVirtualMesh.transformData.GetTransformFromIndex(index); + } + + public Transform GetCenterTransform() + { + if (hasUniqueData) + return uniqueData.transformData.transformArray[shareVirtualMesh.centerTransformIndex]; + else + return shareVirtualMesh.GetCenterTransform(); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs.meta new file mode 100644 index 0000000..a2cb5a7 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bac7915dc7b0bda49baed15536766603 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs new file mode 100644 index 0000000..f8d7ece --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs @@ -0,0 +1,40 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using UnityEditor; + +namespace MagicaCloth2 +{ + /// + /// インスペクター拡張のベースクラス + /// + public class MagicaEditorBase : Editor + { + /// + /// マルチ選択編集の適用 + /// + /// + /// + /// + protected void ApplyMultiSelection(bool changed, string undoName, Action act) where T : ClothBehaviour + { + if (changed) + { + foreach (var obj in targets) + { + var tscr = obj as T; + + // Undo + Undo.RecordObject(tscr, undoName); + + act(tscr); + EditorUtility.SetDirty(tscr); + + // OnValidate()手動呼び出し + tscr.GetType().GetMethod("OnValidate", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.Invoke(tscr, null); + } + } + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs.meta new file mode 100644 index 0000000..13a9f4d --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3126cd1eb42b4af4aa38cea3c3836c3e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs new file mode 100644 index 0000000..8812fcb --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs @@ -0,0 +1,76 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using UnityEditor; +using UnityEngine; + +namespace MagicaCloth2 +{ + [CustomPropertyDrawer(typeof(SharePreBuildData))] + public class SharePreBuildDataDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + EditorGUI.BeginProperty(position, label, property); + + // サイズ + float lineHight = EditorGUIUtility.singleLineHeight; + + // 子のフィールドをインデントしない + var indent = EditorGUI.indentLevel; + EditorGUI.indentLevel = 0; + + var buildIdProperty = property.FindPropertyRelative("buildId"); + var versionProperty = property.FindPropertyRelative("version"); + var resultProperty = property.FindPropertyRelative("buildResult.result"); + + // テキスト幅調整 + EditorGUIUtility.labelWidth = position.width; + + // build Id + string buildId = string.IsNullOrEmpty(buildIdProperty.stringValue) ? "(Empty)" : buildIdProperty.stringValue; + EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), new GUIContent(buildId)); + position.y += lineHight; + + // インデント+1 + EditorGUI.indentLevel = indent + 1; + + // result + Define.Result ret = (Define.Result)resultProperty.enumValueIndex; + var result = new ResultCode(ret); + if (result.IsFaild() == false) + { + // バージョン確認 + if (versionProperty.intValue != Define.System.LatestPreBuildVersion) + result.SetError(Define.Result.PreBuildData_VersionMismatch); + } + + // result text + var backColor = GUI.color; + if (result.IsSuccess()) + { + GUI.color = Color.green; + EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), new GUIContent($"{result.Result}")); + } + else + { + GUI.color = Color.red; + EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), new GUIContent($"Error: {result.Result}")); + } + GUI.color = backColor; + + // インデントを元通りに戻します + EditorGUI.indentLevel = indent; + + EditorGUI.EndProperty(); + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + float h = EditorGUIUtility.singleLineHeight; + h *= 2; + + return h; + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs.meta new file mode 100644 index 0000000..7bd80fa --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c6706416db7bdd14cb7ed3f5195d6498 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild.meta b/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild.meta new file mode 100644 index 0000000..bbbd80b --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d09f86fb6833fb048935d02b3254e292 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs b/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs new file mode 100644 index 0000000..a645eaf --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs @@ -0,0 +1,514 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using System.Collections.Generic; +using Unity.Mathematics; +using UnityEditor; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// PreBuildDataの作成 + /// + public static class PreBuildDataCreation + { + /// + /// PreBuildDataを作成しアセットとして保存する. + /// Create PreBuildData and save it as an asset. + /// + /// + /// Show save dialog if ScriptableObject does not exist. + /// + public static ResultCode CreatePreBuildData(MagicaCloth cloth, bool useNewSaveDialog = true) + { + var sdata = cloth.SerializeData; + var preBuildData = cloth.GetSerializeData2().preBuildData; + string buildId = preBuildData.buildId; + + // ビルドIDが存在しない場合はここで新規作成する + if (string.IsNullOrEmpty(buildId)) + { + buildId = PreBuildSerializeData.GenerateBuildID(); + } + + // スクリプタブルオブジェクトへ保存 + if (preBuildData.preBuildScriptableObject == null && useNewSaveDialog) + { + string assetName = $"MagicaPreBuild_{buildId}"; + + // 保存フォルダ読み込み + const string StateKey = "MagicaCloth2_PreBuild_Folder"; + string path = SessionState.GetString(StateKey, "Assets/"); + + string assetPath = EditorUtility.SaveFilePanelInProject("Saving MagicaCloth pre-build data", assetName, "asset", "MagicaCloth pre-build data name", path); + //Debug.Log($"AssetPath:{assetPath}"); + if (string.IsNullOrEmpty(assetPath)) + return new ResultCode(Define.Result.Cancel); + + // 保存フォルダ書き込み + SessionState.SetString(StateKey, System.IO.Path.GetDirectoryName(assetPath)); + + var sobj = ScriptableObject.CreateInstance(); + AssetDatabase.CreateAsset(sobj, assetPath); + AssetDatabase.Refresh(); + + preBuildData.preBuildScriptableObject = sobj; + } + + var preBuildScriptableObject = preBuildData.preBuildScriptableObject; + if (preBuildScriptableObject == null) + return new ResultCode(Define.Result.PreBuild_InvalidPreBuildData); + + // 構築 + var sharePreBuildData = new SharePreBuildData(); + var uniquePreBuildData = new UniquePreBuildData(); + if (sdata.IsValid()) + { + MakePreBuildData(cloth, buildId, sharePreBuildData, uniquePreBuildData); + } + else + { + sharePreBuildData.buildResult.SetError(Define.Result.PreBuildData_InvalidClothData); + } + + // データシリアライズ + preBuildData.buildId = buildId; + preBuildScriptableObject.AddPreBuildData(sharePreBuildData); + preBuildData.uniquePreBuildData = uniquePreBuildData; + + EditorUtility.SetDirty(preBuildScriptableObject); + EditorUtility.SetDirty(cloth); + AssetDatabase.Refresh(); + + return sharePreBuildData.buildResult; + } + + static void MakePreBuildData(MagicaCloth cloth, string buildId, SharePreBuildData sharePreBuildData, UniquePreBuildData uniquePreBuildData) + { + //Debug.Log($"MakePreBuildData().start"); + //var span = new TimeSpan("PreBuild"); + + sharePreBuildData.version = Define.System.LatestPreBuildVersion; + sharePreBuildData.buildId = buildId; + sharePreBuildData.buildResult.SetProcess(); + uniquePreBuildData.version = Define.System.LatestPreBuildVersion; + uniquePreBuildData.buildResult.SetProcess(); + + var setupDataList = new List(); + VirtualMesh proxyMesh = null; + var renderMeshList = new List(); + + try + { + var sdata = cloth.SerializeData; + var sdata2 = cloth.GetSerializeData2(); + var clothType = sdata.clothType; + + //======================== Initialize ============================ + // クロスを生成するための最低限の情報が揃っているかチェックする + if (sdata.IsValid() == false) + { + sharePreBuildData.buildResult.SetResult(sdata.VerificationResult); + throw new MagicaClothProcessingException(); + } + + // 初期トランスフォーム状態 + var clothTransformRecord = new TransformRecord(cloth.ClothTransform, read: true); + + // 法線調整用トランスフォーム + var normalAdjustmentTransformRecord = new TransformRecord( + sdata.normalAlignmentSetting.adjustmentTransform ? + sdata.normalAlignmentSetting.adjustmentTransform : + cloth.ClothTransform, read: true); + + // セットアップ情報の初期化 + if (clothType == ClothProcess.ClothType.MeshCloth) + { + foreach (var ren in sdata.sourceRenderers) + { + if (ren) + { + var setupData = new RenderSetupData(null, ren); + if (setupData.IsFaild()) + { + sharePreBuildData.buildResult.Merge(setupData.result); + throw new MagicaClothProcessingException(); + } + setupDataList.Add(setupData); + + // セットアップ情報のシリアライズ + sharePreBuildData.renderSetupDataList.Add(setupData.ShareSerialize()); + uniquePreBuildData.renderSetupDataList.Add(setupData.UniqueSerialize()); + } + } + } + else if (clothType == ClothProcess.ClothType.BoneCloth || clothType == ClothProcess.ClothType.BoneSpring) + { + var setupData = new RenderSetupData( + null, + clothType == ClothProcess.ClothType.BoneCloth ? RenderSetupData.SetupType.BoneCloth : RenderSetupData.SetupType.BoneSpring, + clothTransformRecord.transform, + sdata.rootBones, + clothType == ClothProcess.ClothType.BoneCloth ? null : sdata.colliderCollisionConstraint.collisionBones, + clothType == ClothProcess.ClothType.BoneCloth ? sdata.connectionMode : RenderSetupData.BoneConnectionMode.Line, + cloth.name + ); + if (setupData.IsFaild()) + { + sharePreBuildData.buildResult.Merge(setupData.result); + throw new MagicaClothProcessingException(); + } + setupDataList.Add(setupData); + } + + // カスタムスキニングのボーン情報 + List customSkinningBoneRecords = new List(); + int bcnt = sdata.customSkinningSetting.skinningBones.Count; + for (int i = 0; i < bcnt; i++) + { + customSkinningBoneRecords.Add(new TransformRecord(sdata.customSkinningSetting.skinningBones[i], read: true)); + } + + //======================== Proxy/Mapping Mesh ============================ + // ペイントマップ情報 + bool usePaintMap = false; + var paintMapDataList = new List(); + if (clothType == ClothProcess.ClothType.MeshCloth && sdata.paintMode != ClothSerializeData.PaintMode.Manual) + { + var ret = cloth.Process.GeneratePaintMapDataList(paintMapDataList); + Develop.DebugLog($"Generate paint map data list. {ret.GetResultString()}"); + if (ret.IsError()) + { + sharePreBuildData.buildResult.Merge(ret); + throw new MagicaClothProcessingException(); + } + //if (paintMapDataList.Count != renderHandleList.Count) + if (paintMapDataList.Count != setupDataList.Count) + { + sharePreBuildData.buildResult.SetError(Define.Result.CreateCloth_PaintMapCountMismatch); + throw new MagicaClothProcessingException(); + } + usePaintMap = true; + } + + // セレクションデータ + SelectionData selectionData = usePaintMap ? new SelectionData() : sdata2.selectionData.Clone(); + bool isValidSelection = selectionData?.IsValid() ?? false; + + // プロキシメッシュ作成 + proxyMesh = new VirtualMesh("Proxy"); + proxyMesh.result.SetProcess(); + if (clothType == ClothProcess.ClothType.MeshCloth) + { + + // MeshClothではクロストランスフォームを追加しておく + proxyMesh.SetTransform(clothTransformRecord); + + if (setupDataList.Count == 0) + { + sharePreBuildData.buildResult.SetError(Define.Result.ClothProcess_InvalidRenderHandleList); + throw new MagicaClothProcessingException(); + } + + // render mesh import + selection + merge + for (int i = 0; i < setupDataList.Count; i++) + { + VirtualMesh renderMesh = null; + try + { + // レンダーメッシュ作成 + var renderSetupData = setupDataList[i]; + renderMesh = new VirtualMesh($"[{renderSetupData.name}]"); + renderMesh.result.SetProcess(); + + // import ------------------------------------------------- + renderMesh.ImportFrom(renderSetupData, sdata.GetUvChannel()); + if (renderMesh.IsError) + { + sharePreBuildData.buildResult.Merge(renderMesh.result); + throw new MagicaClothProcessingException(); + } + Develop.DebugLog($"(IMPORT) {renderMesh}"); + + // selection ---------------------------------------------- + // MeshClothでペイントテクスチャ指定の場合はセレクションデータを生成する + SelectionData renderSelectionData = selectionData; + if (usePaintMap) + { + // セレクションデータ生成 + var ret = cloth.Process.GenerateSelectionDataFromPaintMap(clothTransformRecord, renderMesh, paintMapDataList[i], out renderSelectionData); + Develop.DebugLog($"Generate selection from paint map. {ret.GetResultString()}"); + if (ret.IsError()) + { + sharePreBuildData.buildResult.Merge(ret); + throw new MagicaClothProcessingException(); + } + + // セレクションデータ結合 + selectionData.Merge(renderSelectionData); + } + isValidSelection = selectionData?.IsValid() ?? false; + + // メッシュの切り取り + if (renderSelectionData?.IsValid() ?? false) + { + // 余白 + float mergin = renderMesh.CalcSelectionMergin(sdata.reductionSetting); + mergin = math.max(mergin, Define.System.MinimumGridSize); + + // セレクション情報から切り取りの実行 + // ペイントマップの場合はレンダラーごとのセレクションデータで切り取り + renderMesh.SelectionMesh(renderSelectionData, clothTransformRecord.localToWorldMatrix, mergin); + if (renderMesh.IsError) + { + sharePreBuildData.buildResult.Merge(renderMesh.result); + throw new MagicaClothProcessingException(); + } + Develop.DebugLog($"(SELECTION) {renderMesh}"); + } + + // レンダーメッシュの作成完了 + renderMesh.result.SetSuccess(); + + // merge -------------------------------------------------- + proxyMesh.AddMesh(renderMesh); + + // レンダーメッシュ情報を記録 + renderMeshList.Add(renderMesh); + renderMesh = null; + } + catch (MagicaClothProcessingException) + { + throw; + } + catch (Exception exception) + { + Debug.LogException(exception); + sharePreBuildData.buildResult.SetError(Define.Result.ClothProcess_Exception); + throw; + } + finally + { + // この時点で作業用renderMeshが存在する場合は中断されているので開放する + renderMesh?.Dispose(); + } + } + Develop.DebugLog($"(MERGE) {proxyMesh}"); + + // リダクション + if (proxyMesh.VertexCount > 1) + { + if (sdata.reductionSetting.IsEnabled) + { + proxyMesh.Reduction(sdata.reductionSetting, System.Threading.CancellationToken.None); + if (proxyMesh.IsError) + { + sharePreBuildData.buildResult.Merge(proxyMesh.result); + throw new MagicaClothProcessingException(); + } + + Develop.DebugLog($"(REDUCTION) {proxyMesh}"); + } + } + } + else if (clothType == ClothProcess.ClothType.BoneCloth || clothType == ClothProcess.ClothType.BoneSpring) + { + // import + var boneClothSetupData = setupDataList[0]; + proxyMesh.ImportFrom(boneClothSetupData, 0); + if (proxyMesh.IsError) + { + sharePreBuildData.buildResult.Merge(proxyMesh.result); + throw new MagicaClothProcessingException(); + } + Develop.DebugLog($"(IMPORT) {proxyMesh}"); + + // セレクションデータが存在しない場合は簡易作成する + if (isValidSelection == false) + { + selectionData = new SelectionData(proxyMesh, float4x4.identity); + if (selectionData.Count > 0) + { + // まずすべて移動設定 + selectionData.Fill(VertexAttribute.Move); + + // 次にルートのみ固定 + foreach (int id in boneClothSetupData.rootTransformIdList) + { + int rootIndex = boneClothSetupData.GetTransformIndexFromId(id); + selectionData.attributes[rootIndex] = VertexAttribute.Fixed; + } + isValidSelection = selectionData.IsValid(); + } + } + } + + // 元の頂点から結合頂点へのインデックスを初期化 + if (proxyMesh.joinIndices.IsCreated == false) + { + proxyMesh.joinIndices = new Unity.Collections.NativeArray(proxyMesh.VertexCount, Unity.Collections.Allocator.Persistent); + JobUtility.SerialNumberRun(proxyMesh.joinIndices, proxyMesh.VertexCount); // 連番をつける + } + + // optimization + proxyMesh.Optimization(); + if (proxyMesh.IsError) + { + sharePreBuildData.buildResult.Merge(proxyMesh.result); + throw new MagicaClothProcessingException(); + } + Develop.DebugLog($"(OPTIMIZE) {proxyMesh}"); + + // attribute + if (isValidSelection) + { + // セレクションデータから頂点属性を付与する + proxyMesh.ApplySelectionAttribute(selectionData); + if (proxyMesh.IsError) + { + sharePreBuildData.buildResult.Merge(proxyMesh.result); + throw new MagicaClothProcessingException(); + } + } + + // proxy mesh(属性決定後に実行) + proxyMesh.ConvertProxyMesh(sdata, clothTransformRecord, customSkinningBoneRecords, normalAdjustmentTransformRecord); + if (proxyMesh.IsError) + { + sharePreBuildData.buildResult.Merge(proxyMesh.result); + throw new MagicaClothProcessingException(); + } + Develop.DebugLog($"(PROXY) {proxyMesh}"); + + // ProxyMeshの最終チェック + if (proxyMesh.VertexCount > Define.System.MaxProxyMeshVertexCount) + { + sharePreBuildData.buildResult.SetError(Define.Result.ProxyMesh_Over32767Vertices); + throw new MagicaClothProcessingException(); + } + if (proxyMesh.EdgeCount > Define.System.MaxProxyMeshEdgeCount) + { + sharePreBuildData.buildResult.SetError(Define.Result.ProxyMesh_Over32767Edges); + throw new MagicaClothProcessingException(); + } + if (proxyMesh.TriangleCount > Define.System.MaxProxyMeshTriangleCount) + { + sharePreBuildData.buildResult.SetError(Define.Result.ProxyMesh_Over32767Triangles); + throw new MagicaClothProcessingException(); + } + + // finish + if (proxyMesh.IsError) + { + sharePreBuildData.buildResult.Merge(proxyMesh.result); + throw new MagicaClothProcessingException(); + } + proxyMesh.result.SetSuccess(); + Develop.DebugLog("CreateProxyMesh finish!"); + + // Mapping(MeshClothのみ) + if (clothType == ClothProcess.ClothType.MeshCloth) + { + foreach (VirtualMesh renderMesh in renderMeshList) + { + renderMesh.Mapping(proxyMesh); + if (renderMesh.IsError) + { + sharePreBuildData.buildResult.Merge(renderMesh.result); + throw new MagicaClothProcessingException(); + } + Develop.DebugLog($"(MAPPING) {renderMesh}"); + } + } + + // ======================= Cloth Data =============================== + // クロスデータ作成 + var parameters = cloth.SerializeData.GetClothParameters(); + var distanceConstraintData = DistanceConstraint.CreateData(proxyMesh, parameters); + if (distanceConstraintData != null) + { + if (distanceConstraintData.result.IsSuccess()) + { + sharePreBuildData.distanceConstraintData = distanceConstraintData; + } + else + { + sharePreBuildData.buildResult.Merge(distanceConstraintData.result); + throw new MagicaClothProcessingException(); + } + } + var bendingConstraintData = TriangleBendingConstraint.CreateData(proxyMesh, parameters); + if (bendingConstraintData != null) + { + if (bendingConstraintData.result.IsSuccess()) + { + sharePreBuildData.bendingConstraintData = bendingConstraintData; + } + else + { + sharePreBuildData.buildResult.Merge(bendingConstraintData.result); + throw new MagicaClothProcessingException(); + } + } + var inertiaConstraintData = InertiaConstraint.CreateData(proxyMesh, parameters); + if (inertiaConstraintData != null) + { + if (inertiaConstraintData.result.IsSuccess()) + { + sharePreBuildData.inertiaConstraintData = inertiaConstraintData; + } + else + { + sharePreBuildData.buildResult.Merge(inertiaConstraintData.result); + throw new MagicaClothProcessingException(); + } + } + + // ======================= Serialize =============================== + sharePreBuildData.buildScale = clothTransformRecord.scale; + sharePreBuildData.proxyMesh = proxyMesh.ShareSerialize(); + uniquePreBuildData.proxyMesh = proxyMesh.UniqueSerialize(); + foreach (VirtualMesh renderMesh in renderMeshList) + { + sharePreBuildData.renderMeshList.Add(renderMesh.ShareSerialize()); + uniquePreBuildData.renderMeshList.Add(renderMesh.UniqueSerialize()); + } + + // 成功 + sharePreBuildData.buildResult.SetSuccess(); + + Develop.DebugLog(sharePreBuildData); + } + catch (MagicaClothProcessingException) + { + if (sharePreBuildData.buildResult.IsError() == false) + sharePreBuildData.buildResult.SetError(Define.Result.PreBuildData_MagicaClothException); + sharePreBuildData.buildResult.DebugLog(); + } + catch (Exception exception) + { + Debug.LogException(exception); + sharePreBuildData.buildResult.SetError(Define.Result.PreBuildData_UnknownError); + } + finally + { + setupDataList.ForEach(x => x.Dispose()); + setupDataList.Clear(); + + renderMeshList.ForEach(x => x?.Dispose()); + renderMeshList.Clear(); + + proxyMesh?.Dispose(); + proxyMesh = null; + + // 内部情報は外部情報の結果をコピー + uniquePreBuildData.buildResult = sharePreBuildData.buildResult; + } + + //Debug.Log(span); + //Debug.Log($"MakePreBuildData().end"); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs.meta new file mode 100644 index 0000000..5f32c89 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d37ab6d9c5e31034a9503a7cedd96ee3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/VRCDeveloperTool.meta b/Assets/External/VRCDeveloperTool.meta new file mode 100644 index 0000000..7d31ad2 --- /dev/null +++ b/Assets/External/VRCDeveloperTool.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 457bd13b309fa6f448bc060c257d7ba7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/YAMOScripts.meta b/Assets/External/YAMOScripts.meta new file mode 100644 index 0000000..4506180 --- /dev/null +++ b/Assets/External/YAMOScripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f43d31ff050db5341a2e7dcb2132b522 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Utility/FindUnusedBones/FindUnusedBones.cs b/Assets/Scripts/Utility/FindUnusedBones/FindUnusedBones.cs deleted file mode 100644 index a53fa1a..0000000 --- a/Assets/Scripts/Utility/FindUnusedBones/FindUnusedBones.cs +++ /dev/null @@ -1,109 +0,0 @@ -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; - -public class FindUnusedBones : EditorWindow -{ - private List excludeStrings = new List(); // 제외할 문자열 리스트 - - [MenuItem("Tools/Find Unused Bones")] - public static void ShowWindow() - { - GetWindow("Find Unused Bones"); - } - - private void OnGUI() - { - GUILayout.Label("Exclude Strings", EditorStyles.boldLabel); - - // 동적으로 문자열 입력 필드와 + - 버튼을 추가 - for (int i = 0; i < excludeStrings.Count; i++) - { - GUILayout.BeginHorizontal(); - excludeStrings[i] = EditorGUILayout.TextField($"Exclude String {i + 1}", excludeStrings[i]); - - if (GUILayout.Button("-", GUILayout.Width(20))) - { - excludeStrings.RemoveAt(i); - } - GUILayout.EndHorizontal(); - } - - if (GUILayout.Button("+", GUILayout.Width(20))) - { - excludeStrings.Add(string.Empty); // 빈 문자열 입력 필드 추가 - } - - GUILayout.Space(20); - - if (GUILayout.Button("Find and Select Unused Bones")) - { - FindAndSelectUnusedBones(); - } - } - - private void FindAndSelectUnusedBones() - { - if (Selection.activeGameObject == null) - { - Debug.LogWarning("No GameObject selected!"); - return; - } - - Transform root = Selection.activeGameObject.transform; - SkinnedMeshRenderer[] skinnedMeshRenderers = root.GetComponentsInChildren(); - - HashSet usedBones = new HashSet(); - HashSet excludedObjects = new HashSet(); - - // Add all bones used by SkinnedMeshRenderers to usedBones set - foreach (var skinnedMeshRenderer in skinnedMeshRenderers) - { - foreach (var bone in skinnedMeshRenderer.bones) - { - usedBones.Add(bone); - } - // Add the SkinnedMeshRenderer's gameObject and its parents to excludedObjects set - Transform current = skinnedMeshRenderer.transform; - while (current != null) - { - excludedObjects.Add(current); - current = current.parent; - } - } - - List unusedBones = new List(); - Transform[] allBones = root.GetComponentsInChildren(); - foreach (var bone in allBones) - { - // 문자열 필터링: 사용자가 입력한 문자열을 포함한 오브젝트는 제외 - bool excludeBone = false; - foreach (var excludeString in excludeStrings) - { - if (!string.IsNullOrEmpty(excludeString) && bone.name.ToLower().Contains(excludeString.ToLower())) - { - excludeBone = true; - break; - } - } - - if (!usedBones.Contains(bone) && - !excludedObjects.Contains(bone) && - bone != root && - !excludeBone) // 필터링된 오브젝트 제외 - { - unusedBones.Add(bone); - } - } - - if (unusedBones.Count > 0) - { - Selection.objects = unusedBones.ConvertAll(b => b.gameObject).ToArray(); - Debug.Log($"Found {unusedBones.Count} unused bones. Selected in the hierarchy."); - } - else - { - Debug.Log("No unused bones found."); - } - } -} diff --git a/Assets/Scripts/Utility/ObjectNameChanger/ObjectNameChanger.cs b/Assets/Scripts/Utility/ObjectNameChanger/ObjectNameChanger.cs deleted file mode 100644 index d6cd485..0000000 --- a/Assets/Scripts/Utility/ObjectNameChanger/ObjectNameChanger.cs +++ /dev/null @@ -1,99 +0,0 @@ -using UnityEngine; -using UnityEditor; - -public class ObjectNameModifier : EditorWindow -{ - private string prefixText = string.Empty; - private string suffixText = string.Empty; - - [MenuItem("Tools/Object Name Modifier")] - public static void ShowWindow() - { - GetWindow("Object Name Modifier"); - } - - private void OnGUI() - { - GUILayout.Label("Modify Object Names", EditorStyles.boldLabel); - - // Prefix Text 입력 - prefixText = EditorGUILayout.TextField("Prefix", prefixText); - - // Suffix Text 입력 - suffixText = EditorGUILayout.TextField("Suffix", suffixText); - - GUILayout.Space(10); - - // Prefix와 Suffix 추가 버튼 - if (GUILayout.Button("Apply Prefix and Suffix")) - { - ApplyPrefixAndSuffix(); - } - - GUILayout.Space(10); - - // 문자열 앞/뒤 한 글자씩 제거 - if (GUILayout.Button("Remove First Character")) - { - RemoveFirstCharacter(); - } - if (GUILayout.Button("Remove Last Character")) - { - RemoveLastCharacter(); - } - - GUILayout.Space(10); - - // 빈칸을 _로 변경 - if (GUILayout.Button("Replace Spaces with Underscores")) - { - ReplaceSpacesWithUnderscores(); - } - } - - // Prefix와 Suffix를 적용하는 메서드 - void ApplyPrefixAndSuffix() - { - foreach (GameObject obj in Selection.gameObjects) - { - Undo.RecordObject(obj, "Change Object Name"); - obj.name = prefixText + obj.name + suffixText; - } - } - - // 첫 글자를 제거하는 메서드 - void RemoveFirstCharacter() - { - foreach (GameObject obj in Selection.gameObjects) - { - if (obj.name.Length > 0) - { - Undo.RecordObject(obj, "Remove First Character"); - obj.name = obj.name.Substring(1); - } - } - } - - // 마지막 글자를 제거하는 메서드 - void RemoveLastCharacter() - { - foreach (GameObject obj in Selection.gameObjects) - { - if (obj.name.Length > 0) - { - Undo.RecordObject(obj, "Remove Last Character"); - obj.name = obj.name.Substring(0, obj.name.Length - 1); - } - } - } - - // 빈칸을 _로 변경하는 메서드 - void ReplaceSpacesWithUnderscores() - { - foreach (GameObject obj in Selection.gameObjects) - { - Undo.RecordObject(obj, "Replace Spaces"); - obj.name = obj.name.Replace(" ", "_"); - } - } -}