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