From 920b9966ee9c5e8178ac32a9f5c5828526893580 Mon Sep 17 00:00:00 2001 From: Yamo4490 Date: Tue, 2 Sep 2025 02:43:55 +0900 Subject: [PATCH] =?UTF-8?q?Modify:=20=EB=A7=A4=EC=A7=80=EC=B9=B4=ED=81=B4?= =?UTF-8?q?=EB=A1=9C=EC=8A=A42=20=EB=B2=84=EC=A0=84=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Common/Materials/MC2_Floor.mat.meta | 7 + .../Common/Materials/MC2_Test_Back.mat.meta | 7 + .../Common/Materials/MC2_Test_Front.mat.meta | 7 + .../Common/Materials/MC2_White.mat | 26 +- .../Common/Materials/MC2_White.mat.meta | 7 + .../Common/Model/Materials/Arrow.mat.meta | 7 + .../Common/Model/arrow_b.fbx.meta | 7 + .../Common/Prefabs/Cube.prefab.meta | 7 + .../Common/Prefabs/CubeRoup.prefab.meta | 7 + .../Common/Prefabs/Env.prefab.meta | 7 + .../Common/Prefabs/Plane.prefab.meta | 7 + .../Prefabs/RuntimeBuildDemo.prefab.meta | 7 + .../Prefabs/RuntimeDressUpDemo.prefab.meta | 7 + .../Prefabs/SimpleImputManager.prefab.meta | 7 + .../Common/Prefabs/Stage.prefab.meta | 7 + .../Common/Prefabs/UI_KAGURA.prefab.meta | 7 + .../Prefabs/UI_RuntimeBuild.prefab.meta | 7 + .../Prefabs/UI_RuntimeDressUp.prefab.meta | 7 + .../Common/Prefabs/UI_Wind.prefab.meta | 7 + .../Common/Prefabs/WindDemo.prefab.meta | 7 + .../Common/Prefabs/WindParticle.prefab.meta | 7 + .../MC2_BoneCloth_Ribbon_Demo.json.meta | 7 + .../Common/Scripts/AutoRotate.cs | 23 +- .../Common/Scripts/AutoRotate.cs.meta | 7 + .../Common/Scripts/CameraOrbit.cs | 27 +- .../Common/Scripts/CameraOrbit.cs.meta | 7 + .../Common/Scripts/CreateSingleton.cs.meta | 7 + ...caCloth2UPMImporterShaderGraph.asmdef.meta | 7 + .../ShaderGraph/UnityPackageImporter.cs.meta | 7 + .../Scripts/GameObjectContainer.cs.meta | 7 + .../Common/Scripts/MagicaCloth2Example.asmdef | 25 + .../Scripts/MagicaCloth2Example.asmdef.meta | 14 + .../Common/Scripts/ModelController.cs.meta | 7 + .../Common/Scripts/RuntimeBuildDemo.cs | 14 +- .../Common/Scripts/RuntimeBuildDemo.cs.meta | 7 + .../Common/Scripts/RuntimeDressUpDemo.cs.meta | 7 + .../Common/Scripts/SimpleInput.cs | 196 + .../Common/Scripts/SimpleInput.cs.meta | 18 + .../Common/Scripts/SimpleInputManager.cs | 44 +- .../Common/Scripts/SimpleInputManager.cs.meta | 7 + .../Common/Scripts/SliderText.cs.meta | 7 + .../Common/Scripts/TargetFPS.cs.meta | 7 + .../Common/Scripts/WindDemo.cs.meta | 7 + .../MC2_Common_Lit_Back.shadergraph.meta | 7 + .../MC2_Common_Lit_Front.shadergraph.meta | 7 + .../SD_UnityChan_Skirt_PaintMap.png.meta | 7 + .../CoreRP/RuntimeBuild_CoreRP.unity.meta | 7 + .../CoreRP/RuntimeDressUp_CoreRP.unity.meta | 7 + .../CoreRP/UnityChanKAGURA_CoreRP.unity | 4 +- .../CoreRP/UnityChanKAGURA_CoreRP.unity.meta | 7 + .../DemoScenes/CoreRP/Wind_CoreRP.unity.meta | 7 + .../MC2_SkyandFogSettingsProfile.asset.meta | 7 + .../HDRP/RuntimeBuild_HDRP.unity.meta | 7 + .../HDRP/RuntimeDressUp_HDRP.unity.meta | 7 + .../HDRP/UnityChanKAGURA_HDRP.unity.meta | 7 + .../DemoScenes/HDRP/Wind_HDRP.unity.meta | 7 + .../URP/RuntimeBuild_URP.unity.meta | 7 + .../URP/RuntimeDressUp_URP.unity.meta | 7 + .../URP/UnityChanKAGURA_URP.unity.meta | 7 + .../DemoScenes/URP/Wind_URP.unity.meta | 7 + .../DemoScenes_Unity_6.1_or_Higher.meta | 8 + .../HighDefinition3D.meta | 8 + .../RuntimeBuild_HighDefinition3D.unity | 3 + .../RuntimeBuild_HighDefinition3D.unity.meta | 14 + .../RuntimeDressUp_HighDefinition3D.unity | 3 + ...RuntimeDressUp_HighDefinition3D.unity.meta | 14 + .../UnityChanKAGURA_HighDefinition3D.unity | 3 + ...nityChanKAGURA_HighDefinition3D.unity.meta | 14 + .../Wind_HighDefinition3D.unity | 3 + .../Wind_HighDefinition3D.unity.meta | 14 + .../Universal3D.meta | 8 + .../RuntimeBuild_Universal3D.unity | 3 + .../RuntimeBuild_Universal3D.unity.meta | 14 + .../RuntimeDressUp_Universal3D.unity | 3 + .../RuntimeDressUp_Universal3D.unity.meta | 14 + .../UnityChanKAGURA_Universal3D.unity | 3 + .../UnityChanKAGURA_Universal3D.unity.meta | 14 + .../Universal3D/Wind_Universal3D.unity | 3 + .../Universal3D/Wind_Universal3D.unity.meta | 14 + .../UnityChan/Logo/Dark_Silhouette.png.meta | 7 + .../SD_Kohaku_chanz/Materials/SB_def_mat.mat | 2 +- .../Materials/SB_def_mat.mat.meta | 7 + .../SD_Kohaku_chanz/Materials/SB_nol_mat.mat | 26 +- .../Materials/SB_nol_mat.mat.meta | 7 + .../SD_Kohaku_chanz/Materials/SB_skin_mat.mat | 26 +- .../Materials/SB_skin_mat.mat.meta | 7 + .../SD_Kohaku_chanz/Materials/def_mat.mat | 26 +- .../Materials/def_mat.mat.meta | 7 + .../SD_Kohaku_chanz/Materials/hair_mat.mat | 2 +- .../Materials/hair_mat.mat.meta | 7 + .../SD_Kohaku_chanz/Materials/mouth_mat.mat | 26 +- .../Materials/mouth_mat.mat.meta | 7 + .../SD_Kohaku_chanz/Materials/nol_mat.mat | 2 +- .../Materials/nol_mat.mat.meta | 7 + .../SD_Kohaku_chanz/Materials/skin_mat.mat | 2 +- .../Materials/skin_mat.mat.meta | 7 + .../SD_UnityChan.controller.meta | 7 + .../Textures/body_sum.png.meta | 7 + .../Textures/body_win.png.meta | 7 + .../Textures/misaki_head.png.meta | 7 + .../Textures/utc_all2.png.meta | 7 + .../Textures/yuko_head.png.meta | 7 + .../Utc_sum_humanoid (Body).prefab | 4 +- .../Utc_sum_humanoid (Body).prefab.meta | 8 + .../Utc_sum_humanoid (Hair).prefab | 4 +- .../Utc_sum_humanoid (Hair).prefab.meta | 8 + .../Utc_sum_humanoid (Skeleton).prefab.meta | 8 + .../Utc_sum_humanoid Variant.prefab.meta | 8 + .../SD_Kohaku_chanz/Utc_sum_humanoid.fbx.meta | 61 +- ...nse Terms and Condition_EN_UCL2.0.pdf.meta | 8 + ...s and Condition_Summary_EN_UCL2.0.pdf.meta | 8 + ...03Indication of License_EN_UCL2.0.pdf.meta | 8 + ...nse Terms and Condition_JP_UCL2.0.pdf.meta | 8 + ...s and Condition_Summary_JP_UCL2.0.pdf.meta | 8 + ...03Indication of License_JP_UCL2.0.pdf.meta | 8 + .../License Logo/LUUL_LOGO_rules02.ai.meta | 8 + .../License Logo/LUUL_LOGO_rules02.psd.meta | 8 + .../License Logo/LUUL_logo-guideline.pdf.meta | 8 + .../LUUL_logo-guideline_en.pdf.meta | 8 + .../Others/jpg/Dark_Silhouette.jpg.meta | 8 + .../Others/jpg/Light_Silhouette.jpg.meta | 8 + .../Others/png/Dark_Silhouette.png.meta | 8 + .../Others/png/Light_Frame.png.meta | 8 + .../Others/png/Light_Silhouette.png.meta | 8 + .../Others/svg/Dark_Silhouette.svg.meta | 8 + .../Others/svg/Light_Frame.svg.meta | 8 + .../Others/svg/Light_Silhouette.svg.meta | 8 + .../UnityChan/Unity-Chan License.txt.meta | 8 + .../Animation/RUN00_F.anim.meta | 7 + .../UC01_001_UniteInTheSky -WA-.fbx.meta | 8 + .../Animation/WAIT02.anim.meta | 7 + .../Animation/WAIT04.anim.meta | 7 + .../Animation/WALK00_F.anim.meta | 7 + .../UnityChanKAGURA/Animation/WIN00.anim.meta | 7 + .../UnityChanKAGURA/Materials/Albedo.mat.meta | 7 + .../Materials/Body Back.mat.meta | 8 + .../UnityChanKAGURA/Materials/Body.mat.meta | 7 + .../UnityChanKAGURA/Materials/Eyes.mat.meta | 7 + .../Materials/Eyes_HL.mat.meta | 7 + .../UnityChanKAGURA/Materials/Face.mat.meta | 7 + .../UnityChanKAGURA/Materials/Hair.mat.meta | 7 + .../Materials/HairPony.mat.meta | 7 + .../Materials/Headgear.mat.meta | 7 + .../Materials/LongSleeve Back.mat.meta | 8 + .../Materials/LongSleeve.mat.meta | 7 + .../UnityChanKAGURA/Materials/Skin.mat.meta | 7 + .../Materials/TEX/PNG/Body_Base.png.meta | 7 + .../Materials/TEX/PNG/Body_Emi.png.meta | 7 + .../Materials/TEX/PNG/Body_SGM.png.meta | 7 + .../Materials/TEX/PNG/Body_Shd1.png.meta | 7 + .../Materials/TEX/PNG/Body_Shd2.png.meta | 7 + .../Materials/TEX/PNG/Body_Spc.png.meta | 7 + .../Materials/TEX/PNG/Face_Base.png.meta | 7 + .../Materials/TEX/PNG/Face_Emi.png.meta | 7 + .../Materials/TEX/PNG/Face_LSM.png.meta | 7 + .../Materials/TEX/PNG/Face_Rim.png.meta | 7 + .../Materials/TEX/PNG/Face_SGM.png.meta | 7 + .../Materials/TEX/PNG/Face_Shd1.png.meta | 7 + .../Materials/TEX/PNG/Face_Shd2.png.meta | 7 + .../Materials/TEX/PNG/Hair_SGM.png.meta | 7 + .../Materials/TEX/PNG/Headfgear_Base.png.meta | 7 + .../Materials/TEX/PNG/Skin_Base.png.meta | 7 + .../Materials/TEX/PNG/Skin_Emi.png.meta | 7 + .../Materials/TEX/PNG/Skin_Nrm.png.meta | 7 + .../Materials/TEX/PNG/Skin_Rim.png.meta | 7 + .../Materials/TEX/PNG/Skin_SGM.png.meta | 7 + .../Materials/TEX/PNG/Skin_Spc.png.meta | 7 + .../Materials/TEX/PNG/Skin_SpcCol.png.meta | 7 + .../Materials/face3_main.mat.meta | 7 + .../Materials/headExt.mat.meta | 7 + .../UniteInTheSky.controller.meta | 7 + .../UnityChanKAGURA/UnityCHanKAGURA.fbx.meta | 43 +- .../UnityCHanKAGURA_MC2.prefab | 4 +- .../UnityCHanKAGURA_MC2.prefab.meta | 7 + .../MagicaCloth2/MagicaCloth2.asmdef.meta | 7 + Assets/External/MagicaCloth2/Readme.txt.meta | 7 + .../External/MagicaCloth2/Readme_jpn.txt.meta | 7 + .../MagicaCloth2/Res/Icon/icon-cloth.png.meta | 7 + .../Res/Icon/icon-collider.png.meta | 7 + .../Res/Icon/icon-settings.png.meta | 7 + .../MagicaCloth2/Res/Icon/icon-wind.png.meta | 7 + .../Res/Preset/MC2_Preset_Accessory.json | 4 +- .../Res/Preset/MC2_Preset_Accessory.json.meta | 7 + .../Res/Preset/MC2_Preset_Cape.json | 4 +- .../Res/Preset/MC2_Preset_Cape.json.meta | 7 + .../Res/Preset/MC2_Preset_FrontHair.json | 4 +- .../Res/Preset/MC2_Preset_FrontHair.json.meta | 7 + .../Res/Preset/MC2_Preset_HardSpring.json | 4 +- .../Preset/MC2_Preset_HardSpring.json.meta | 7 + .../Res/Preset/MC2_Preset_LongHair.json | 4 +- .../Res/Preset/MC2_Preset_LongHair.json.meta | 7 + .../Res/Preset/MC2_Preset_MiddleSpring.json | 4 +- .../Preset/MC2_Preset_MiddleSpring.json.meta | 7 + .../Res/Preset/MC2_Preset_ShortHair.json | 4 +- .../Res/Preset/MC2_Preset_ShortHair.json.meta | 7 + .../Res/Preset/MC2_Preset_Skirt.json | 4 +- .../Res/Preset/MC2_Preset_Skirt.json.meta | 7 + .../Res/Preset/MC2_Preset_SoftSkirt.json | 3 + .../Res/Preset/MC2_Preset_SoftSkirt.json.meta | 14 + .../Res/Preset/MC2_Preset_SoftSpring.json | 4 +- .../Preset/MC2_Preset_SoftSpring.json.meta | 7 + .../Res/Preset/MC2_Preset_Tail.json | 4 +- .../Res/Preset/MC2_Preset_Tail.json.meta | 7 + .../Cloth/CheckSliderSerializeData.cs.meta | 7 + .../Scripts/Core/Cloth/ClothBehaviour.cs | 6 + .../Scripts/Core/Cloth/ClothBehaviour.cs.meta | 7 + .../Scripts/Core/Cloth/ClothForceMode.cs.meta | 7 + .../Core/Cloth/ClothInitSerializeData.cs | 211 + .../Core/Cloth/ClothInitSerializeData.cs.meta | 18 + .../Scripts/Core/Cloth/ClothMeshWriteMode.cs | 25 + .../Core/Cloth/ClothMeshWriteMode.cs.meta | 18 + .../Core/Cloth/ClothNormalAxis.cs.meta | 7 + .../Scripts/Core/Cloth/ClothParameters.cs | 5 +- .../Core/Cloth/ClothParameters.cs.meta | 7 + .../Scripts/Core/Cloth/ClothProcess.cs | 857 +++-- .../Scripts/Core/Cloth/ClothProcess.cs.meta | 7 + .../Scripts/Core/Cloth/ClothProcessData.cs | 206 +- .../Core/Cloth/ClothProcessData.cs.meta | 7 + .../Core/Cloth/ClothProcessGeneration.cs | 45 +- .../Core/Cloth/ClothProcessGeneration.cs.meta | 7 + .../Scripts/Core/Cloth/ClothSerializeData.cs | 19 +- .../Core/Cloth/ClothSerializeData.cs.meta | 7 + .../Scripts/Core/Cloth/ClothSerializeData2.cs | 35 +- .../Core/Cloth/ClothSerializeData2.cs.meta | 7 + .../Core/Cloth/ClothSerializeDataFunction.cs | 58 +- .../Cloth/ClothSerializeDataFunction.cs.meta | 7 + .../Scripts/Core/Cloth/ClothUpdateMode.cs | 9 + .../Core/Cloth/ClothUpdateMode.cs.meta | 7 + .../Core/Cloth/Collider/ColliderComponent.cs | 318 +- .../Cloth/Collider/ColliderComponent.cs.meta | 7 + .../Cloth/Collider/ColliderSymmetryMode.cs | 52 + .../Collider/ColliderSymmetryMode.cs.meta | 18 + .../Cloth/Collider/MagicaCapsuleCollider.cs | 20 +- .../Collider/MagicaCapsuleCollider.cs.meta | 7 + .../Collider/MagicaPlaneCollider.cs.meta | 7 + .../Collider/MagicaSphereCollider.cs.meta | 7 + .../Core/Cloth/Constraints/AngleConstraint.cs | 334 +- .../Cloth/Constraints/AngleConstraint.cs.meta | 7 + .../ColliderCollisionConstraint.cs | 1178 +++--- .../ColliderCollisionConstraint.cs.meta | 7 + .../Cloth/Constraints/DistanceConstraint.cs | 187 +- .../Constraints/DistanceConstraint.cs.meta | 7 + .../Cloth/Constraints/InertiaConstraint.cs | 103 +- .../Constraints/InertiaConstraint.cs.meta | 7 + .../Cloth/Constraints/MotionConstraint.cs | 131 +- .../Constraints/MotionConstraint.cs.meta | 7 + .../Constraints/SelfCollisionConstraint.cs | 3385 ++++++++--------- .../SelfCollisionConstraint.cs.meta | 7 + .../Cloth/Constraints/SpringConstraint.cs | 7 - .../Constraints/SpringConstraint.cs.meta | 7 + .../Cloth/Constraints/TetherConstraint.cs | 125 +- .../Constraints/TetherConstraint.cs.meta | 7 + .../Constraints/TriangleBendingConstraint.cs | 621 ++- .../TriangleBendingConstraint.cs.meta | 7 + .../Scripts/Core/Cloth/CullingSettings.cs | 57 +- .../Core/Cloth/CullingSettings.cs.meta | 7 + .../Core/Cloth/CurveSerializeData.cs.meta | 7 + .../Core/Cloth/CustomSkinningSettings.cs | 6 +- .../Core/Cloth/CustomSkinningSettings.cs.meta | 7 + .../Core/Cloth/GizmoSerializeData.cs.meta | 7 + .../Scripts/Core/Cloth/MagicaCloth.cs | 41 +- .../Scripts/Core/Cloth/MagicaCloth.cs.meta | 9 +- .../Scripts/Core/Cloth/MagicaClothAPI.cs | 158 +- .../Scripts/Core/Cloth/MagicaClothAPI.cs.meta | 7 + .../Cloth/MagicaClothAnimationProperty.cs | 130 + .../MagicaClothAnimationProperty.cs.meta | 18 + .../Cloth/NormalAlignmentSettings.cs.meta | 7 + .../Scripts/Core/Cloth/SelectionData.cs | 6 - .../Scripts/Core/Cloth/SelectionData.cs.meta | 7 + .../Scripts/Core/Cloth/Wind/MagicaWindZone.cs | 9 +- .../Core/Cloth/Wind/MagicaWindZone.cs.meta | 7 + .../Core/Cloth/Wind/WindParams.cs.meta | 7 + .../Core/Cloth/Wind/WindSettings.cs.meta | 7 + .../Scripts/Core/Define/ResultDefine.cs | 46 + .../Scripts/Core/Define/ResultDefine.cs.meta | 7 + .../Scripts/Core/Define/SystemDefine.cs | 41 +- .../Scripts/Core/Define/SystemDefine.cs.meta | 7 + .../Scripts/Core/Interface/ICount.cs.meta | 7 + .../Core/Interface/IDataValidate.cs.meta | 7 + .../Scripts/Core/Interface/ITransform.cs.meta | 7 + .../Scripts/Core/Interface/IValid.cs.meta | 7 + .../Core/Manager/Cloth/ClothManager.cs | 154 +- .../Core/Manager/Cloth/ClothManager.cs.meta | 7 + .../Core/Manager/Cloth/PreBuildManager.cs | 301 ++ .../Manager/Cloth/PreBuildManager.cs.meta | 18 + .../Scripts/Core/Manager/IManager.cs.meta | 7 + .../Scripts/Core/Manager/MagicaManager.cs | 46 +- .../Core/Manager/MagicaManager.cs.meta | 7 + .../Scripts/Core/Manager/MagicaManagerAPI.cs | 71 +- .../Core/Manager/MagicaManagerAPI.cs.meta | 7 + .../Scripts/Core/Manager/MagicaSettings.cs | 54 +- .../Core/Manager/MagicaSettings.cs.meta | 9 +- .../Scripts/Core/Manager/Render/RenderData.cs | 407 +- .../Core/Manager/Render/RenderData.cs.meta | 7 + .../Core/Manager/Render/RenderManager.cs | 218 +- .../Core/Manager/Render/RenderManager.cs.meta | 7 + .../Core/Manager/Render/RenderSetupData.cs | 335 +- .../Manager/Render/RenderSetupData.cs.meta | 7 + .../Render/RenderSetupDataSerialization.cs | 202 + .../RenderSetupDataSerialization.cs.meta | 18 + .../Render/RenderSetupSerializeData.cs | 356 ++ .../Render/RenderSetupSerializeData.cs.meta | 18 + .../Manager/Simulation/ColliderManager.cs | 1192 +++--- .../Simulation/ColliderManager.cs.meta | 7 + .../Manager/Simulation/SimulationManager.cs | 2589 +++++-------- .../Simulation/SimulationManager.cs.meta | 7 + .../Simulation/SimulationManagerNormal.cs | 1769 +++++++++ .../SimulationManagerNormal.cs.meta | 18 + .../Simulation/SimulationManagerSplit.cs | 2335 ++++++++++++ .../Simulation/SimulationManagerSplit.cs.meta | 18 + .../Core/Manager/Simulation/TimeManager.cs | 4 +- .../Manager/Simulation/TimeManager.cs.meta | 7 + .../Manager/Simulation/WindManager.cs.meta | 7 + .../Scripts/Core/Manager/Team/TeamManager.cs | 2769 +++++++++----- .../Core/Manager/Team/TeamManager.cs.meta | 7 + .../Scripts/Core/Manager/Team/TeamWindData.cs | 6 + .../Core/Manager/Team/TeamWindData.cs.meta | 7 + .../Manager/TransformManager/TransformData.cs | 31 +- .../TransformManager/TransformData.cs.meta | 7 + .../TransformDataSerialization.cs | 117 + .../TransformDataSerialization.cs.meta | 18 + .../TransformManager/TransformManager.cs | 417 +- .../TransformManager/TransformManager.cs.meta | 7 + .../TransformManager/TransformRecord.cs | 20 +- .../TransformManager/TransformRecord.cs.meta | 7 + .../TransformRecordSerializeData.cs | 82 + .../TransformRecordSerializeData.cs.meta | 18 + .../Manager/VirtualMesh/VirtualMeshManager.cs | 1902 ++++----- .../VirtualMesh/VirtualMeshManager.cs.meta | 7 + .../MagicaCloth2/Scripts/Core/PreBuild.meta | 8 + .../Core/PreBuild/PreBuildScriptableObject.cs | 64 + .../PreBuild/PreBuildScriptableObject.cs.meta | 18 + .../Core/PreBuild/PreBuildSerializeData.cs | 101 + .../PreBuild/PreBuildSerializeData.cs.meta | 18 + .../Core/PreBuild/SharePreBuildData.cs | 69 + .../Core/PreBuild/SharePreBuildData.cs.meta | 18 + .../Core/PreBuild/UniquePreBuildData.cs | 49 + .../Core/PreBuild/UniquePreBuildData.cs.meta | 18 + .../Core/Reduction/ReductionSettings.cs.meta | 7 + .../Core/Reduction/ReductionWorkData.cs.meta | 7 + .../Core/Reduction/SameDistanceReduction.cs | 175 +- .../Reduction/SameDistanceReduction.cs.meta | 7 + .../Reduction/ShapeDistanceReduction.cs.meta | 7 + .../Reduction/SimpleDistanceReduction.cs.meta | 7 + .../Core/Reduction/StepReductionBase.cs | 30 +- .../Core/Reduction/StepReductionBase.cs.meta | 7 + .../Core/Settings/ClothDebugSettings.cs | 18 +- .../Core/Settings/ClothDebugSettings.cs.meta | 7 + .../Settings/VirtualMeshDebugSettings.cs.meta | 7 + .../Scripts/Core/Utility/Data/DataUtility.cs | 82 +- .../Core/Utility/Data/DataUtility.cs.meta | 7 + .../Utility/Data/MultiDataBuilder.cs.meta | 7 + .../Scripts/Core/Utility/Grid/GridMap.cs | 2 +- .../Scripts/Core/Utility/Grid/GridMap.cs.meta | 7 + .../Core/Utility/Jobs/InterlockUtility.cs | 376 +- .../Utility/Jobs/InterlockUtility.cs.meta | 7 + .../Core/Utility/Jobs/JobUtility.cs.meta | 7 + .../Scripts/Core/Utility/Math/AABB.cs.meta | 7 + .../Scripts/Core/Utility/Math/IntAABB.cs.meta | 7 + .../Core/Utility/Math/MathExtensions.cs | 8 +- .../Core/Utility/Math/MathExtensions.cs.meta | 7 + .../Scripts/Core/Utility/Math/MathUtility.cs | 253 +- .../Core/Utility/Math/MathUtility.cs.meta | 7 + .../Core/Utility/Math/MinimumData.cs.meta | 7 + .../Core/Utility/Mesh/MeshUtility.cs.meta | 7 + .../Scripts/Core/Utility/Misc/Develop.cs.meta | 7 + .../Utility/Misc/StaticStringBuilder.cs.meta | 7 + .../NativeCollection/DataChunk.cs.meta | 7 + .../NativeCollection/ExBitFlag16.cs.meta | 7 + .../NativeCollection/ExBitFlag8.cs.meta | 7 + .../ExCostSortedList1.cs.meta | 7 + .../ExCostSortedList4.cs.meta | 7 + .../Utility/NativeCollection/ExNativeArray.cs | 23 + .../NativeCollection/ExNativeArray.cs.meta | 7 + .../NativeCollection/ExProcessingList.cs.meta | 7 + .../NativeCollection/ExSimpleNativeArray.cs | 91 +- .../ExSimpleNativeArray.cs.meta | 7 + .../ExTransformAccessArray.cs.meta | 7 + .../FixedList128BytesExtensions.cs | 16 +- .../FixedList128BytesExtensions.cs.meta | 7 + .../FixedList32BytesExtensions.cs | 17 +- .../FixedList32BytesExtensions.cs.meta | 7 + .../FixedList4096BytesExtensions.cs | 16 +- .../FixedList4096BytesExtensions.cs.meta | 7 + .../FixedList512BytesExtensions.cs | 16 +- .../FixedList512BytesExtensions.cs.meta | 7 + .../FixedList64BytesExtensions.cs | 16 +- .../FixedList64BytesExtensions.cs.meta | 7 + .../NativeCollection/NativeArrayExtensions.cs | 50 +- .../NativeArrayExtensions.cs.meta | 7 + .../NativeMultiHashMapExtensions.cs | 147 +- .../NativeMultiHashMapExtensions.cs.meta | 7 + .../NativeParallelHashMapExtensions.cs | 30 + .../NativeParallelHashMapExtensions.cs.meta | 18 + .../NativeReferenceExtensions.cs | 2 +- .../NativeReferenceExtensions.cs.meta | 7 + .../Core/Utility/ResultCode/Exception.cs.meta | 7 + .../Core/Utility/ResultCode/ResultCode.cs | 14 +- .../Utility/ResultCode/ResultCode.cs.meta | 7 + .../Scripts/Core/Utility/Time/TimeSpan.cs | 21 +- .../Core/Utility/Time/TimeSpan.cs.meta | 7 + .../Core/Utility/Time/UnityTimeSpan.cs.meta | 7 + .../Function/VirtualMeshInputOutput.cs | 134 +- .../Function/VirtualMeshInputOutput.cs.meta | 7 + .../Function/VirtualMeshMapping.cs | 9 +- .../Function/VirtualMeshMapping.cs.meta | 7 + .../Function/VirtualMeshOptimization.cs | 4 +- .../Function/VirtualMeshOptimization.cs.meta | 7 + .../VirtualMesh/Function/VirtualMeshProxy.cs | 413 +- .../Function/VirtualMeshProxy.cs.meta | 7 + .../Function/VirtualMeshReduction.cs | 6 +- .../Function/VirtualMeshReduction.cs.meta | 7 + .../Function/VirtualMeshSerialization.cs | 291 ++ .../Function/VirtualMeshSerialization.cs.meta | 18 + .../VirtualMesh/Function/VirtualMeshWork.cs | 2 +- .../Function/VirtualMeshWork.cs.meta | 7 + .../Core/VirtualMesh/VertexAttribute.cs.meta | 7 + .../Scripts/Core/VirtualMesh/VirtualMesh.cs | 76 +- .../Core/VirtualMesh/VirtualMesh.cs.meta | 7 + .../VirtualMesh/VirtualMeshBoneWeight.cs.meta | 7 + .../Core/VirtualMesh/VirtualMeshContainer.cs | 60 + .../VirtualMesh/VirtualMeshContainer.cs.meta | 18 + .../VirtualMesh/VirtualMeshPrimitive.cs.meta | 7 + .../VirtualMesh/VirtualMeshRaycastHit.cs.meta | 7 + .../VirtualMesh/VirtualMeshTransform.cs.meta | 7 + .../Cloth/ClothAssetPostprocessor.cs.meta | 7 + .../Editor/Cloth/ClothEditorManager.cs | 275 +- .../Editor/Cloth/ClothEditorManager.cs.meta | 7 + .../Editor/Cloth/ClothEditorUtility.cs | 60 +- .../Editor/Cloth/ClothEditorUtility.cs.meta | 7 + .../Cloth/ClothInspectorUtility.cs.meta | 7 + .../Scripts/Editor/Cloth/ClothPainter.cs | 32 +- .../Scripts/Editor/Cloth/ClothPainter.cs.meta | 7 + .../Editor/Cloth/ClothPresetUtility.cs.meta | 7 + .../Cloth/MagicaCapsuleColliderEditor.cs | 50 +- .../Cloth/MagicaCapsuleColliderEditor.cs.meta | 7 + .../Scripts/Editor/Cloth/MagicaClothEditor.cs | 226 +- .../Editor/Cloth/MagicaClothEditor.cs.meta | 7 + .../Scripts/Editor/Cloth/MagicaEditorBase.cs | 40 + .../Editor/Cloth/MagicaEditorBase.cs.meta | 18 + .../Editor/Cloth/MagicaPlaneColliderEditor.cs | 13 +- .../Cloth/MagicaPlaneColliderEditor.cs.meta | 7 + .../Editor/Cloth/MagicaSettingsEditor.cs | 5 +- .../Editor/Cloth/MagicaSettingsEditor.cs.meta | 7 + .../Cloth/MagicaSphereColliderEditor.cs | 34 +- .../Cloth/MagicaSphereColliderEditor.cs.meta | 7 + .../Editor/Cloth/MagicaWindZoneEditor.cs | 2 +- .../Editor/Cloth/MagicaWindZoneEditor.cs.meta | 7 + .../Editor/Cloth/VirtualMeshEditorUtility.cs | 42 +- .../Cloth/VirtualMeshEditorUtility.cs.meta | 7 + .../Editor/EditorExtension/AboutMenu.cs | 2 +- .../Editor/EditorExtension/AboutMenu.cs.meta | 7 + .../CheckSliderSerializeDataDrawer.cs.meta | 7 + .../CurveSerializeDataDrawer.cs.meta | 7 + .../DrawIconInHierarchy.cs.meta | 7 + .../Editor/EditorExtension/MenuItemScript.cs | 40 +- .../EditorExtension/MenuItemScript.cs.meta | 7 + .../SharePreBuildDataDrawer.cs | 76 + .../SharePreBuildDataDrawer.cs.meta | 18 + .../Scripts/Editor/Gizmos/GizmoUtility.cs | 183 +- .../Editor/Gizmos/GizmoUtility.cs.meta | 7 + .../MagicaCapsuleColliderGizmoDrawer.cs.meta | 7 + .../Gizmos/MagicaClothGizmoDrawer.cs.meta | 7 + .../MagicaPlaneColliderGizmoDrawer.cs.meta | 7 + .../MagicaSphereColliderGizmoDrawer.cs.meta | 7 + .../Gizmos/MagicaWindZoneGizmoDrawer.cs.meta | 7 + .../Editor/MagicaCloth2.Editor.asmdef.meta | 7 + .../MagicaCloth2/Scripts/Editor/PreBuild.meta | 8 + .../Editor/PreBuild/PreBuildDataCreation.cs | 514 +++ .../PreBuild/PreBuildDataCreation.cs.meta | 18 + .../MagicaCloth2UPMImporterBurst.asmdef.meta | 7 + .../Burst/UnityPackageImporter.cs.meta | 7 + ...caCloth2UPMImporterCollections.asmdef.meta | 7 + .../Collections/UnityPackageImporter.cs.meta | 7 + 474 files changed, 21559 insertions(+), 9828 deletions(-) create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeBuild_HighDefinition3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeBuild_HighDefinition3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeDressUp_HighDefinition3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeDressUp_HighDefinition3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/UnityChanKAGURA_HighDefinition3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/UnityChanKAGURA_HighDefinition3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/Wind_HighDefinition3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/Wind_HighDefinition3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeBuild_Universal3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeBuild_Universal3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeDressUp_Universal3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeDressUp_Universal3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/UnityChanKAGURA_Universal3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/UnityChanKAGURA_Universal3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/Wind_Universal3D.unity create mode 100644 Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/Wind_Universal3D.unity.meta create mode 100644 Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSkirt.json create mode 100644 Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSkirt.json.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothMeshWriteMode.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothMeshWriteMode.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderSymmetryMode.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderSymmetryMode.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAnimationProperty.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAnimationProperty.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/PreBuildManager.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/PreBuildManager.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupDataSerialization.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupDataSerialization.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupSerializeData.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupSerializeData.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerNormal.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerNormal.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/PreBuild.meta create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs create mode 100644 Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs.meta diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Floor.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Floor.mat.meta index fda7b491..e6c78ccf 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Floor.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Floor.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Floor.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Test_Back.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Test_Back.mat.meta index 4c66d558..3eca78b1 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Test_Back.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Test_Back.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Test_Back.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Test_Front.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Test_Front.mat.meta index fde3165e..b06b8c8e 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Test_Front.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Test_Front.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_Test_Front.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_White.mat b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_White.mat index 75309715..65b21dcd 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_White.mat +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_White.mat @@ -1,18 +1,5 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: ---- !u!114 &-39192238385914524 -MonoBehaviour: - m_ObjectHideFlags: 11 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} - m_Name: - m_EditorClassIdentifier: - version: 10 --- !u!21 &2100000 Material: serializedVersion: 8 @@ -118,6 +105,19 @@ Material: - _Tiling: {r: 1, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] m_AllowLocking: 1 +--- !u!114 &3313520665792390858 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 10 --- !u!114 &5537520944958903688 MonoBehaviour: m_ObjectHideFlags: 11 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_White.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_White.mat.meta index 02914d40..8a53ceee 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_White.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_White.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Materials/MC2_White.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Model/Materials/Arrow.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Model/Materials/Arrow.mat.meta index ad27c0a4..8673df22 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Model/Materials/Arrow.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Model/Materials/Arrow.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Model/Materials/Arrow.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Model/arrow_b.fbx.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Model/arrow_b.fbx.meta index e459460c..375c71e4 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Model/arrow_b.fbx.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Model/arrow_b.fbx.meta @@ -95,3 +95,10 @@ ModelImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Model/arrow_b.fbx + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Cube.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Cube.prefab.meta index f1d57d96..f07ac579 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Cube.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Cube.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Cube.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/CubeRoup.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/CubeRoup.prefab.meta index 4edd2ca4..f3f30c31 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/CubeRoup.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/CubeRoup.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/CubeRoup.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Env.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Env.prefab.meta index 5aeb3b84..3250d247 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Env.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Env.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Env.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Plane.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Plane.prefab.meta index 999f1377..9eb703b9 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Plane.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Plane.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Plane.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/RuntimeBuildDemo.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/RuntimeBuildDemo.prefab.meta index 3c8b2c7a..650b1526 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/RuntimeBuildDemo.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/RuntimeBuildDemo.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/RuntimeBuildDemo.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/RuntimeDressUpDemo.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/RuntimeDressUpDemo.prefab.meta index a3d21a79..13f1b0d1 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/RuntimeDressUpDemo.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/RuntimeDressUpDemo.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/RuntimeDressUpDemo.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/SimpleImputManager.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/SimpleImputManager.prefab.meta index 442d2814..02e3b3fd 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/SimpleImputManager.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/SimpleImputManager.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/SimpleImputManager.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Stage.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Stage.prefab.meta index e0caffd3..b4516368 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Stage.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Stage.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/Stage.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_KAGURA.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_KAGURA.prefab.meta index f2130bdc..08827b35 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_KAGURA.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_KAGURA.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_KAGURA.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_RuntimeBuild.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_RuntimeBuild.prefab.meta index 2ad5314b..de754a7c 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_RuntimeBuild.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_RuntimeBuild.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_RuntimeBuild.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_RuntimeDressUp.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_RuntimeDressUp.prefab.meta index 028fcda0..861edc0c 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_RuntimeDressUp.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_RuntimeDressUp.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_RuntimeDressUp.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_Wind.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_Wind.prefab.meta index bca53a86..d30185ea 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_Wind.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_Wind.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/UI_Wind.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/WindDemo.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/WindDemo.prefab.meta index 24d6423d..d91442ed 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/WindDemo.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/WindDemo.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/WindDemo.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/WindParticle.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/WindParticle.prefab.meta index b0656b99..eeaa38c2 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/WindParticle.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/WindParticle.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Prefabs/WindParticle.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Resources/MC2_BoneCloth_Ribbon_Demo.json.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Resources/MC2_BoneCloth_Ribbon_Demo.json.meta index 04ed02d8..c065a153 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Resources/MC2_BoneCloth_Ribbon_Demo.json.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Resources/MC2_BoneCloth_Ribbon_Demo.json.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Resources/MC2_BoneCloth_Ribbon_Demo.json + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/AutoRotate.cs b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/AutoRotate.cs index 0c7539f8..48e2d326 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/AutoRotate.cs +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/AutoRotate.cs @@ -9,6 +9,13 @@ namespace MagicaCloth2 { public Vector3 eulers = new Vector3(0, 90, 0); public Space space = Space.World; + public enum UpdateMode + { + Update, + FixedUpdate, + } + [SerializeField] + private UpdateMode updateMode = UpdateMode.Update; [SerializeField] [Range(0.1f, 5.0f)] @@ -19,11 +26,23 @@ namespace MagicaCloth2 private float time = 0; + private void FixedUpdate() + { + if (updateMode == UpdateMode.FixedUpdate) + UpdatePosition(Time.fixedDeltaTime); + } + void Update() + { + if (updateMode == UpdateMode.Update) + UpdatePosition(Time.deltaTime); + } + + void UpdatePosition(float dtime) { if (useSin) { - time += Time.deltaTime; + time += dtime; float ang = (time % interval) / interval * Mathf.PI * 2.0f; var t = Mathf.Sin(ang); if (space == Space.World) @@ -33,7 +52,7 @@ namespace MagicaCloth2 } else { - transform.Rotate(eulers * Time.deltaTime, space); + transform.Rotate(eulers * dtime, space); } } } diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/AutoRotate.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/AutoRotate.cs.meta index 25e7cb35..97968fcd 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/AutoRotate.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/AutoRotate.cs.meta @@ -10,3 +10,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/AutoRotate.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CameraOrbit.cs b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CameraOrbit.cs index 0966cf7c..512d46ff 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CameraOrbit.cs +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CameraOrbit.cs @@ -124,10 +124,7 @@ namespace MagicaCloth2 return; // カメラターゲットポジション - if (cameraTarget) - { - cameraTargetPos = cameraTarget.position; - } + cameraTargetPos = cameraTarget ? cameraTarget.position : transform.position; // 補間 cameraDist = Mathf.SmoothDamp(cameraDist, setCameraDist, ref cameraDistVelocity, cameraDistHokanTime); @@ -147,13 +144,13 @@ namespace MagicaCloth2 Vector3 pos = q * v; // ターゲットポジション - Vector3 tarpos = cameraTargetPos + cameraTargetOffset; + Vector3 tarpos = cameraTargetPos + transform.TransformVector(cameraTargetOffset); Vector3 fixpos = tarpos + pos; - cameraTransform.localPosition = fixpos; + cameraTransform.position = fixpos; // 回転確定 Vector3 relativePos = tarpos - cameraTransform.position; - Quaternion rot = Quaternion.LookRotation(relativePos); + Quaternion rot = Quaternion.LookRotation(relativePos, transform.up); cameraTransform.rotation = rot; } @@ -182,8 +179,8 @@ namespace MagicaCloth2 } else if (moveMode == MoveMode.Free) { - Vector3 offset = cameraTransform.up * -speed.y * moveSpeed; - offset += cameraTransform.right * -speed.x * moveSpeed; + Vector3 offset = transform.InverseTransformDirection(cameraTransform.up) * -speed.y * moveSpeed; + offset += transform.InverseTransformDirection(cameraTransform.right) * -speed.x * moveSpeed; cameraTargetOffset += offset; } @@ -207,7 +204,7 @@ namespace MagicaCloth2 /// private void OnTouchMove(int fid, Vector2 screenPos, Vector2 screenVelocity, Vector2 cmVelocity) { - screenVelocity *= Time.deltaTime * 60.0f; + screenVelocity *= SpeedAdjustment(); if (fid == 2) { @@ -225,6 +222,8 @@ namespace MagicaCloth2 private void OnDoubleTouchMove(int fid, Vector2 screenPos, Vector2 screenVelocity, Vector2 cmVelocity) { + screenVelocity *= SpeedAdjustment(); + if (SimpleInputManager.Instance.GetTouchCount() >= 3) updateOffset(screenVelocity); } @@ -236,9 +235,15 @@ namespace MagicaCloth2 /// private void OnTouchPinch(float speedscr, float speedcm) { - //if (Mathf.Abs(speedcm) > 1.0f) + speedcm *= SpeedAdjustment(); + if (SimpleInputManager.Instance.GetTouchCount() < 3) updateZoom(speedcm); } + + private float SpeedAdjustment() + { + return Time.deltaTime * 60.0f; + } } } diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CameraOrbit.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CameraOrbit.cs.meta index 469a81c6..99a01d8d 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CameraOrbit.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CameraOrbit.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CameraOrbit.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CreateSingleton.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CreateSingleton.cs.meta index 2ab1f794..4b4ff663 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CreateSingleton.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CreateSingleton.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CreateSingleton.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/Editor/ShaderGraph/MagicaCloth2UPMImporterShaderGraph.asmdef.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/Editor/ShaderGraph/MagicaCloth2UPMImporterShaderGraph.asmdef.meta index b7c84cab..fe02f634 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/Editor/ShaderGraph/MagicaCloth2UPMImporterShaderGraph.asmdef.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/Editor/ShaderGraph/MagicaCloth2UPMImporterShaderGraph.asmdef.meta @@ -5,3 +5,10 @@ AssemblyDefinitionImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/Editor/ShaderGraph/MagicaCloth2UPMImporterShaderGraph.asmdef + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/Editor/ShaderGraph/UnityPackageImporter.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/Editor/ShaderGraph/UnityPackageImporter.cs.meta index 83d2a669..6d49f765 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/Editor/ShaderGraph/UnityPackageImporter.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/Editor/ShaderGraph/UnityPackageImporter.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/Editor/ShaderGraph/UnityPackageImporter.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/GameObjectContainer.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/GameObjectContainer.cs.meta index 6425dc71..ba981ef0 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/GameObjectContainer.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/GameObjectContainer.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/GameObjectContainer.cs + uploadId: 756593 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 00000000..f0713e7a --- /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 00000000..cea1bdba --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 5bc0ea054e216f5498d1a84885db7ab1 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/ModelController.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/ModelController.cs.meta index 9a9f86f0..2027cc8d 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/ModelController.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/ModelController.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/ModelController.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeBuildDemo.cs b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeBuildDemo.cs index 1ed4f217..418d758c 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeBuildDemo.cs +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeBuildDemo.cs @@ -233,6 +233,7 @@ namespace MagicaCloth2 sdata.colliderCollisionConstraint.mode = ColliderCollisionConstraint.Mode.Point; // setup collider + // UpperLeg L var lobj = new GameObject("CapsuleCollider_L"); lobj.transform.SetParent(gameObjectContainer.GetGameObject("Character1_LeftUpLeg").transform); lobj.transform.localPosition = new Vector3(0.0049f, 0.0f, -0.0832f); @@ -240,17 +241,10 @@ namespace MagicaCloth2 var colliderL = lobj.AddComponent(); colliderL.direction = MagicaCapsuleCollider.Direction.Z; colliderL.SetSize(0.082f, 0.094f, 0.3f); - - var robj = new GameObject("CapsuleCollider_R"); - robj.transform.SetParent(gameObjectContainer.GetGameObject("Character1_RightUpLeg").transform); - robj.transform.localPosition = new Vector3(-0.0049f, 0.0f, -0.0832f); - robj.transform.localEulerAngles = new Vector3(0.23f, -16.376f, -0.028f); - var colliderR = robj.AddComponent(); - colliderR.direction = MagicaCapsuleCollider.Direction.Z; - colliderR.SetSize(0.082f, 0.094f, 0.3f); - + // UpperLeg R (Symmetry) + colliderL.symmetryMode = ColliderSymmetryMode.AutomaticHumanBody; + colliderL.UpdateParameters(); // Required when changing parameters. sdata.colliderCollisionConstraint.colliderList.Add(colliderL); - sdata.colliderCollisionConstraint.colliderList.Add(colliderR); // start build cloth.BuildAndRun(); diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeBuildDemo.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeBuildDemo.cs.meta index e13eec36..37b54f53 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeBuildDemo.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeBuildDemo.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeBuildDemo.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeDressUpDemo.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeDressUpDemo.cs.meta index b83073fe..3b8111d3 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeDressUpDemo.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeDressUpDemo.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeDressUpDemo.cs + uploadId: 756593 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 00000000..ab3496ce --- /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/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs.meta new file mode 100644 index 00000000..45af9716 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: ab72fcfec8965ae4181307a06400b57b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInputManager.cs b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInputManager.cs index 0a3b4405..bf5a66c2 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInputManager.cs +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInputManager.cs @@ -105,6 +105,8 @@ namespace MagicaCloth2 //========================================================================================= protected override void InitSingleton() { + SimpleInput.Init(); + // スクリーン情報 CalcScreenDpi(); @@ -188,7 +190,7 @@ namespace MagicaCloth2 public int GetTouchCount() { - return Input.touchCount; + return SimpleInput.touchCount; } public bool IsUI() @@ -199,7 +201,7 @@ namespace MagicaCloth2 if (mobilePlatform) { // モバイル用タッチ入力 - return EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId); + return EventSystem.current.IsPointerOverGameObject(SimpleInput.GetTouch(0).fingerId); } else { @@ -214,7 +216,7 @@ namespace MagicaCloth2 /// private void UpdateMobile() { - int count = Input.touchCount; + int count = SimpleInput.touchCount; if (count == 0) { @@ -223,7 +225,7 @@ namespace MagicaCloth2 // バックボタン if (Application.platform == RuntimePlatform.Android) { - if (Input.GetKey(KeyCode.Escape) && lastTime + 0.2f < Time.time) + if (SimpleInput.GetKey(KeyCode.Escape) && lastTime + 0.2f < Time.time) { lastTime = Time.time; if (OnBackButton != null) @@ -239,7 +241,7 @@ namespace MagicaCloth2 // メイン for (int i = 0; i < count; i++) { - Touch touch = Input.GetTouch(i); + Touch touch = SimpleInput.GetTouch(i); int fid = touch.fingerId; // フィンガーIDが0と1以外は無視する @@ -289,7 +291,7 @@ namespace MagicaCloth2 int setcnt = 0; for (int j = 0; j < count; j++) { - Touch t = Input.GetTouch(j); + Touch t = SimpleInput.GetTouch(j); if (mainFingerId == t.fingerId) { t1pos = t.position; @@ -497,7 +499,7 @@ namespace MagicaCloth2 private void UpdateMouse() { // BackSpace を Android 端末のバックボタンに割り当てる - if (Input.GetKeyDown(KeyCode.Backspace)) + if (SimpleInput.GetKeyDown(KeyCode.Backspace)) { if (OnBackButton != null) OnBackButton(); @@ -507,7 +509,7 @@ namespace MagicaCloth2 for (int i = 0; i < 3; i++) { // マウスボタンダウン - if (Input.GetMouseButtonDown(i)) + if (SimpleInput.GetMouseButtonDown(i)) { if (IsUI()) continue; @@ -519,46 +521,46 @@ namespace MagicaCloth2 mouseDown[i] = true; // 入力位置を記録 - downPos[i] = Input.mousePosition; - mouseOldMovePos[i] = Input.mousePosition; + downPos[i] = SimpleInput.mousePosition; + mouseOldMovePos[i] = SimpleInput.mousePosition; if (i == 0) - flickDownPos[i] = Input.mousePosition; + flickDownPos[i] = SimpleInput.mousePosition; // タッチダウンイベント発行 if (OnTouchDown != null) - OnTouchDown(i, Input.mousePosition); + OnTouchDown(i, SimpleInput.mousePosition); } // マウスボタンアップ - if (Input.GetMouseButtonUp(i) && mouseDown[i]) + if (SimpleInput.GetMouseButtonUp(i) && mouseDown[i]) { mouseDown[i] = false; // フリック判定 if (i == 0) { - CheckFlic(i, mouseOldMovePos[i], Input.mousePosition, flickDownPos[i], flickDownTime[i]); + CheckFlic(i, mouseOldMovePos[i], SimpleInput.mousePosition, flickDownPos[i], flickDownTime[i]); } mouseOldMovePos[i] = Vector2.zero; // タッチアップイベント if (OnTouchUp != null) - OnTouchUp(i, Input.mousePosition); + OnTouchUp(i, SimpleInput.mousePosition); // タップ判定 - float distcm = Vector2.Distance(downPos[0], Input.mousePosition) / screenDpc; + float distcm = Vector2.Distance(downPos[0], SimpleInput.mousePosition) / screenDpc; if (distcm <= tapRadiusCm) { if (OnTouchTap != null) - OnTouchTap(i, Input.mousePosition); + OnTouchTap(i, SimpleInput.mousePosition); } } // 移動 if (mouseDown[i]) { - Vector2 spos = new Vector2(Input.mousePosition.x, Input.mousePosition.y); + Vector2 spos = new Vector2(SimpleInput.mousePosition.x, SimpleInput.mousePosition.y); Vector2 delta = spos - mouseOldMovePos[i]; if (spos != mouseOldMovePos[i]) @@ -569,10 +571,10 @@ namespace MagicaCloth2 // 移動通知(現在スクリーン座標、速度(スクリーン比率/s)、速度(cm/s)) if (OnTouchMove != null) - OnTouchMove(i, Input.mousePosition, CalcScreenRatioVector(delta) / Time.deltaTime, speedcm); + OnTouchMove(i, SimpleInput.mousePosition, CalcScreenRatioVector(delta) / Time.deltaTime, speedcm); } - mouseOldMovePos[i] = Input.mousePosition; + mouseOldMovePos[i] = SimpleInput.mousePosition; // フリックダウン位置更新 flickDownPos[i] = (flickDownPos[i] + spos) * 0.5f; @@ -582,7 +584,7 @@ namespace MagicaCloth2 } // ピンチイン/アウト - float w = Input.GetAxis("Mouse ScrollWheel"); + float w = SimpleInput.GetMouseScrollWheel(); if (Mathf.Abs(w) > 0.01f) { // モバイル入力とスケール感を合わせるために係数を掛ける diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInputManager.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInputManager.cs.meta index caaf8f95..27ceaaed 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInputManager.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInputManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInputManager.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SliderText.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SliderText.cs.meta index 5b845c36..50f57feb 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SliderText.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SliderText.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SliderText.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/TargetFPS.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/TargetFPS.cs.meta index 1a6c0764..f8b8c699 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/TargetFPS.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/TargetFPS.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/TargetFPS.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/WindDemo.cs.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/WindDemo.cs.meta index 4892d391..8bfef270 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/WindDemo.cs.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/WindDemo.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Scripts/WindDemo.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Shaders/MC2_Common_Lit_Back.shadergraph.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Shaders/MC2_Common_Lit_Back.shadergraph.meta index b9c5388b..344ba09e 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Shaders/MC2_Common_Lit_Back.shadergraph.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Shaders/MC2_Common_Lit_Back.shadergraph.meta @@ -8,3 +8,10 @@ ScriptedImporter: assetBundleName: assetBundleVariant: script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Shaders/MC2_Common_Lit_Back.shadergraph + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Shaders/MC2_Common_Lit_Front.shadergraph.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Shaders/MC2_Common_Lit_Front.shadergraph.meta index ff256694..15a92363 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Shaders/MC2_Common_Lit_Front.shadergraph.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Shaders/MC2_Common_Lit_Front.shadergraph.meta @@ -8,3 +8,10 @@ ScriptedImporter: assetBundleName: assetBundleVariant: script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Shaders/MC2_Common_Lit_Front.shadergraph + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Textures/SD_UnityChan_Skirt_PaintMap.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Textures/SD_UnityChan_Skirt_PaintMap.png.meta index 9664902f..008b57bd 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Textures/SD_UnityChan_Skirt_PaintMap.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Textures/SD_UnityChan_Skirt_PaintMap.png.meta @@ -133,3 +133,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/Common/Textures/SD_UnityChan_Skirt_PaintMap.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/RuntimeBuild_CoreRP.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/RuntimeBuild_CoreRP.unity.meta index 08041a60..18e2feb8 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/RuntimeBuild_CoreRP.unity.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/RuntimeBuild_CoreRP.unity.meta @@ -5,3 +5,10 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/RuntimeBuild_CoreRP.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/RuntimeDressUp_CoreRP.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/RuntimeDressUp_CoreRP.unity.meta index 9c7cb142..5f4d8e54 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/RuntimeDressUp_CoreRP.unity.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/RuntimeDressUp_CoreRP.unity.meta @@ -5,3 +5,10 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/RuntimeDressUp_CoreRP.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/UnityChanKAGURA_CoreRP.unity b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/UnityChanKAGURA_CoreRP.unity index 45a9369b..78a5aa64 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/UnityChanKAGURA_CoreRP.unity +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/UnityChanKAGURA_CoreRP.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0a30028efec38943b8b0a0a3e6c27faf3b27c037688c241e17d2a10cfc19731 -size 23432 +oid sha256:6fe3dc5720a8c5fad181a0d26496c40a37ac6d36d4adaa54682a75eaf87a33c9 +size 22305 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/UnityChanKAGURA_CoreRP.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/UnityChanKAGURA_CoreRP.unity.meta index 8d3ddf15..47ff0707 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/UnityChanKAGURA_CoreRP.unity.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/UnityChanKAGURA_CoreRP.unity.meta @@ -5,3 +5,10 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/UnityChanKAGURA_CoreRP.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/Wind_CoreRP.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/Wind_CoreRP.unity.meta index 1bb3c959..584dc04f 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/Wind_CoreRP.unity.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/Wind_CoreRP.unity.meta @@ -5,3 +5,10 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/Wind_CoreRP.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/MC2_SkyandFogSettingsProfile.asset.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/MC2_SkyandFogSettingsProfile.asset.meta index a30f1354..0009e1cc 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/MC2_SkyandFogSettingsProfile.asset.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/MC2_SkyandFogSettingsProfile.asset.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/MC2_SkyandFogSettingsProfile.asset + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/RuntimeBuild_HDRP.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/RuntimeBuild_HDRP.unity.meta index fd609d8a..559bca0a 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/RuntimeBuild_HDRP.unity.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/RuntimeBuild_HDRP.unity.meta @@ -5,3 +5,10 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/RuntimeBuild_HDRP.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/RuntimeDressUp_HDRP.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/RuntimeDressUp_HDRP.unity.meta index 8bea2cf0..4cd66521 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/RuntimeDressUp_HDRP.unity.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/RuntimeDressUp_HDRP.unity.meta @@ -5,3 +5,10 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/RuntimeDressUp_HDRP.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/UnityChanKAGURA_HDRP.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/UnityChanKAGURA_HDRP.unity.meta index 374b61f5..d9390fcf 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/UnityChanKAGURA_HDRP.unity.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/UnityChanKAGURA_HDRP.unity.meta @@ -5,3 +5,10 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/UnityChanKAGURA_HDRP.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/Wind_HDRP.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/Wind_HDRP.unity.meta index b627f60c..b0a5099b 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/Wind_HDRP.unity.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/Wind_HDRP.unity.meta @@ -5,3 +5,10 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/HDRP/Wind_HDRP.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/RuntimeBuild_URP.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/RuntimeBuild_URP.unity.meta index 632a5982..9ec4fc44 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/RuntimeBuild_URP.unity.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/RuntimeBuild_URP.unity.meta @@ -5,3 +5,10 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/RuntimeBuild_URP.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/RuntimeDressUp_URP.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/RuntimeDressUp_URP.unity.meta index 6dcb7c2b..d0acf47c 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/RuntimeDressUp_URP.unity.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/RuntimeDressUp_URP.unity.meta @@ -5,3 +5,10 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/RuntimeDressUp_URP.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/UnityChanKAGURA_URP.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/UnityChanKAGURA_URP.unity.meta index c50bf39e..15520817 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/UnityChanKAGURA_URP.unity.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/UnityChanKAGURA_URP.unity.meta @@ -5,3 +5,10 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/UnityChanKAGURA_URP.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/Wind_URP.unity.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/Wind_URP.unity.meta index cb67e264..f298694a 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/Wind_URP.unity.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/Wind_URP.unity.meta @@ -5,3 +5,10 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/URP/Wind_URP.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher.meta new file mode 100644 index 00000000..74824a62 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 20f694a56cb3ba842b35402189c3b2f6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D.meta new file mode 100644 index 00000000..a52c053f --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 098d9df8397d80f45baed0214420d1cf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: 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 00000000..3f6cc57d --- /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 00000000..ff590357 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeBuild_HighDefinition3D.unity.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 8a0637df5c1ee8a4d8d6c5d2f3807cde +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeBuild_HighDefinition3D.unity + uploadId: 756593 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 00000000..c23bafbe --- /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 00000000..e0f9bca4 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeDressUp_HighDefinition3D.unity.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 30700d501f109174891f340ae1fc1833 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/RuntimeDressUp_HighDefinition3D.unity + uploadId: 756593 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 00000000..71564526 --- /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 00000000..08312189 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/UnityChanKAGURA_HighDefinition3D.unity.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: ca2d4f8e19e54d642bbc386701570fd4 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/UnityChanKAGURA_HighDefinition3D.unity + uploadId: 756593 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 00000000..244111f0 --- /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 00000000..0d3360fe --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/Wind_HighDefinition3D.unity.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 8ef5d38bbe84ef44cb76386cf579b78d +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/HighDefinition3D/Wind_HighDefinition3D.unity + uploadId: 756593 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 00000000..c51f6ec4 --- /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 00000000..6571ff92 --- /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 00000000..75bcbb9a --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeBuild_Universal3D.unity.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 9d96bb6c1a7bbf14b95fba198bd36558 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeBuild_Universal3D.unity + uploadId: 756593 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 00000000..18f566a9 --- /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 00000000..0a6c8542 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeDressUp_Universal3D.unity.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 01f984873de94d845a6f0dad6e1764ce +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/RuntimeDressUp_Universal3D.unity + uploadId: 756593 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 00000000..c9715c26 --- /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 00000000..b892e855 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/UnityChanKAGURA_Universal3D.unity.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 54b38eb7d538c7f44b7fd7a9df0478d3 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/UnityChanKAGURA_Universal3D.unity + uploadId: 756593 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 00000000..e0bd9e1b --- /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 00000000..405c8dc2 --- /dev/null +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/Wind_Universal3D.unity.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 44a8005bc0be2894fb5f7cec86f3eeae +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes_Unity_6.1_or_Higher/Universal3D/Wind_Universal3D.unity + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/Logo/Dark_Silhouette.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/Logo/Dark_Silhouette.png.meta index a91419f5..a9e64089 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/Logo/Dark_Silhouette.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/Logo/Dark_Silhouette.png.meta @@ -133,3 +133,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/Logo/Dark_Silhouette.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_def_mat.mat b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_def_mat.mat index c1138f16..52d1b9fa 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_def_mat.mat +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_def_mat.mat @@ -1,6 +1,6 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: ---- !u!114 &-5805247609134839791 +--- !u!114 &-8367319535634762937 MonoBehaviour: m_ObjectHideFlags: 11 m_CorrespondingSourceObject: {fileID: 0} diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_def_mat.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_def_mat.mat.meta index 1df11100..374da6eb 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_def_mat.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_def_mat.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_def_mat.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_nol_mat.mat b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_nol_mat.mat index 0dc73c45..5dbb1be2 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_nol_mat.mat +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_nol_mat.mat @@ -105,19 +105,6 @@ Material: - _Tiling: {r: 1, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] m_AllowLocking: 1 ---- !u!114 &1416824612331664537 -MonoBehaviour: - m_ObjectHideFlags: 11 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} - m_Name: - m_EditorClassIdentifier: - version: 10 --- !u!114 &5988364977265673585 MonoBehaviour: m_ObjectHideFlags: 11 @@ -131,3 +118,16 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: version: 0 +--- !u!114 &6642007414726601541 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 10 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_nol_mat.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_nol_mat.mat.meta index 8acd3aac..48e00d42 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_nol_mat.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_nol_mat.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_nol_mat.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_skin_mat.mat b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_skin_mat.mat index 7ca1a6ee..487cbc5b 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_skin_mat.mat +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_skin_mat.mat @@ -13,6 +13,19 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: version: 0 +--- !u!114 &-3527211999276890483 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 10 --- !u!21 &2100000 Material: serializedVersion: 8 @@ -118,16 +131,3 @@ Material: - _Tiling: {r: 1, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] m_AllowLocking: 1 ---- !u!114 &7561439969631927331 -MonoBehaviour: - m_ObjectHideFlags: 11 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} - m_Name: - m_EditorClassIdentifier: - version: 10 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_skin_mat.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_skin_mat.mat.meta index a77823f1..8015b067 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_skin_mat.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_skin_mat.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/SB_skin_mat.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/def_mat.mat b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/def_mat.mat index 8b14002c..9b400892 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/def_mat.mat +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/def_mat.mat @@ -1,18 +1,5 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: ---- !u!114 &-3348263818793008538 -MonoBehaviour: - m_ObjectHideFlags: 11 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} - m_Name: - m_EditorClassIdentifier: - version: 10 --- !u!114 &-1839986918002453301 MonoBehaviour: m_ObjectHideFlags: 11 @@ -26,6 +13,19 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: version: 0 +--- !u!114 &-1156612615677998621 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 10 --- !u!21 &2100000 Material: serializedVersion: 8 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/def_mat.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/def_mat.mat.meta index 39800a06..24f6d5f2 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/def_mat.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/def_mat.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/def_mat.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/hair_mat.mat b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/hair_mat.mat index 48b84cb1..b2a9d855 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/hair_mat.mat +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/hair_mat.mat @@ -118,7 +118,7 @@ Material: - _Tiling: {r: 1, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] m_AllowLocking: 1 ---- !u!114 &8904441550551059416 +--- !u!114 &3524422830314133294 MonoBehaviour: m_ObjectHideFlags: 11 m_CorrespondingSourceObject: {fileID: 0} diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/hair_mat.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/hair_mat.mat.meta index 1adcd0bb..8cad7460 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/hair_mat.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/hair_mat.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/hair_mat.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/mouth_mat.mat b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/mouth_mat.mat index 59044bee..e12c6539 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/mouth_mat.mat +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/mouth_mat.mat @@ -1,5 +1,18 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: +--- !u!114 &-4586411623184738822 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 10 --- !u!21 &2100000 Material: serializedVersion: 8 @@ -118,16 +131,3 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: version: 0 ---- !u!114 &6747972257908541556 -MonoBehaviour: - m_ObjectHideFlags: 11 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} - m_Name: - m_EditorClassIdentifier: - version: 10 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/mouth_mat.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/mouth_mat.mat.meta index 9da46773..0f0c6611 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/mouth_mat.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/mouth_mat.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/mouth_mat.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/nol_mat.mat b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/nol_mat.mat index 26dd958b..46d08385 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/nol_mat.mat +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/nol_mat.mat @@ -1,6 +1,6 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: ---- !u!114 &-3882220622740168363 +--- !u!114 &-1182480219143839893 MonoBehaviour: m_ObjectHideFlags: 11 m_CorrespondingSourceObject: {fileID: 0} diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/nol_mat.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/nol_mat.mat.meta index e55fc721..9d078a31 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/nol_mat.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/nol_mat.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/nol_mat.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/skin_mat.mat b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/skin_mat.mat index c4dc4bab..7ad20da8 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/skin_mat.mat +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/skin_mat.mat @@ -1,6 +1,6 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: ---- !u!114 &-6659663828051372056 +--- !u!114 &-6487248340714685668 MonoBehaviour: m_ObjectHideFlags: 11 m_CorrespondingSourceObject: {fileID: 0} diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/skin_mat.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/skin_mat.mat.meta index 2727e440..15148879 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/skin_mat.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/skin_mat.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Materials/skin_mat.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/SD_UnityChan.controller.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/SD_UnityChan.controller.meta index 78613b00..7b18d809 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/SD_UnityChan.controller.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/SD_UnityChan.controller.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/SD_UnityChan.controller + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/body_sum.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/body_sum.png.meta index e2bfad8d..f9ed6109 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/body_sum.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/body_sum.png.meta @@ -133,3 +133,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/body_sum.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/body_win.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/body_win.png.meta index 878450c3..b9f51e6a 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/body_win.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/body_win.png.meta @@ -133,3 +133,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/body_win.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/misaki_head.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/misaki_head.png.meta index b50338c6..6d783611 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/misaki_head.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/misaki_head.png.meta @@ -133,3 +133,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/misaki_head.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/utc_all2.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/utc_all2.png.meta index 63b7e687..fc88cc45 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/utc_all2.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/utc_all2.png.meta @@ -133,3 +133,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/utc_all2.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/yuko_head.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/yuko_head.png.meta index c3cf7c14..fae0a2a9 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/yuko_head.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/yuko_head.png.meta @@ -133,3 +133,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Textures/yuko_head.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Body).prefab b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Body).prefab index df73543c..2e175432 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Body).prefab +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Body).prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e36810faeafb1c9effaf360ca0d250e8fd737558fcc4423ca3f84f8acf859686 -size 194332 +oid sha256:65425706988a58d5797e6383be3c3c3f073e26decefa6e16acd3474a16477045 +size 230271 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Body).prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Body).prefab.meta index d102802d..5edf25b8 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Body).prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Body).prefab.meta @@ -5,3 +5,11 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid + (Body).prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Hair).prefab b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Hair).prefab index 07235922..7f8d6581 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Hair).prefab +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Hair).prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8404f84ad997715570beb3ab06d2fe48412b78df0cd38f68aab944574e1ce137 -size 152902 +oid sha256:f1d1e9c1b01e53284c9e76f151987e27c12bd36e7fcadb114ea5b7b69a379bd4 +size 185523 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Hair).prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Hair).prefab.meta index f8b4e144..81c1dbd2 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Hair).prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Hair).prefab.meta @@ -5,3 +5,11 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid + (Hair).prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Skeleton).prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Skeleton).prefab.meta index e2be6b5d..e73b56ac 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Skeleton).prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Skeleton).prefab.meta @@ -5,3 +5,11 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid + (Skeleton).prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid Variant.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid Variant.prefab.meta index aa0274ac..0a9fddf7 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid Variant.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid Variant.prefab.meta @@ -5,3 +5,11 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid + Variant.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid.fbx.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid.fbx.meta index a8e69415..6959d13c 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid.fbx.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid.fbx.meta @@ -524,7 +524,8 @@ ModelImporter: - name: Character1_LeftHandPinky3 parentName: Character1_LeftHandPinky2 position: {x: -0.0075915335, y: -0.000000009536743, z: 0} - rotation: {x: -0.000000002793968, y: -0.000000029802322, z: -0.000000007450581, w: 1} + rotation: {x: -0.000000002793968, y: -0.000000029802322, z: -0.000000007450581, + w: 1} scale: {x: 0.9999999, y: 1, z: 0.99999994} - name: Character1_LeftHandIndex1 parentName: Character1_LeftHand @@ -539,7 +540,8 @@ ModelImporter: - name: Character1_LeftHandIndex3 parentName: Character1_LeftHandIndex2 position: {x: -0.0107357595, y: 0.000000014305114, z: -0.000000076293944} - rotation: {x: -0.0000000018626456, y: -0.00000014901154, z: -0.0000000037252887, w: 1} + rotation: {x: -0.0000000018626456, y: -0.00000014901154, z: -0.0000000037252887, + w: 1} scale: {x: 1.0000004, y: 0.9999999, z: 1.0000004} - name: Character1_LeftHandThumb1 parentName: Character1_LeftHand @@ -559,7 +561,8 @@ ModelImporter: - name: Character1_LeftHandThumb4 parentName: Character1_LeftHandThumb3 position: {x: -0.012429466, y: -0.000000038146972, z: 0.000000038146972} - rotation: {x: 0.00000014156107, y: 0.00000002607702, z: -0.000000089406974, w: 1} + rotation: {x: 0.00000014156107, y: 0.00000002607702, z: -0.000000089406974, + w: 1} scale: {x: 1.0000001, y: 0.99999946, z: 0.9999998} - name: Character1_LeftHandMiddle1 parentName: Character1_LeftHand @@ -574,7 +577,8 @@ ModelImporter: - name: Character1_LeftHandMiddle3 parentName: Character1_LeftHandMiddle2 position: {x: -0.012807655, y: -0.000000005960464, z: -0.000000076293944} - rotation: {x: 0.000000007450579, y: -0.000000014901163, z: -0.0000000037252907, w: 1} + rotation: {x: 0.000000007450579, y: -0.000000014901163, z: -0.0000000037252907, + w: 1} scale: {x: 1, y: 1.0000001, z: 0.99999994} - name: J_L_Elbow parentName: Character1_LeftForeArm @@ -619,17 +623,20 @@ ModelImporter: - name: J_L_HairTail_01 parentName: J_L_HairTail_00 position: {x: 0.000000019073486, y: -0.000000076293944, z: -0.19820912} - rotation: {x: 0.000000029802326, y: -0.000000022351744, z: 0.000000011175873, w: 1} + rotation: {x: 0.000000029802326, y: -0.000000022351744, z: 0.000000011175873, + w: 1} scale: {x: 1, y: 0.99999994, z: 1.0000001} - name: J_L_HairTail_02 parentName: J_L_HairTail_01 position: {x: -0, y: 0.000000114440915, z: -0.2224917} - rotation: {x: -4.9960047e-16, y: -0.00000006705523, z: -0.0000000074505815, w: 1} + rotation: {x: -4.9960047e-16, y: -0.00000006705523, z: -0.0000000074505815, + w: 1} scale: {x: 0.9999999, y: 1.0000002, z: 0.99999994} - name: J_L_HairTail_03 parentName: J_L_HairTail_02 position: {x: 0.000000019073486, y: 0.000000076293944, z: -0.17191942} - rotation: {x: 0.000000014901161, y: -0.000000007450581, z: -0.000000007450581, w: 1} + rotation: {x: 0.000000014901161, y: -0.000000007450581, z: -0.000000007450581, + w: 1} scale: {x: 1, y: 1, z: 1} - name: J_L_HeadRibbon_00 parentName: Character1_Head @@ -649,7 +656,8 @@ ModelImporter: - name: J_L_HeadRibbon_03 parentName: J_L_HeadRibbon_02 position: {x: -0.000000076293944, y: -0.00000015258789, z: 0.16675673} - rotation: {x: -0.00000022351746, y: -0.00000011920929, z: 0.0000000149011345, w: 1} + rotation: {x: -0.00000022351746, y: -0.00000011920929, z: 0.0000000149011345, + w: 1} scale: {x: 1, y: 0.9999999, z: 1.0000001} - name: J_R_HairSide2_00 parentName: Character1_Head @@ -669,17 +677,20 @@ ModelImporter: - name: J_R_HairTail_01 parentName: J_R_HairTail_00 position: {x: -0.000000095367426, y: 0.0000009918213, z: -0.19820796} - rotation: {x: 0.000000029802322, y: -0.0000000074505815, z: -0.00000010058282, w: 1} + rotation: {x: 0.000000029802322, y: -0.0000000074505815, z: -0.00000010058282, + w: 1} scale: {x: 1.0000001, y: 0.99999994, z: 1} - name: J_R_HairTail_02 parentName: J_R_HairTail_01 position: {x: -0.0000004196167, y: -0.0000005340576, z: -0.2224927} - rotation: {x: 0.000000089406925, y: 0.000000014901161, z: -0.000000040978207, w: 1} + rotation: {x: 0.000000089406925, y: 0.000000014901161, z: -0.000000040978207, + w: 1} scale: {x: 0.99999964, y: 1.0000002, z: 1} - name: J_R_HairTail_03 parentName: J_R_HairTail_02 position: {x: -0.000000038146972, y: -0.000000038146972, z: -0.17191932} - rotation: {x: -1.6653337e-16, y: -0.000000014901158, z: -0.000000011175868, w: 1} + rotation: {x: -1.6653337e-16, y: -0.000000014901158, z: -0.000000011175868, + w: 1} scale: {x: 1.0000001, y: 1.0000001, z: 1.0000001} - name: J_R_HeadRibbon_00 parentName: Character1_Head @@ -714,7 +725,8 @@ ModelImporter: - name: J_L_HairSide_02 parentName: J_L_HairSide_01 position: {x: -0.17118454, y: 0.000000009536743, z: 0.00000022888183} - rotation: {x: 0.000000077299774, y: -0.00000008475035, z: -0.000000014901153, w: 1} + rotation: {x: 0.000000077299774, y: -0.00000008475035, z: -0.000000014901153, + w: 1} scale: {x: 1.0000002, y: 1, z: 0.9999998} - name: J_R_HairSide_00 parentName: Character1_Head @@ -729,7 +741,8 @@ ModelImporter: - name: J_R_HairSide_02 parentName: J_R_HairSide_01 position: {x: 0.17118447, y: 0.000000009536743, z: -0.00000016212464} - rotation: {x: -0.00000069662923, y: 0.00000008195637, z: 0.000000029802383, w: 1} + rotation: {x: -0.00000069662923, y: 0.00000008195637, z: 0.000000029802383, + w: 1} scale: {x: 0.9999999, y: 1.0000001, z: 0.9999996} - name: bone_eye_L parentName: Character1_Head @@ -829,7 +842,8 @@ ModelImporter: - name: Character1_RightHandPinky3 parentName: Character1_RightHandPinky2 position: {x: 0.0075922012, y: 0.00000013589859, z: -0.00000030517577} - rotation: {x: -0.00000024121255, y: 0.00000025331983, z: -0.000000014901105, w: 1} + rotation: {x: -0.00000024121255, y: 0.00000025331983, z: -0.000000014901105, + w: 1} scale: {x: 0.99999964, y: 1.0000001, z: 1} - name: Character1_RightHandRing1 parentName: Character1_RightHand @@ -844,7 +858,8 @@ ModelImporter: - name: Character1_RightHandRing3 parentName: Character1_RightHandRing2 position: {x: 0.0100004, y: -0.000000009834766, z: -0.00000034332274} - rotation: {x: 0.0000002421438, y: 0.000000029802315, z: -0.0000000022118978, w: 1} + rotation: {x: 0.0000002421438, y: 0.000000029802315, z: -0.0000000022118978, + w: 1} scale: {x: 1.0000004, y: 1.0000001, z: 1.0000001} - name: Character1_RightHandIndex1 parentName: Character1_RightHand @@ -859,7 +874,8 @@ ModelImporter: - name: Character1_RightHandIndex3 parentName: Character1_RightHandIndex2 position: {x: 0.010736103, y: -0.000000085830685, z: -0.00000015258789} - rotation: {x: -0.000000007450581, y: 0.000000104308135, z: -0.000000016763806, w: 1} + rotation: {x: -0.000000007450581, y: 0.000000104308135, z: -0.000000016763806, + w: 1} scale: {x: 0.9999998, y: 0.9999999, z: 1.0000004} - name: Character1_RightHandMiddle1 parentName: Character1_RightHand @@ -874,7 +890,8 @@ ModelImporter: - name: Character1_RightHandMiddle3 parentName: Character1_RightHandMiddle2 position: {x: 0.012807674, y: 0.0000000667572, z: -0.00000087738033} - rotation: {x: -0.0000000018626964, y: -0.00000092387177, z: -0.000000055879344, w: 1} + rotation: {x: -0.0000000018626964, y: -0.00000092387177, z: -0.000000055879344, + w: 1} scale: {x: 1.0000001, y: 1, z: 0.9999999} - name: J_R_ForeArm_00_tw parentName: Character1_RightForeArm @@ -1029,7 +1046,8 @@ ModelImporter: - name: J_R_knee parentName: Character1_RightUpLeg position: {x: -0, y: 0.022121582, z: -0.15356168} - rotation: {x: 0.0000000025893838, y: 0.000000009194991, z: 0.0000000023283064, w: 1} + rotation: {x: 0.0000000025893838, y: 0.000000009194991, z: 0.0000000023283064, + w: 1} scale: {x: 1, y: 1, z: 1} - name: utc_head parentName: Utc_sum_humanoid(Clone) @@ -1079,3 +1097,10 @@ ModelImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid.fbx + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/01Unity-Chan License Terms and Condition_EN_UCL2.0.pdf.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/01Unity-Chan License Terms and Condition_EN_UCL2.0.pdf.meta index 7e370183..de7829ce 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/01Unity-Chan License Terms and Condition_EN_UCL2.0.pdf.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/01Unity-Chan License Terms and Condition_EN_UCL2.0.pdf.meta @@ -5,3 +5,11 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/01Unity-Chan + License Terms and Condition_EN_UCL2.0.pdf + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/02Unity-Chan License Terms and Condition_Summary_EN_UCL2.0.pdf.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/02Unity-Chan License Terms and Condition_Summary_EN_UCL2.0.pdf.meta index e99bae58..1e02e671 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/02Unity-Chan License Terms and Condition_Summary_EN_UCL2.0.pdf.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/02Unity-Chan License Terms and Condition_Summary_EN_UCL2.0.pdf.meta @@ -5,3 +5,11 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/02Unity-Chan + License Terms and Condition_Summary_EN_UCL2.0.pdf + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/03Indication of License_EN_UCL2.0.pdf.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/03Indication of License_EN_UCL2.0.pdf.meta index 6eaa3bd4..cc08eda0 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/03Indication of License_EN_UCL2.0.pdf.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/03Indication of License_EN_UCL2.0.pdf.meta @@ -5,3 +5,11 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/English/03Indication + of License_EN_UCL2.0.pdf + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/01Unity-Chan License Terms and Condition_JP_UCL2.0.pdf.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/01Unity-Chan License Terms and Condition_JP_UCL2.0.pdf.meta index e9d95989..cc01d966 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/01Unity-Chan License Terms and Condition_JP_UCL2.0.pdf.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/01Unity-Chan License Terms and Condition_JP_UCL2.0.pdf.meta @@ -5,3 +5,11 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/01Unity-Chan + License Terms and Condition_JP_UCL2.0.pdf + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/02Unity-Chan License Terms and Condition_Summary_JP_UCL2.0.pdf.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/02Unity-Chan License Terms and Condition_Summary_JP_UCL2.0.pdf.meta index 678f5b68..8969c88c 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/02Unity-Chan License Terms and Condition_Summary_JP_UCL2.0.pdf.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/02Unity-Chan License Terms and Condition_Summary_JP_UCL2.0.pdf.meta @@ -5,3 +5,11 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/02Unity-Chan + License Terms and Condition_Summary_JP_UCL2.0.pdf + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/03Indication of License_JP_UCL2.0.pdf.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/03Indication of License_JP_UCL2.0.pdf.meta index 69d2d752..71a62788 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/03Indication of License_JP_UCL2.0.pdf.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/03Indication of License_JP_UCL2.0.pdf.meta @@ -5,3 +5,11 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/Japanese/03Indication + of License_JP_UCL2.0.pdf + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_LOGO_rules02.ai.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_LOGO_rules02.ai.meta index 66e3eda7..9575c929 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_LOGO_rules02.ai.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_LOGO_rules02.ai.meta @@ -5,3 +5,11 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License + Logo/LUUL_LOGO_rules02.ai + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_LOGO_rules02.psd.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_LOGO_rules02.psd.meta index cee4d9fa..f8fdc761 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_LOGO_rules02.psd.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_LOGO_rules02.psd.meta @@ -133,3 +133,11 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License + Logo/LUUL_LOGO_rules02.psd + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_logo-guideline.pdf.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_logo-guideline.pdf.meta index 6c4eca2f..b97ec614 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_logo-guideline.pdf.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_logo-guideline.pdf.meta @@ -5,3 +5,11 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License + Logo/LUUL_logo-guideline.pdf + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_logo-guideline_en.pdf.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_logo-guideline_en.pdf.meta index 14cb0a16..ba773669 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_logo-guideline_en.pdf.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/LUUL_logo-guideline_en.pdf.meta @@ -5,3 +5,11 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License + Logo/LUUL_logo-guideline_en.pdf + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/jpg/Dark_Silhouette.jpg.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/jpg/Dark_Silhouette.jpg.meta index f247ebd4..bfb6de0d 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/jpg/Dark_Silhouette.jpg.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/jpg/Dark_Silhouette.jpg.meta @@ -133,3 +133,11 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License + Logo/Others/jpg/Dark_Silhouette.jpg + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/jpg/Light_Silhouette.jpg.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/jpg/Light_Silhouette.jpg.meta index 6497d7f9..84d85602 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/jpg/Light_Silhouette.jpg.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/jpg/Light_Silhouette.jpg.meta @@ -133,3 +133,11 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License + Logo/Others/jpg/Light_Silhouette.jpg + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/png/Dark_Silhouette.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/png/Dark_Silhouette.png.meta index ff1507d3..d7d7d0e5 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/png/Dark_Silhouette.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/png/Dark_Silhouette.png.meta @@ -133,3 +133,11 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License + Logo/Others/png/Dark_Silhouette.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/png/Light_Frame.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/png/Light_Frame.png.meta index 3ea31d42..35d52fe9 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/png/Light_Frame.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/png/Light_Frame.png.meta @@ -133,3 +133,11 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License + Logo/Others/png/Light_Frame.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/png/Light_Silhouette.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/png/Light_Silhouette.png.meta index 8c107994..0abf566c 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/png/Light_Silhouette.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/png/Light_Silhouette.png.meta @@ -133,3 +133,11 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License + Logo/Others/png/Light_Silhouette.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/svg/Dark_Silhouette.svg.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/svg/Dark_Silhouette.svg.meta index f556b7d3..8295f26a 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/svg/Dark_Silhouette.svg.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/svg/Dark_Silhouette.svg.meta @@ -5,3 +5,11 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License + Logo/Others/svg/Dark_Silhouette.svg + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/svg/Light_Frame.svg.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/svg/Light_Frame.svg.meta index 026f1e4c..1b0f8139 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/svg/Light_Frame.svg.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/svg/Light_Frame.svg.meta @@ -5,3 +5,11 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License + Logo/Others/svg/Light_Frame.svg + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/svg/Light_Silhouette.svg.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/svg/Light_Silhouette.svg.meta index 2cbe484a..eca480f1 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/svg/Light_Silhouette.svg.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License Logo/Others/svg/Light_Silhouette.svg.meta @@ -5,3 +5,11 @@ DefaultImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UCL2.0/License + Logo/Others/svg/Light_Silhouette.svg + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/Unity-Chan License.txt.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/Unity-Chan License.txt.meta index 06b4096e..2adc6f26 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/Unity-Chan License.txt.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/Unity-Chan License.txt.meta @@ -5,3 +5,11 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/Unity-Chan + License.txt + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/RUN00_F.anim.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/RUN00_F.anim.meta index ac7246d3..0576d8ce 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/RUN00_F.anim.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/RUN00_F.anim.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/RUN00_F.anim + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/UC01_001_UniteInTheSky -WA-.fbx.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/UC01_001_UniteInTheSky -WA-.fbx.meta index 58372d7f..bccaa898 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/UC01_001_UniteInTheSky -WA-.fbx.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/UC01_001_UniteInTheSky -WA-.fbx.meta @@ -1139,3 +1139,11 @@ ModelImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/UC01_001_UniteInTheSky + -WA-.fbx + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WAIT02.anim.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WAIT02.anim.meta index 97a14dfe..3f27c2f5 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WAIT02.anim.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WAIT02.anim.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WAIT02.anim + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WAIT04.anim.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WAIT04.anim.meta index 7998c131..4a9407dc 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WAIT04.anim.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WAIT04.anim.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WAIT04.anim + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WALK00_F.anim.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WALK00_F.anim.meta index 8ef36ead..c3100148 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WALK00_F.anim.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WALK00_F.anim.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WALK00_F.anim + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WIN00.anim.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WIN00.anim.meta index 6188edef..059cccb9 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WIN00.anim.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WIN00.anim.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Animation/WIN00.anim + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Albedo.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Albedo.mat.meta index a574487f..efa01cdf 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Albedo.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Albedo.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Albedo.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Body Back.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Body Back.mat.meta index 12cfeba1..70324ca1 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Body Back.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Body Back.mat.meta @@ -6,3 +6,11 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Body + Back.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Body.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Body.mat.meta index 56774b83..4a580829 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Body.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Body.mat.meta @@ -7,3 +7,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Body.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Eyes.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Eyes.mat.meta index b901288f..6ffab132 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Eyes.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Eyes.mat.meta @@ -7,3 +7,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Eyes.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Eyes_HL.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Eyes_HL.mat.meta index 80ac406f..5895365a 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Eyes_HL.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Eyes_HL.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Eyes_HL.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Face.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Face.mat.meta index a9db4277..011cc00b 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Face.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Face.mat.meta @@ -7,3 +7,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Face.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Hair.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Hair.mat.meta index fc702678..b1f3daa4 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Hair.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Hair.mat.meta @@ -7,3 +7,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Hair.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/HairPony.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/HairPony.mat.meta index 719a4638..90ecbfc2 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/HairPony.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/HairPony.mat.meta @@ -7,3 +7,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/HairPony.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Headgear.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Headgear.mat.meta index f858dbd1..61e89a10 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Headgear.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Headgear.mat.meta @@ -7,3 +7,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Headgear.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/LongSleeve Back.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/LongSleeve Back.mat.meta index 4d73bcf7..9f6702a5 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/LongSleeve Back.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/LongSleeve Back.mat.meta @@ -6,3 +6,11 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/LongSleeve + Back.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/LongSleeve.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/LongSleeve.mat.meta index 3dd40171..6012aeab 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/LongSleeve.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/LongSleeve.mat.meta @@ -7,3 +7,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/LongSleeve.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Skin.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Skin.mat.meta index ed5220cb..f262fdde 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Skin.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Skin.mat.meta @@ -7,3 +7,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/Skin.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Base.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Base.png.meta index abe0c9ba..e55ecabb 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Base.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Base.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Base.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Emi.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Emi.png.meta index f44db686..9f183a74 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Emi.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Emi.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Emi.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_SGM.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_SGM.png.meta index 7e9d9cda..30a5d978 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_SGM.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_SGM.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_SGM.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Shd1.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Shd1.png.meta index 3654197e..c9ab2800 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Shd1.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Shd1.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Shd1.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Shd2.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Shd2.png.meta index 68eb45b2..9e8f71d6 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Shd2.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Shd2.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Shd2.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Spc.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Spc.png.meta index 4186c54a..3ec2a1c5 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Spc.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Spc.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Body_Spc.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Base.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Base.png.meta index fd685467..28721547 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Base.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Base.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Base.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Emi.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Emi.png.meta index 6b8446ba..4cfe5938 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Emi.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Emi.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Emi.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_LSM.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_LSM.png.meta index 54400b4e..2cbaaa97 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_LSM.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_LSM.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_LSM.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Rim.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Rim.png.meta index f40fe31e..cedb6221 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Rim.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Rim.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Rim.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_SGM.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_SGM.png.meta index 46e30702..c70d027e 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_SGM.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_SGM.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_SGM.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Shd1.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Shd1.png.meta index 0f7fa712..1820e574 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Shd1.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Shd1.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Shd1.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Shd2.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Shd2.png.meta index 65177a9b..934ff633 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Shd2.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Shd2.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Face_Shd2.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Hair_SGM.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Hair_SGM.png.meta index 063a0391..cbb1534a 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Hair_SGM.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Hair_SGM.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Hair_SGM.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Headfgear_Base.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Headfgear_Base.png.meta index f322c00b..fe494a9b 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Headfgear_Base.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Headfgear_Base.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Headfgear_Base.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Base.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Base.png.meta index 0b4455cf..85ff04d6 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Base.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Base.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Base.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Emi.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Emi.png.meta index 6217632c..4318be81 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Emi.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Emi.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Emi.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Nrm.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Nrm.png.meta index 9bd5b339..7e9e342d 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Nrm.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Nrm.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Nrm.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Rim.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Rim.png.meta index 0fa714a2..2960eee0 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Rim.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Rim.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Rim.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_SGM.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_SGM.png.meta index b25f5ab4..196427d1 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_SGM.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_SGM.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_SGM.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Spc.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Spc.png.meta index fe3b4e05..d86396bd 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Spc.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Spc.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_Spc.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_SpcCol.png.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_SpcCol.png.meta index eecb6367..86198681 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_SpcCol.png.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_SpcCol.png.meta @@ -138,3 +138,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/TEX/PNG/Skin_SpcCol.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/face3_main.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/face3_main.mat.meta index 3ef95aa0..48824728 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/face3_main.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/face3_main.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/face3_main.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/headExt.mat.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/headExt.mat.meta index f9977951..c94071f3 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/headExt.mat.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/headExt.mat.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/Materials/headExt.mat + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UniteInTheSky.controller.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UniteInTheSky.controller.meta index 60406f79..38be1232 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UniteInTheSky.controller.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UniteInTheSky.controller.meta @@ -6,3 +6,10 @@ NativeFormatImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UniteInTheSky.controller + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA.fbx.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA.fbx.meta index f7869cf0..175da030 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA.fbx.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA.fbx.meta @@ -1119,12 +1119,14 @@ ModelImporter: - name: DB_HairPonny_E_06 parentName: DB_HairPonny_E_05 position: {x: -0.20536478, y: 0.0000000181024, z: -0.000000052352917} - rotation: {x: 0.000000010306467, y: 0.00000037532288, z: -0.00000015743396, w: 1} + rotation: {x: 0.000000010306467, y: 0.00000037532288, z: -0.00000015743396, + w: 1} scale: {x: 1, y: 1, z: 1} - name: DB_HairPonny_E_07 parentName: DB_HairPonny_E_06 position: {x: -0.20241548, y: -0.000000007486665, z: -0.000000014204306} - rotation: {x: -0.000000013092317, y: -0.0000013895333, z: 0.000000036315225, w: 1} + rotation: {x: -0.000000013092317, y: -0.0000013895333, z: 0.000000036315225, + w: 1} scale: {x: 1, y: 1, z: 1} - name: DB_HairPonny_E_08 parentName: DB_HairPonny_E_07 @@ -1379,7 +1381,8 @@ ModelImporter: - name: DB_Sode_B_03_L parentName: DB_Sode_B_02_L position: {x: -0.00000003495618, y: 0.16377598, z: 0.00000008490355} - rotation: {x: 0.00000043213367, y: -0.000000017451445, z: 0.000000006864544, w: 1} + rotation: {x: 0.00000043213367, y: -0.000000017451445, z: 0.000000006864544, + w: 1} scale: {x: 1, y: 1, z: 1} - name: DB_Sode_B_04_L parentName: DB_Sode_B_03_L @@ -1424,12 +1427,14 @@ ModelImporter: - name: DB_Sode_A_05_L parentName: DB_Sode_A_04_L position: {x: 0.0000000058321894, y: 0.18826447, z: -0.000000033450405} - rotation: {x: -0.0000031758095, y: -0.00000007047311, z: -0.000000009660246, w: 1} + rotation: {x: -0.0000031758095, y: -0.00000007047311, z: -0.000000009660246, + w: 1} scale: {x: 1, y: 1, z: 1} - name: DB_Sode_A_06_L parentName: DB_Sode_A_05_L position: {x: -0.00000004670306, y: 0.10419001, z: -0.00000009729876} - rotation: {x: 0.0000025499612, y: -0.0000000085358245, z: 0.0000000013564954, w: 1} + rotation: {x: 0.0000025499612, y: -0.0000000085358245, z: 0.0000000013564954, + w: 1} scale: {x: 1, y: 1, z: 1} - name: DB_Sode_A_06_L_end parentName: DB_Sode_A_06_L @@ -1929,7 +1934,8 @@ ModelImporter: - name: DB_Skirt_E_04_L parentName: DB_Skirt_E_03_L position: {x: -0.061201386, y: 0.0000000047683715, z: 0.00000004529953} - rotation: {x: 0.00000017229465, y: 0.0000000018626438, z: -0.00000020489097, w: 1} + rotation: {x: 0.00000017229465, y: 0.0000000018626438, z: -0.00000020489097, + w: 1} scale: {x: 0.99999994, y: 1.0000002, z: 1.0000001} - name: DB_Skirt_E_04_L_end parentName: DB_Skirt_E_04_L @@ -1954,7 +1960,8 @@ ModelImporter: - name: DB_Skirt_D_04_L parentName: DB_Skirt_D_03_L position: {x: -0.06120134, y: 0.000000028610229, z: 0.00000008167233} - rotation: {x: -0.0000001379085, y: 0.000000059069862, z: -0.000000031664968, w: 1} + rotation: {x: -0.0000001379085, y: 0.000000059069862, z: -0.000000031664968, + w: 1} scale: {x: 1, y: 1, z: 1} - name: DB_Skirt_D_04_L_end parentName: DB_Skirt_D_04_L @@ -2004,7 +2011,8 @@ ModelImporter: - name: DB_Skirt_D_04_R parentName: DB_Skirt_D_03_R position: {x: -0.061201222, y: 0.000000022649765, z: 0.0000000997819} - rotation: {x: 0.00000008333883, y: -0.00000006679329, z: 0.0000000046566138, w: 1} + rotation: {x: 0.00000008333883, y: -0.00000006679329, z: 0.0000000046566138, + w: 1} scale: {x: 1, y: 0.9999998, z: 0.9999999} - name: DB_Skirt_D_04_R_end parentName: DB_Skirt_D_04_R @@ -2029,7 +2037,8 @@ ModelImporter: - name: DB_Skirt_E_04_R parentName: DB_Skirt_E_03_R position: {x: -0.06120137, y: -0.000000052452087, z: 0.000000007152557} - rotation: {x: -0.000000073574476, y: -0.00000002328306, z: 0.00000030547378, w: 1} + rotation: {x: -0.000000073574476, y: -0.00000002328306, z: 0.00000030547378, + w: 1} scale: {x: 1.0000001, y: 1.0000001, z: 1.0000001} - name: DB_Skirt_E_04_R_end parentName: DB_Skirt_E_04_R @@ -2054,7 +2063,8 @@ ModelImporter: - name: DB_Skirt_C_04_R parentName: DB_Skirt_C_03_R position: {x: -0.061201274, y: 0.000000007897615, z: 0.000000007152557} - rotation: {x: 0.000000013969838, y: 0.0000000015133992, z: 0.0000000942091, w: 1} + rotation: {x: 0.000000013969838, y: 0.0000000015133992, z: 0.0000000942091, + w: 1} scale: {x: 1, y: 1, z: 1.0000001} - name: DB_Skirt_C_04_R_end parentName: DB_Skirt_C_04_R @@ -2079,7 +2089,8 @@ ModelImporter: - name: DB_Skirt_B_04_R parentName: DB_Skirt_B_03_R position: {x: -0.061201327, y: 0.000000023841856, z: -0.000000014305114} - rotation: {x: -0.000000018626448, y: -0.00000012479722, z: -0.00000025518239, w: 1} + rotation: {x: -0.000000018626448, y: -0.00000012479722, z: -0.00000025518239, + w: 1} scale: {x: 1, y: 1.0000001, z: 1.0000001} - name: DB_Skirt_B_04_R_end parentName: DB_Skirt_B_04_R @@ -2114,7 +2125,8 @@ ModelImporter: - name: DB_Skirt_A_05_R parentName: DB_Skirt_A_04_R position: {x: -0.068666466, y: -0.0000000011920929, z: 0.000000023841856} - rotation: {x: -0.000000070780516, y: -0.000000027008351, z: 0.000000088475645, w: 1} + rotation: {x: -0.000000070780516, y: -0.000000027008351, z: 0.000000088475645, + w: 1} scale: {x: 1.0000001, y: 1, z: 1.0000001} - name: DB_Skirt_A_05_R_end parentName: DB_Skirt_A_05_R @@ -2245,3 +2257,10 @@ ModelImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA.fbx + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA_MC2.prefab b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA_MC2.prefab index 95d1c929..59845608 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA_MC2.prefab +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA_MC2.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30248c993012647c1ae3c5d3dc4682a436cbee16ddf1d480e4cbd79d71fa046d -size 840671 +oid sha256:14cdc785604144bb02b06bc56d2439eafe6035c3aa279ca90edc94824ab1c3c1 +size 1050073 diff --git a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA_MC2.prefab.meta b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA_MC2.prefab.meta index 1f4b6144..0eb1ab18 100644 --- a/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA_MC2.prefab.meta +++ b/Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA_MC2.prefab.meta @@ -5,3 +5,10 @@ PrefabImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA_MC2.prefab + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/MagicaCloth2.asmdef.meta b/Assets/External/MagicaCloth2/MagicaCloth2.asmdef.meta index 8be1cce3..27377342 100644 --- a/Assets/External/MagicaCloth2/MagicaCloth2.asmdef.meta +++ b/Assets/External/MagicaCloth2/MagicaCloth2.asmdef.meta @@ -5,3 +5,10 @@ AssemblyDefinitionImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/MagicaCloth2.asmdef + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Readme.txt.meta b/Assets/External/MagicaCloth2/Readme.txt.meta index 34934921..cbdd5391 100644 --- a/Assets/External/MagicaCloth2/Readme.txt.meta +++ b/Assets/External/MagicaCloth2/Readme.txt.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Readme.txt + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Readme_jpn.txt.meta b/Assets/External/MagicaCloth2/Readme_jpn.txt.meta index c0c1039a..735fb715 100644 --- a/Assets/External/MagicaCloth2/Readme_jpn.txt.meta +++ b/Assets/External/MagicaCloth2/Readme_jpn.txt.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Readme_jpn.txt + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Icon/icon-cloth.png.meta b/Assets/External/MagicaCloth2/Res/Icon/icon-cloth.png.meta index 87a8e234..93c678e0 100644 --- a/Assets/External/MagicaCloth2/Res/Icon/icon-cloth.png.meta +++ b/Assets/External/MagicaCloth2/Res/Icon/icon-cloth.png.meta @@ -122,3 +122,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Icon/icon-cloth.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Icon/icon-collider.png.meta b/Assets/External/MagicaCloth2/Res/Icon/icon-collider.png.meta index f418d040..6532b4a7 100644 --- a/Assets/External/MagicaCloth2/Res/Icon/icon-collider.png.meta +++ b/Assets/External/MagicaCloth2/Res/Icon/icon-collider.png.meta @@ -134,3 +134,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Icon/icon-collider.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Icon/icon-settings.png.meta b/Assets/External/MagicaCloth2/Res/Icon/icon-settings.png.meta index dcb317a8..60d893a2 100644 --- a/Assets/External/MagicaCloth2/Res/Icon/icon-settings.png.meta +++ b/Assets/External/MagicaCloth2/Res/Icon/icon-settings.png.meta @@ -133,3 +133,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Icon/icon-settings.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Icon/icon-wind.png.meta b/Assets/External/MagicaCloth2/Res/Icon/icon-wind.png.meta index e23a34f8..7a8bb290 100644 --- a/Assets/External/MagicaCloth2/Res/Icon/icon-wind.png.meta +++ b/Assets/External/MagicaCloth2/Res/Icon/icon-wind.png.meta @@ -133,3 +133,10 @@ TextureImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Icon/icon-wind.png + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Accessory.json b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Accessory.json index c5081e22..13048cca 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Accessory.json +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Accessory.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1e2f79971878ba5c297838ad35991c32cf4a3a024b2b3f41a6bb84ce37d40dd -size 4902 +oid sha256:9230b1b99e7f2a1a4792abd4aa390a94944a620e166e3b5268f64106f17f07d6 +size 6293 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Accessory.json.meta b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Accessory.json.meta index 3723e494..55a7a181 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Accessory.json.meta +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Accessory.json.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Accessory.json + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Cape.json b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Cape.json index f58e28f7..b09d1003 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Cape.json +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Cape.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a231cd5bb894f1c2295a5f594c1a8e48e6888bb4dd59a12041ad8ead1b8c0f38 -size 4898 +oid sha256:e9d58113a22f6e8405a83f620ffc94255740d6d2f47515f921f30dbf2a6d21a9 +size 6288 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Cape.json.meta b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Cape.json.meta index 27684048..d0f11c03 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Cape.json.meta +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Cape.json.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Cape.json + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_FrontHair.json b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_FrontHair.json index 419d135a..6702b2ed 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_FrontHair.json +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_FrontHair.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc579add2e2753d68f81019fdc09f68b596242641c0ea1cfa4a2a0a915f67420 -size 4914 +oid sha256:c4525fcb0d6edbdf1cb9be2320e0183d2b16c0431174a7bfbf77d7b1045477ff +size 6304 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_FrontHair.json.meta b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_FrontHair.json.meta index 39cbb35c..ff6d5424 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_FrontHair.json.meta +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_FrontHair.json.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_FrontHair.json + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_HardSpring.json b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_HardSpring.json index daf19306..ccc8f82c 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_HardSpring.json +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_HardSpring.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d12e5a64e15cd95ea369aa7699fbbc9ae4611cdf2beb13586b4efb2d0336cf6 -size 6101 +oid sha256:547af0e1cd8f916d6157753c9558eabd5c1b1a605aac76e82014afb828ab9a45 +size 6151 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_HardSpring.json.meta b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_HardSpring.json.meta index e584ffdf..852a34f3 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_HardSpring.json.meta +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_HardSpring.json.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_HardSpring.json + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_LongHair.json b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_LongHair.json index ce8555d7..5a056159 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_LongHair.json +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_LongHair.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5fba83920709e7503a59ed4947fb7004747ffde7af0205a56222ac6dee414ca -size 5080 +oid sha256:bca2069de6a5b90981188c4f1292c6ad78b2cd3e090f35373c4d14dc36418703 +size 6485 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_LongHair.json.meta b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_LongHair.json.meta index 55826ab6..1ec8ac23 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_LongHair.json.meta +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_LongHair.json.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_LongHair.json + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_MiddleSpring.json b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_MiddleSpring.json index ed94b553..76634848 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_MiddleSpring.json +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_MiddleSpring.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ada23826e292294dfba2aa624b859fcbd04e8cb9a7bc6da6f11e727ca1b5173 -size 6102 +oid sha256:88480173e4c0cf1c93b6ac45231c3469d338b381ff862666572b69075a49f2cd +size 6152 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_MiddleSpring.json.meta b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_MiddleSpring.json.meta index 1e6dff93..432d56c5 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_MiddleSpring.json.meta +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_MiddleSpring.json.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_MiddleSpring.json + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_ShortHair.json b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_ShortHair.json index 3ee1664a..ca590f71 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_ShortHair.json +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_ShortHair.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31fc5c1073d88e4f75f78e2509d4e1299c70d0fd21bd6f492fa2a444ca76a8e9 -size 5008 +oid sha256:f1a20e0284bd5a7aa34d85d7dbc87b3117037d415d24b931066cec8b15143010 +size 6414 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_ShortHair.json.meta b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_ShortHair.json.meta index 7e5065aa..e3dd10d3 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_ShortHair.json.meta +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_ShortHair.json.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_ShortHair.json + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Skirt.json b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Skirt.json index 2c9415cc..0362d9ca 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Skirt.json +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Skirt.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9082a88f302870cd33e34319af2daad3d0f78ff77a30f007e6cc475dba89ed33 -size 5101 +oid sha256:ce17b1e7c8ec0e0a7e64828384d05c13da8efc0e7abdbb9f0bcb08c8eea2eb87 +size 6508 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Skirt.json.meta b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Skirt.json.meta index 67d7483f..e2095825 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Skirt.json.meta +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Skirt.json.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Skirt.json + uploadId: 756593 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 00000000..4a608d31 --- /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 00000000..87c02083 --- /dev/null +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSkirt.json.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 95115815f2f656045acda9f116a05915 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSkirt.json + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSpring.json b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSpring.json index b01a96e8..a6ca0c60 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSpring.json +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSpring.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e476689a1a4857eb5466e7c82f9e502601aab545ecd3b646caf49dc68f21c50 -size 6102 +oid sha256:6ac65e79b165e423c680750ec4a5b3cd30b77b4755dc4b9e378823e17ee6149a +size 6152 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSpring.json.meta b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSpring.json.meta index 68b796c5..8a13529c 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSpring.json.meta +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSpring.json.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSpring.json + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Tail.json b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Tail.json index c472494e..dd624ba2 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Tail.json +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Tail.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8ed1e9b4d1f4d482521d762c3dd12673caeaa3751ca310205b8f0ce4cbb93d5 -size 4974 +oid sha256:84399b8b65a155eadda37d373a27d89e268dfd987dbdb8f4cef21a194cf39dcf +size 6343 diff --git a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Tail.json.meta b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Tail.json.meta index 157dcd0a..f043e278 100644 --- a/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Tail.json.meta +++ b/Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Tail.json.meta @@ -5,3 +5,10 @@ TextScriptImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Tail.json + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CheckSliderSerializeData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CheckSliderSerializeData.cs.meta index 5409c2cc..b34b1598 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CheckSliderSerializeData.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CheckSliderSerializeData.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/CheckSliderSerializeData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothBehaviour.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothBehaviour.cs index 4982c975..13c645cc 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothBehaviour.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothBehaviour.cs @@ -19,5 +19,11 @@ namespace MagicaCloth2 { return 0; } + + /// + /// Gizmo display state. + /// + public bool IsGizmoVisible { get; set; } + protected virtual void OnDrawGizmos() => IsGizmoVisible = true; } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothBehaviour.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothBehaviour.cs.meta index 2e8a2772..ce3d5044 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothBehaviour.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothBehaviour.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothBehaviour.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothForceMode.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothForceMode.cs.meta index 3f6669b0..73f902d6 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothForceMode.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothForceMode.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothForceMode.cs + uploadId: 756593 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 00000000..7e3e4ab4 --- /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/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs.meta new file mode 100644 index 00000000..218507a6 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 87cb8cdfb6686334d904a1e0c0536944 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothInitSerializeData.cs + uploadId: 756593 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 00000000..f32a33a7 --- /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 00000000..bcdb8c16 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothMeshWriteMode.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: c89429b06b0fde045af1104d0fe4d6b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothMeshWriteMode.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothNormalAxis.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothNormalAxis.cs.meta index 0774aafe..a83f4acd 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothNormalAxis.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothNormalAxis.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothNormalAxis.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothParameters.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothParameters.cs index 680f8b72..90ac7c2f 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothParameters.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothParameters.cs @@ -24,7 +24,7 @@ namespace MagicaCloth2 /// /// 重力方向(ワールド空間) /// - public float3 gravityDirection; + public float3 worldGravityDirection; /// /// 初期姿勢での重力の減衰率(0.0 ~ 1.0) @@ -63,6 +63,9 @@ namespace MagicaCloth2 public float rotationalInterpolation; public float rootRotation; + // カリング(Culling) + public CullingSettings.CullingParams culling; + // 慣性制約(Inertia) public InertiaConstraint.InertiaConstraintParams inertiaConstraint; diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothParameters.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothParameters.cs.meta index e69e8ba0..c42e7743 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothParameters.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothParameters.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothParameters.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcess.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcess.cs index aee4aa12..df7e205f 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcess.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcess.cs @@ -9,6 +9,7 @@ using Unity.Burst; using Unity.Collections; using Unity.Jobs; using Unity.Mathematics; +using Unity.Profiling; using UnityEngine; namespace MagicaCloth2 @@ -19,107 +20,253 @@ namespace MagicaCloth2 public partial class ClothProcess { //========================================================================================= + static readonly ProfilerMarker initClothProfiler = new ProfilerMarker("InitCloth"); + /// - /// 初期化(★必ずアニメーションの実行前に行う) + /// 初期化(必ずアニメーションの実行前に行う) /// internal void Init() { Debug.Assert(cloth); - Develop.DebugLog($"Init start :{cloth.name}"); + Develop.DebugLog($"Init start [{cloth.name}]"); + initClothProfiler.Begin(); + result.SetSuccess(); + InitDataResult.Clear(); - // すでに初期化済みならスキップ - if (IsState(State_InitComplete)) + try { - return; - } - - // すでに破棄されている場合はエラーとする。再初期化はできない - if (isDestory) - { - Develop.LogError($"Already destroyed components cannot be reinitialized."); - return; - } - - SetState(State_Valid, false); - result.SetProcess(); - var sdata = cloth.SerializeData; - - // クロスを生成するための最低限の情報が揃っているかチェックする - if (sdata.IsValid() == false) - { - //result.SetResult(Define.Result.Empty); - result.SetResult(sdata.VerificationResult); - return; - } - - // 基本情報 - clothType = sdata.clothType; - reductionSettings = sdata.reductionSetting; - parameters = sdata.GetClothParameters(); - - // 初期トランスフォーム状態 - clothTransformRecord = new TransformRecord(cloth.ClothTransform); - - // 法線調整用トランスフォーム - normalAdjustmentTransformRecord = new TransformRecord( - sdata.normalAlignmentSetting.adjustmentTransform ? - sdata.normalAlignmentSetting.adjustmentTransform : - cloth.ClothTransform); - - // レンダラーとセットアップ情報の初期化 - if (clothType == ClothType.MeshCloth) - { - // MeshCloth - // 必要なレンダラーを登録する - foreach (var ren in sdata.sourceRenderers) + // すでに破棄されている場合はエラーとする。再初期化はできない + if (isDestory) { - if (ren) + Develop.LogError($"Already destroyed components cannot be reinitialized."); + throw new OperationCanceledException(); + } + + // すでに初期化済みならスキップ + if (IsState(State_InitComplete)) + { + throw new OperationCanceledException(); + } + + var sdata = cloth.SerializeData; + var sdata2 = cloth.GetSerializeData2(); + + SetState(State_Valid, false); + + // アニメーション用プロパティ初期化 + cloth.InitAnimationProperty(); + + // クロスを生成するための最低限の情報が揃っているかチェックする + if (sdata.IsValid() == false) + { + result.SetResult(sdata.VerificationResult); + throw new OperationCanceledException(); + } + + // クロスの状態検証 + var statusResult = GenerateStatusCheck(); + result.Merge(statusResult); + if (statusResult.IsError()) + { + throw new MagicaClothProcessingException(); + } + + SetState(State_InitComplete, true); + + // PreBuildデータの利用と検証 + bool usePreBuildData = sdata2.preBuildData.UsePreBuild(); + SharePreBuildData sharePreBuildData = null; + if (usePreBuildData) + { + SetState(State_UsePreBuild, true); + var r = sdata2.preBuildData.DataValidate(); + if (r.IsFaild()) { - int handle = AddRenderer(ren); - if (handle == 0) + result.Merge(r); + throw new OperationCanceledException(); + } + + sharePreBuildData = sdata2.preBuildData.GetSharePreBuildData(); + } + + // 初期化データの利用と検証 + bool useInitData = false; +#if !MC2_DISABLE_INITDATA + if (usePreBuildData == false && sdata2.initData != null && sdata2.initData.HasData()) + { + // 初期化データ検証 + InitDataResult = sdata2.initData.DataValidate(this); + useInitData = InitDataResult.IsSuccess(); + if (InitDataResult.IsSuccess()) + Develop.DebugLog($"InitData validation [{cloth.name}] : {InitDataResult.GetResultString()}"); + else + { + Develop.DebugLogWarning($"InitData validation [{cloth.name}] : {InitDataResult.GetResultString()}"); + Develop.DebugLogWarning("Do not use InitData."); + } + } +#endif + + // 基本情報 + clothType = sdata.clothType; + reductionSettings = sdata.reductionSetting; + parameters = sdata.GetClothParameters(); + + // 初期トランスフォーム状態 + clothTransformRecord = new TransformRecord(cloth.ClothTransform, read: useInitData == false); + if (usePreBuildData) + { + // Pre-Buildでは編集時スケールを復元する + clothTransformRecord.scale = sharePreBuildData.buildScale; + } + if (useInitData) + { + // initDataから復元 + sdata2.initData.clothTransformRecord.Deserialize(clothTransformRecord); + } + + // 法線調整用トランスフォーム + normalAdjustmentTransformRecord = new TransformRecord( + sdata.normalAlignmentSetting.adjustmentTransform ? + sdata.normalAlignmentSetting.adjustmentTransform : + cloth.ClothTransform, read: useInitData == false); + if (useInitData) + { + // initDataから復元 + sdata2.initData.normalAdjustmentTransformRecord.Deserialize(normalAdjustmentTransformRecord); + } + + // PreBuildデータの登録 + PreBuildManager.ShareDeserializationData sharePreBuildDeserializeData = usePreBuildData ? MagicaManager.PreBuild.RegisterPreBuildData(sharePreBuildData, true) : null; + UniquePreBuildData uniquePreBuildData = usePreBuildData ? sdata2.preBuildData.uniquePreBuildData : null; + + // レンダラーとセットアップ情報の初期化 + // なおセットアップ情報はVirtualMeshを生成するためのものなのでベイク構築時は不要 + if (clothType == ClothType.MeshCloth) + { + // MeshCloth + // 必要なレンダラーを登録する + for (int i = 0; i < sdata.sourceRenderers.Count; i++) + { + var ren = sdata.sourceRenderers[i]; + if (ren) { - result.SetError(Define.Result.ClothInit_FailedAddRenderer); - return; - } - var rdata = MagicaManager.Render.GetRendererData(handle); - result.Merge(rdata.Result); - if (rdata.Result.IsFaild()) - { - return; + // PreBuildではセットアップ情報を復元する + RenderSetupData setup = null; + RenderSetupData.UniqueSerializationData uniquePreBuildSetupData = null; + if (usePreBuildData) + { + setup = sharePreBuildDeserializeData.renderSetupDataList[i]; + uniquePreBuildSetupData = uniquePreBuildData.renderSetupDataList[i]; + + if (setup.result.IsFaild()) + { + setup.Dispose(); + result.SetError(Define.Result.PreBuild_SetupDeserializationError); + throw new OperationCanceledException(); + } + } + + // 初期化データの参照 + RenderSetupSerializeData initSetupData = useInitData ? sdata2.initData.clothSetupDataList[i] : null; + + int handle = AddRenderer(ren, setup, uniquePreBuildSetupData, initSetupData); + if (handle == 0) + { + result.SetError(Define.Result.ClothInit_FailedAddRenderer); + throw new OperationCanceledException(); + } + var rdata = MagicaManager.Render.GetRendererData(handle); + result.Merge(rdata.Result); + if (rdata.Result.IsFaild()) + { + throw new OperationCanceledException(); + } } } } + else if (clothType == ClothType.BoneCloth && usePreBuildData == false) + { + // BoneCloth + CreateBoneRenderSetupData( + useInitData ? sdata2.initData : null, + clothType, sdata.rootBones, null, sdata.connectionMode + ); + } + else if (clothType == ClothType.BoneSpring && usePreBuildData == false) + { + // BoneSpring + // BoneSpringではLine接続のみ + CreateBoneRenderSetupData( + useInitData ? sdata2.initData : null, + clothType, sdata.rootBones, sdata.colliderCollisionConstraint.collisionBones, RenderSetupData.BoneConnectionMode.Line + ); + } + + // カスタムスキニングのボーン情報 + int bcnt = sdata.customSkinningSetting.skinningBones.Count; + for (int i = 0; i < bcnt; i++) + { + var tr = new TransformRecord(sdata.customSkinningSetting.skinningBones[i], read: useInitData == false); + if (useInitData) + { + // initDataから復元 + sdata2.initData.customSkinningBoneRecords[i].Deserialize(tr); + } + customSkinningBoneRecords.Add(tr); + } + + // 同期コンポーネントの解決と作業バッファへの登録 + var syncPartnerCloth = cloth.SyncPartnerCloth; + if (syncPartnerCloth) + { + // partner + MagicaManager.Team.comp2SyncPartnerCompMap.Add(cloth.GetInstanceID(), syncPartnerCloth.GetInstanceID()); + + // top + // デッドロック対策 + var c = syncPartnerCloth; + while (c) + { + if (c == cloth) + c = null; + else if (c.SyncPartnerCloth) + c = c.SyncPartnerCloth; + else + break; + } + Debug.Assert(c); + SyncTopCloth = c; + MagicaManager.Team.comp2SyncTopCompMap.Add(cloth.GetInstanceID(), SyncTopCloth.GetInstanceID()); + } + + result.SetSuccess(); + SetState(State_Valid, true); + SetState(State_InitSuccess, true); + SetState(State_Verification, true); + + // この時点でクロスコンポーネントが非アクティブの場合は破棄監視リストに登録する + if (cloth.isActiveAndEnabled == false) + MagicaManager.Team.AddMonitoringProcess(this); } - else if (clothType == ClothType.BoneCloth) + catch (OperationCanceledException) { - // BoneCloth - // 必要なボーンを登録する - AddBoneCloth(clothType, sdata.rootBones, null, sdata.connectionMode); } - else if (clothType == ClothType.BoneSpring) + catch (MagicaClothProcessingException) { - // BoneSpring - // 必要なボーンを登録する - // BoneSpringではLine接続のみ - AddBoneCloth(clothType, sdata.rootBones, sdata.colliderCollisionConstraint.collisionBones, RenderSetupData.BoneConnectionMode.Line); } - - // カスタムスキニングのボーン情報 - int bcnt = sdata.customSkinningSetting.skinningBones.Count; - for (int i = 0; i < bcnt; i++) + catch (Exception exception) { - customSkinningBoneRecords.Add(new TransformRecord(sdata.customSkinningSetting.skinningBones[i])); + Debug.LogException(exception); + result.SetError(Define.Result.ClothProcess_Exception); } - result.SetSuccess(); - SetState(State_Valid, true); - SetState(State_InitComplete, true); + initClothProfiler.End(); - // この時点でクロスコンポーネントが非アクティブの場合は破棄監視リストに登録する - if (cloth.isActiveAndEnabled == false) - MagicaManager.Team.AddMonitoringProcess(this); - - Develop.DebugLog($"Init finish :{cloth.name}"); + if (result.IsSuccess()) + Develop.DebugLog($"Cloth Initialize Success! [{cloth.name}]"); + else + Develop.DebugLogError($"Cloth Initialize failure! [{cloth.name}] : {result.GetResultString()}"); } /// @@ -128,7 +275,12 @@ namespace MagicaCloth2 /// /// /// レンダー情報ハンドル - int AddRenderer(Renderer ren) + int AddRenderer( + Renderer ren, + RenderSetupData referenceSetupData, + RenderSetupData.UniqueSerializationData referenceUniqueSetupData, + RenderSetupSerializeData referenceInitSetupData + ) { if (ren == null) return 0; @@ -139,7 +291,7 @@ namespace MagicaCloth2 if (renderHandleList.Contains(handle) == false) { // レンダラーの利用開始 - handle = MagicaManager.Render.AddRenderer(ren); + handle = MagicaManager.Render.AddRenderer(ren, referenceSetupData, referenceUniqueSetupData, referenceInitSetupData); if (handle != 0) { lock (lockObject) @@ -159,10 +311,17 @@ namespace MagicaCloth2 /// /// /// - void AddBoneCloth(ClothType ctype, List rootTransforms, List collisionBones, RenderSetupData.BoneConnectionMode connectionMode) + void CreateBoneRenderSetupData( + ClothInitSerializeData initData, + ClothType ctype, + List rootTransforms, + List collisionBones, + RenderSetupData.BoneConnectionMode connectionMode + ) { // BoneCloth用のセットアップデータ作成 boneClothSetupData = new RenderSetupData( + initData != null ? initData.clothSetupDataList[0] : null, ctype == ClothType.BoneSpring ? RenderSetupData.SetupType.BoneSpring : RenderSetupData.SetupType.BoneCloth, clothTransformRecord.transform, rootTransforms, @@ -172,19 +331,6 @@ namespace MagicaCloth2 ); } -#if false - /// - /// セレクションデータハッシュとレンダラーハッシュを1つに結合したものを返す - /// - /// - /// - /// - int GetSelectionAndRenderMixHash(int selectionHash, int renderHash) - { - return selectionHash + renderHash; - } -#endif - /// /// 有効化 /// @@ -193,20 +339,8 @@ namespace MagicaCloth2 if (MagicaManager.IsPlaying() == false) return; - // 有効化 - SetState(State_Enable, true); - - // チーム有効化 - MagicaManager.Team.SetEnable(TeamId, true); - - // レンダラー有効化 - if (renderHandleList != null) - { - foreach (int renderHandle in renderHandleList) - { - MagicaManager.Render.StartUse(this, renderHandle); - } - } + SetState(State_Component, true); + UpdateUse(); } /// @@ -217,18 +351,32 @@ namespace MagicaCloth2 if (MagicaManager.IsPlaying() == false) return; - // 無効化 - SetState(State_Enable, false); + SetState(State_Component, false); + UpdateUse(); + } - // チーム無効化 - MagicaManager.Team.SetEnable(TeamId, false); + internal void UpdateUse() + { + // 有効状態判定 + bool now = IsState(State_Component) && IsState(State_Verification); - // レンダラー無効化 - if (renderHandleList != null) + // 切り替え { - foreach (int renderHandle in renderHandleList) + SetState(State_Enable, now); + + // チーム + MagicaManager.Team.SetEnable(TeamId, now); + + // レンダラー + if (renderHandleList != null) { - MagicaManager.Render.EndUse(this, renderHandle); + foreach (int renderHandle in renderHandleList) + { + if (now) + MagicaManager.Render.StartUse(this, renderHandle); + else + MagicaManager.Render.EndUse(this, renderHandle); + } } } } @@ -243,10 +391,11 @@ namespace MagicaCloth2 cloth.serializeData2.DataValidate(); // パラメータ変更(実行時のみ) - if (Application.isPlaying) + if (MagicaManager.IsPlaying()) { // ここでは変更フラグのみ立てる - SetState(State_ParameterDirty, true); + //SetState(State_ParameterDirty, true); + MagicaManager.Team.parameterDirtyList.Add(this); } } @@ -254,26 +403,25 @@ namespace MagicaCloth2 /// /// 構築を開始し完了後に自動実行する /// - internal bool StartBuild() + internal bool StartRuntimeBuild() { // ビルド開始 // -コンポーネントが有効であること // -初期化済みであること // -ビルドがまだ実行されていないこと - if (IsValid() && IsState(State_InitComplete) && IsState(State_Build) == false) + // -ベイクデータを利用しないこと + if (IsValid() && IsState(State_InitSuccess) && IsState(State_Build) == false && IsState(State_UsePreBuild) == false) { result.SetProcess(); SetState(State_Build, true); - var _ = BuildAsync(cts.Token); + var _ = RuntimeBuildAsync(cts.Token); return true; } else { - Develop.LogError($"Cloth build failure!: {cloth.name}"); - - // ビルド完了イベント - cloth?.OnBuildComplete?.Invoke(false); - + if (result.IsError() == false) + result.SetError(Define.Result.CreateCloth_CanNotStart); + Develop.LogError($"Cloth runtime build failure! [{cloth.name}] : {result.GetResultString()}"); return false; } } @@ -284,25 +432,42 @@ namespace MagicaCloth2 /// internal bool AutoBuild() { - if (IsState(State_DisableAutoBuild) == false) - return StartBuild(); + bool ret; + bool buildComplate = true; + + if (IsState(State_DisableAutoBuild)) + { + ret = false; + } else - return false; + { + if (IsState(State_UsePreBuild)) + ret = PreBuildDataConstruction(); + else + { + ret = StartRuntimeBuild(); + if (ret) + buildComplate = false; // OnBuildCompleteはランタイム構築後に呼ばれる + } + } + + // ビルド完了イベント + if (buildComplate) + cloth?.OnBuildComplete?.Invoke(cloth, ret); + + return ret; } /// - /// 構築タスク + /// 実行時構築タスク /// /// /// - async Task BuildAsync(CancellationToken ct) + async Task RuntimeBuildAsync(CancellationToken ct) { isBuild = true; Develop.DebugLog($"Build start : {Name}"); result.SetProcess(); -#if MC2_DEBUG - var span = new TimeSpan("Build Cloth"); -#endif // 作成されたレンダラー情報 var renderMeshInfos = new List(); @@ -316,21 +481,54 @@ namespace MagicaCloth2 var sdata = cloth.SerializeData; var sdata2 = cloth.GetSerializeData2(); + // 少し時間を開けてから処理を開始する + await Task.Delay(5); + ct.ThrowIfCancellationRequested(); + // 同期対象がいる場合は相手の一時停止カウンターを加算する - if (cloth.SyncCloth) + if (cloth.SyncPartnerCloth) { - var sync = cloth.SyncCloth; + var sync = cloth.SyncPartnerCloth; while (sync != cloth && sync != null) { sync.Process.IncrementSuspendCounter(); - sync = sync.SyncCloth; + sync = sync.SyncPartnerCloth; } } - // ペイントマップデータの作成(これはメインスレッドでのみ作成可能) + // 頂点属性配列の利用確認 + bool useManualVertexAttribute = false; + if (sdata.clothType == ClothType.MeshCloth && sdata2.vertexAttributeList != null && sdata2.vertexAttributeList.Count > 0) + { + // 頂点属性配列の検証 + if (sdata2.vertexAttributeList.Count != renderHandleList.Count) + { + result.SetError(Define.Result.CreateCloth_VertexAttributeListCountMismatch); + throw new MagicaClothProcessingException(); + } + for (int i = 0; i < renderHandleList.Count; i++) + { + var vertexAttributeArray = sdata2.vertexAttributeList[i]; + if (vertexAttributeArray == null) + { + result.SetError(Define.Result.CreateCloth_VertexAttributeListIsNull); + throw new MagicaClothProcessingException(); + } + int renderHandle = renderHandleList[i]; + var renderData = MagicaManager.Render.GetRendererData(renderHandle); + if (renderData.setupData.vertexCount != vertexAttributeArray.Length) + { + result.SetError(Define.Result.CreateCloth_VertexAttributeListDataMismatch); + throw new MagicaClothProcessingException(); + } + } + useManualVertexAttribute = true; + } + + // ペイントマップデータの利用確認と作成(これはメインスレッドでのみ作成可能) bool usePaintMap = false; var paintMapDataList = new List(); - if (sdata.clothType == ClothType.MeshCloth && sdata.paintMode != ClothSerializeData.PaintMode.Manual) + if (sdata.clothType == ClothType.MeshCloth && sdata.paintMode != ClothSerializeData.PaintMode.Manual && useManualVertexAttribute == false) { var ret = GeneratePaintMapDataList(paintMapDataList); Develop.DebugLog($"Generate paint map data list. {ret.GetResultString()}"); @@ -348,8 +546,8 @@ namespace MagicaCloth2 } // セレクションデータ - // ペイントマップ指定の場合は空で初期化 - SelectionData selectionData = usePaintMap ? new SelectionData() : sdata2.selectionData.Clone(); + // ペイントマップ指定もしくは頂点属性指定の場合は空で初期化 + SelectionData selectionData = (usePaintMap || useManualVertexAttribute) ? new SelectionData() : sdata2.selectionData.Clone(); // BoneCloth/BoneSpringでシリアライズ2にTransformと属性辞書がある場合はIDと属性の辞書に変換(スレッドではアクセスできないため) Dictionary boneAttributeDict = null; @@ -389,13 +587,8 @@ namespace MagicaCloth2 } } - // セレクションデータ - // ペイントマップ指定の場合は空で初期化 - //SelectionData selectionData = usePaintMap ? new SelectionData() : sdata2.selectionData; - // セレクションデータの有無 bool isValidSelection = selectionData?.IsValid() ?? false; - //Develop.Log($"セレクションデータの有無:{isValidSelection}"); // MeshCloth/BoneClothで処理が一部異なる if (clothType == ClothType.MeshCloth) @@ -421,7 +614,7 @@ namespace MagicaCloth2 renderMesh.result.SetProcess(); // import ------------------------------------------------- - renderMesh.ImportFrom(renderData); + renderMesh.ImportFrom(renderData, sdata.GetUvChannel()); if (renderMesh.IsError) { result.Merge(renderMesh.result); @@ -430,8 +623,25 @@ namespace MagicaCloth2 Develop.DebugLog($"(IMPORT) {renderMesh}"); // selection ---------------------------------------------- - // MeshClothでペイントテクスチャ指定の場合はセレクションデータを生成する SelectionData renderSelectionData = selectionData; + + // MeshClothで頂点属性指定がある場合はセレクションデータを生成する + if (useManualVertexAttribute) + { + // セレクションデータ生成 + var ret = GenerateSelectionDataFromVertexAttributeData(clothTransformRecord, renderMesh, sdata2.vertexAttributeList[i], out renderSelectionData); + Develop.DebugLog($"Generate selection from vertex attribute data. {ret.GetResultString()}"); + if (ret.IsError()) + { + result.Merge(ret); + throw new MagicaClothProcessingException(); + } + + // セレクションデータ結合 + selectionData.Merge(renderSelectionData); + } + + // MeshClothでペイントテクスチャ指定の場合はセレクションデータを生成する if (usePaintMap) { // renderMeshからセレクションデータ生成 @@ -478,7 +688,10 @@ namespace MagicaCloth2 var info = new RenderMeshInfo(); //info.mixHash = mixHash; info.renderHandle = renderHandle; - info.renderMesh = renderMesh; + info.renderMeshContainer = new VirtualMeshContainer(renderMesh); + //info.renderMeshPositionAndNormalChunk = renderData.renderMeshPositionAndNormalChunk; + //info.renderMeshTangentChunk = renderData.renderMeshTangentChunk; + info.renderDataWorkIndex = renderData.renderDataWorkIndex; renderMesh = null; renderMeshInfos.Add(info); } @@ -488,7 +701,7 @@ namespace MagicaCloth2 { // ■BoneCloth // import - proxyMesh.ImportFrom(boneClothSetupData); + proxyMesh.ImportFrom(boneClothSetupData, 0); if (proxyMesh.IsError) { result.Merge(proxyMesh.result); @@ -609,16 +822,6 @@ namespace MagicaCloth2 throw new MagicaClothProcessingException(); } - //-------------------------------------------------------------------- -#if false - // pitch/yaw個別制限はv1.0では実装しないので一旦停止 - // 角度制限計算用回転を作成 - ct.ThrowIfCancellationRequested(); - proxyMesh.CreateAngleCalcLocalRotation(normalCalculation, normalCalculationCenter); - if (proxyMesh.IsError) - throw new InvalidOperationException(); -#endif - //-------------------------------------------------------------------- // finish ct.ThrowIfCancellationRequested(); @@ -637,7 +840,8 @@ namespace MagicaCloth2 foreach (var info in renderMeshInfos) { ct.ThrowIfCancellationRequested(); - var vmesh = info.renderMesh; + var cmesh = info.renderMeshContainer; + var vmesh = cmesh.shareVirtualMesh; vmesh.Mapping(proxyMesh); if (vmesh.IsError) { @@ -674,7 +878,7 @@ namespace MagicaCloth2 ct.ThrowIfCancellationRequested(); if (cloth == null) throw new OperationCanceledException(); // キャンセル扱いにする - var syncCloth = cloth.SyncCloth; + var syncCloth = cloth.SyncPartnerCloth; if (syncCloth != null) { int timeOutCount = 100; @@ -690,6 +894,7 @@ namespace MagicaCloth2 Develop.LogWarning($"Sync timeout! Is there a deadlock between synchronous cloths?"); } } + Develop.DebugLog($"Sync complete : {Name}"); // ■メインスレッド ct.ThrowIfCancellationRequested(); @@ -707,11 +912,7 @@ namespace MagicaCloth2 } // パラメータ変更フラグ - SetState(State_ParameterDirty, true); - - // 自チームと同期チームのデータ(コピー) - //var teamData = MagicaManager.Team.GetTeamData(TeamId); - //var syncTeamData = syncCloth != null ? MagicaManager.Team.GetTeamData(syncCloth.Process.TeamId) : default; + //SetState(State_ParameterDirty, true); // ■スレッド ct.ThrowIfCancellationRequested(); @@ -747,12 +948,6 @@ namespace MagicaCloth2 throw new MagicaClothProcessingException(); } - // セルフコリジョン2(SelfCollision2) - //ct.ThrowIfCancellationRequested(); - //self2ConstraintData = SelfCollisionConstraint2.CreateData(TeamId, teamData, ProxyMesh, parameters, syncCloth?.Process?.TeamId ?? 0, syncTeamData, syncCloth?.Process?.ProxyMesh); - //if (self2ConstraintData != null && self2ConstraintData.result.IsError()) - // result = self2ConstraintData.result; - if (result.IsError()) throw new MagicaClothProcessingException(); } @@ -782,7 +977,7 @@ namespace MagicaCloth2 lock (lockObject) { // ProxyMesh登録 - ProxyMesh = proxyMesh; + ProxyMeshContainer = new VirtualMeshContainer(proxyMesh); proxyMesh = null; // チーム登録 @@ -793,8 +988,11 @@ namespace MagicaCloth2 throw new MagicaClothProcessingException(); } + // パラメータ変更フラグ + MagicaManager.Team.parameterDirtyList.Add(this); + // プロキシメッシュ登録 - MagicaManager.VMesh.RegisterProxyMesh(TeamId, ProxyMesh); + MagicaManager.VMesh.RegisterProxyMesh(TeamId, ProxyMeshContainer); MagicaManager.Simulation.RegisterProxyMesh(this); // コライダー登録 @@ -812,23 +1010,20 @@ namespace MagicaCloth2 { foreach (var info in renderMeshInfos) { - if (info.renderMesh.IsError == false && info.renderMesh.IsMapping) + var renderMesh = info.renderMeshContainer.shareVirtualMesh; + + if (renderMesh.IsError == false && renderMesh.IsMapping) { // マッピングメッシュのデータ検証 // ここまでの時間経過でRendererが消滅しているなどの状況があり得るため - if (info.renderMesh.IsValid()) + if (renderMesh.IsValid()) { // MappingMesh登録 - info.mappingChunk = MagicaManager.VMesh.RegisterMappingMesh(TeamId, info.renderMesh); - - // 完了 - info.renderMesh.result.SetSuccess(); - - // コンポーネントがすでに有効状態ならば利用開始 - if (IsState(State_Enable)) - { - MagicaManager.Render.StartUse(this, info.renderHandle); - } + info.mappingChunk = MagicaManager.VMesh.RegisterMappingMesh( + TeamId, + info.renderMeshContainer, + info.renderDataWorkIndex + ); } } } @@ -844,13 +1039,13 @@ namespace MagicaCloth2 ct.ThrowIfCancellationRequested(); // チームの有効状態の設定 - MagicaManager.Team.SetEnable(TeamId, IsState(State_Enable)); + UpdateUse(); - // 初期化完了 + // ビルド完了 result.SetSuccess(); SetState(State_Running, true); - Develop.DebugLog($"Build Complate : {Name}"); + Develop.DebugLog($"Build Complate : {Name}, TeamId:{TeamId}"); } catch (MagicaClothProcessingException) { @@ -874,26 +1069,23 @@ namespace MagicaCloth2 // この時点でデータが存在する場合は失敗しているので破棄する foreach (var info in renderMeshInfos) { - info?.renderMesh?.Dispose(); + info?.renderMeshContainer?.Dispose(); } proxyMesh?.Dispose(); // 同期対象がいる場合は相手の一時停止カウンターを減算する - if (cloth != null && cloth.SyncCloth) + if (cloth != null && cloth.SyncPartnerCloth) { - var sync = cloth.SyncCloth; + var sync = cloth.SyncPartnerCloth; while (sync != cloth && sync != null) { sync.Process.DecrementSuspendCounter(); - sync = sync.SyncCloth; + sync = sync.SyncPartnerCloth; } } // ビルド完了 isBuild = false; -#if MC2_DEBUG - span.DebugLog(); -#endif // この時点でコンポーネントが削除されている場合は破棄する if (isDestory) @@ -903,8 +1095,11 @@ namespace MagicaCloth2 } else if (cloth != null) { + if (result.IsFaild()) + Develop.LogError($"Cloth runtime build failure! [{cloth.name}] : {result.GetResultString()}"); + // ビルド完了イベント - cloth.OnBuildComplete?.Invoke(result.IsSuccess()); + cloth.OnBuildComplete?.Invoke(cloth, result.IsSuccess()); } } } @@ -1112,22 +1307,247 @@ namespace MagicaCloth2 return result; } - - //========================================================================================= - // 単体マッピング - // メモ - // ・レンダラーの情報はすべてスレッドローカルで作成して処理する - // ・成功した場合は最後に書き戻す - - //========================================================================================= /// - /// コライダーの現在のローカルインデックスを返す + /// 頂点属性データ配列からセレクションデータを構築する /// - /// - /// (-1)存在しない - internal int GetColliderIndex(ColliderComponent col) + /// + /// + /// + /// + /// + public ResultCode GenerateSelectionDataFromVertexAttributeData( + TransformRecord clothTransformRecord, VirtualMesh renderMesh, VertexAttribute[] vertexAttributeArray, out SelectionData selectionData + ) { - return colliderList.IndexOf(col); + ResultCode result = new ResultCode(); + result.SetProcess(); + selectionData = new SelectionData(); + + try + { + // セレクションデータバッファ作成 + int vcnt = renderMesh.VertexCount; + using var positionList = new NativeArray(vcnt, Allocator.TempJob); + //using var attributeList = new NativeArray(vcnt, Allocator.TempJob); + + // 頂点座標をクロス空間に変換する + var toM = MathUtility.Transform(renderMesh.initLocalToWorld, clothTransformRecord.worldToLocalMatrix); + JobUtility.TransformPositionRun(renderMesh.localPositions.GetNativeArray(), positionList, vcnt, toM); + + // セレクションデータ設定 + selectionData.positions = positionList.ToArray(); + selectionData.attributes = vertexAttributeArray; // 参照のみ + // 最大距離はプロキシメッシュの座標空間に変換する + selectionData.maxConnectionDistance = MathUtility.TransformDistance(renderMesh.maxVertexDistance.Value, toM); + //Develop.DebugLog($"GenerateSelectionDataFromPaintMap. maxConnectionDistance:{selectionData.maxConnectionDistance}, renderMesh.maxVertexDistance:{renderMesh.maxVertexDistance.Value}"); + selectionData.userEdit = true; + + result.SetSuccess(); + } + catch (MagicaClothProcessingException) + { + if (result.IsNone()) result.SetError(Define.Result.CreateCloth_InvalidVertexAttributeData); + result.DebugLog(); + } + catch (Exception e) + { + Debug.LogException(e); + result.SetError(Define.Result.CreateCloth_InvalidVertexAttributeData); + } + + return result; + } + + //========================================================================================= + static readonly ProfilerMarker preBuildProfiler = new ProfilerMarker("ClothProcess.PreBuild"); + static readonly ProfilerMarker preBuildDeserializationProfiler = new ProfilerMarker("ClothProcess.PreBuild.Deserialization"); + static readonly ProfilerMarker preBuildRegistrationProfiler = new ProfilerMarker("ClothProcess.PreBuild.Registration"); + + /// + /// PreBuildデータによる即時構築 + /// + /// + internal bool PreBuildDataConstruction() + { + if (IsState(State_UsePreBuild) == false) + return false; + if (IsState(State_InitSuccess) == false) + return false; + + // 構築開始 + Develop.DebugLog($"Pre-Build start [{cloth.name}]"); + preBuildProfiler.Begin(); + + result.SetProcess(); + var sdata = cloth.SerializeData; + var sdata2 = cloth.GetSerializeData2(); + + VirtualMeshContainer proxyMeshContainer = null; + List renderMeshContainerList = new List(); + + try + { + // 固有部分データ + var uniquePreBuildData = sdata2.preBuildData.uniquePreBuildData; + + // 共有部分データ + var preBuildDeserializeData = MagicaManager.PreBuild.GetPreBuildData(sdata2.preBuildData.GetSharePreBuildData()); + + try + { + preBuildDeserializationProfiler.Begin(); + + // ProxyMesh復元 + proxyMeshContainer = new VirtualMeshContainer(preBuildDeserializeData.proxyMesh); + if (proxyMeshContainer.shareVirtualMesh.IsError) + { + result.Merge(proxyMeshContainer.shareVirtualMesh.result); + throw new MagicaClothProcessingException(); + } + proxyMeshContainer.uniqueData = uniquePreBuildData.proxyMesh; + + // RenderMesh復元 + for (int i = 0; i < preBuildDeserializeData.renderMeshList.Count; i++) + { + var renderMeshContainer = new VirtualMeshContainer(preBuildDeserializeData.renderMeshList[i]); + renderMeshContainerList.Add(renderMeshContainer); + if (renderMeshContainer.shareVirtualMesh.IsError) + { + result.Merge(renderMeshContainer.shareVirtualMesh.result); + throw new MagicaClothProcessingException(); + } + renderMeshContainer.uniqueData = uniquePreBuildData.renderMeshList[i]; + } + + // 制約データ復元 + inertiaConstraintData = preBuildDeserializeData.inertiaConstraintData; + distanceConstraintData = preBuildDeserializeData.distanceConstraintData; + bendingConstraintData = preBuildDeserializeData.bendingConstraintData; + } + catch + { + throw; + } + finally + { + preBuildDeserializationProfiler.End(); + } + + // パラメータ変更フラグ + //SetState(State_ParameterDirty, true); + + // 登録 + try + { + preBuildRegistrationProfiler.Begin(); + + // ProxyMesh登録 + ProxyMeshContainer = proxyMeshContainer; + proxyMeshContainer = null; + + // チーム登録 + TeamId = MagicaManager.Cloth.AddCloth(this, parameters); + if (TeamId <= 0) + { + result.SetError(Define.Result.ClothProcess_OverflowTeamCount4096); + throw new MagicaClothProcessingException(); + } + + // パラメータ変更フラグ + MagicaManager.Team.parameterDirtyList.Add(this); + + // プロキシメッシュ登録 + MagicaManager.VMesh.RegisterProxyMesh(TeamId, ProxyMeshContainer); + MagicaManager.Simulation.RegisterProxyMesh(this); + + // コライダー登録 + MagicaManager.Collider.Register(this); + + // 制約データ登録 + MagicaManager.Simulation.RegisterConstraint(this); + + // マッピングメッシュ登録 + for (int i = 0; i < renderMeshContainerList.Count; i++) + { + var renderMeshContainer = renderMeshContainerList[i]; + var renderMesh = renderMeshContainer.shareVirtualMesh; + if (renderMesh.IsError == false && renderMesh.IsMapping && renderMesh.IsValid()) + { + renderMeshContainerList[i] = null; + + // レンダーハンドル + int renderHandle = renderHandleList[i]; + var renderData = MagicaManager.Render.GetRendererData(renderHandle); + + // MappingMesh登録 + var mappingChunk = MagicaManager.VMesh.RegisterMappingMesh( + TeamId, + renderMeshContainer, + renderData.renderDataWorkIndex + ); + + // 完了 + renderMesh.result.SetSuccess(); + + // レンダラー情報を登録 + var info = new RenderMeshInfo() + { + renderHandle = renderHandle, + renderMeshContainer = renderMeshContainer, + mappingChunk = mappingChunk, + renderDataWorkIndex = renderData.renderDataWorkIndex + }; + renderMeshInfoList.Add(info); + } + } + + // チームの有効状態の設定 + UpdateUse(); + } + catch + { + throw; + } + finally + { + preBuildRegistrationProfiler.End(); + } + + // ビルド完了 + result.SetSuccess(); + SetState(State_Running, true); + + Develop.DebugLog($"Pre-Build Complate : {Name}, TeamId:{TeamId}"); + } + catch (MagicaClothProcessingException) + { + if (result.IsError() == false) + result.SetError(Define.Result.PreBuild_UnknownError); + result.DebugLog(); + } + catch (Exception e) + { + Debug.LogException(e); + result.SetError(Define.Result.PreBuild_Exception); + } + finally + { + // この時点でデータが存在する場合は失敗しているので破棄する + renderMeshContainerList.ForEach(x => x?.Dispose()); + renderMeshContainerList.Clear(); + proxyMeshContainer?.Dispose(); + + // ビルド完了 + //Develop.DebugLog($"PreBuild Construction Complate.[{cloth.name}] result:{result.GetResultString()}"); + if (result.IsFaild()) + Develop.LogError($"Cloth Pre-Build construction failure! [{cloth.name}] : {result.GetResultString()}"); + else + Develop.DebugLog($"Cloth Pre-Build Success! [{cloth.name}]"); + } + + preBuildProfiler.End(); + + return result.IsSuccess(); } //========================================================================================= @@ -1140,18 +1560,19 @@ namespace MagicaCloth2 // 連動アニメーター更新 if (cullingSettings.cameraCullingMode == CullingSettings.CameraCullingMode.AnimatorLinkage - || cullingSettings.cameraCullingMethod == CullingSettings.CameraCullingMethod.AutomaticRenderer) + || cullingSettings.cameraCullingMethod == CullingSettings.CameraCullingMethod.AutomaticRenderer + || cloth.SerializeData.updateMode == ClothUpdateMode.AnimatorLinkage) { - cullingAnimator = cloth.GetComponentInParent(); + interlockingAnimator = cloth.GetComponentInParent(); } // 連動レンダラー更新 - if (cullingSettings.cameraCullingMethod == CullingSettings.CameraCullingMethod.AutomaticRenderer && cullingAnimator) + if (cullingSettings.cameraCullingMethod == CullingSettings.CameraCullingMethod.AutomaticRenderer && interlockingAnimator) { // ★GetComponentsInChildrenのコストはキャラクタ100体で1msほど。 // ★もしコストが問題となるようならばキャッシュする - cullingAnimatorRenderers.Clear(); - cullingAnimator.GetComponentsInChildren(cullingAnimatorRenderers); + interlockingAnimatorRenderers.Clear(); + interlockingAnimator.GetComponentsInChildren(interlockingAnimatorRenderers); } } @@ -1161,7 +1582,7 @@ namespace MagicaCloth2 internal void UpdateRendererUse() { // 対応するレンダーデータに更新を指示する - renderHandleList.ForEach(handle => MagicaManager.Render.GetRendererData(handle).UpdateUse(null, 0)); + renderHandleList.ForEach(handle => MagicaManager.Render.GetRendererData(handle).UpdateUse(this, 0)); } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcess.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcess.cs.meta index 39b3da10..5ea84a66 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcess.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcess.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcess.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessData.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessData.cs index 6ccb7195..c0e04e64 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessData.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessData.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Threading; using Unity.Collections; +using Unity.Mathematics; using UnityEngine; namespace MagicaCloth2 @@ -16,20 +17,31 @@ namespace MagicaCloth2 { public MagicaCloth cloth { get; internal set; } + /// + /// 同期中の参照クロス。これは同期階層の最上位のクロスを指す + /// + public MagicaCloth SyncTopCloth { get; internal set; } + /// /// 状態フラグ(0 ~ 31) /// public const int State_Valid = 0; public const int State_Enable = 1; - public const int State_ParameterDirty = 2; - public const int State_InitComplete = 3; - public const int State_Build = 4; - public const int State_Running = 5; - public const int State_DisableAutoBuild = 6; - public const int State_CullingInvisible = 7; // チームデータの同フラグのコピー - public const int State_CullingKeep = 8; // チームデータの同フラグのコピー - public const int State_SkipWriting = 9; // 書き込み停止(ストップモーション用) - public const int State_SkipWritingDirty = 10; // 書き込み停止フラグ更新サイン + //public const int State_ParameterDirty = 2; + public const int State_InitSuccess = 3; + public const int State_InitComplete = 4; + public const int State_Build = 5; + public const int State_Running = 6; + public const int State_DisableAutoBuild = 7; + public const int State_CameraCullingInvisible = 8; // チームデータの同フラグのコピー + public const int State_CameraCullingKeep = 9; // チームデータの同フラグのコピー + public const int State_SkipWriting = 10; // 書き込み停止(ストップモーション用) + //public const int State_SkipWritingDirty = 11; // 書き込み停止フラグ更新サイン + public const int State_UsePreBuild = 12; // PreBuildを利用 + public const int State_DistanceCullingInvisible = 13; // チームデータの同フラグのコピー + public const int State_UpdateTangent = 14; // 接線の更新 + public const int State_Component = 15; // コンポーネントの有効状態 + public const int State_Verification = 16; // 検証結果による有効状態 /// /// 現在の状態 @@ -45,7 +57,7 @@ namespace MagicaCloth2 /// レンダー情報へのハンドル /// (レンダラーのセットアップデータ) /// - List renderHandleList = new List(); + internal List renderHandleList = new List(); /// /// BoneClothのセットアップデータ @@ -58,8 +70,11 @@ namespace MagicaCloth2 public class RenderMeshInfo { public int renderHandle; - public VirtualMesh renderMesh; + public VirtualMeshContainer renderMeshContainer; public DataChunk mappingChunk; + //public DataChunk renderMeshPositionAndNormalChunk; + //public DataChunk renderMeshTangentChunk; + public int renderDataWorkIndex; } internal List renderMeshInfoList = new List(); @@ -96,6 +111,11 @@ namespace MagicaCloth2 internal ResultCode result; public ResultCode Result => result; + /// + /// 初期化データ参照結果 + /// + public ResultCode InitDataResult { get; internal set; } + /// /// Cloth Type /// @@ -120,18 +140,15 @@ namespace MagicaCloth2 /// /// プロキシメッシュ /// - public VirtualMesh ProxyMesh { get; private set; } = null; + public VirtualMeshContainer ProxyMeshContainer { get; private set; } = null; /// - /// コライダーリスト - /// コライダーが格納されるインデックスは他のデータのインデックスと一致している + /// 登録中のコライダー + /// int2 (メインコライダー・ローカルインデックス, シンメトリーコライダー・ローカルインデックス) + /// メインコライダーのインデックス0はあり得る + /// シンメトリーコライダーのインデックス0はシンメトリーが存在しないことを示す /// - internal List colliderList = new List(); - - /// - /// コライダー配列数 - /// - internal int ColliderCapacity => colliderList.Count; + internal Dictionary colliderDict = new Dictionary(); //========================================================================================= /// @@ -156,14 +173,37 @@ namespace MagicaCloth2 //========================================================================================= /// - /// カリング用対象アニメーター + /// 連動アニメーター + /// ・カリング + /// ・更新モード /// - internal Animator cullingAnimator = null; + internal Animator interlockingAnimator = null; /// /// カリング用アニメーター配下のレンダラーリスト /// - internal List cullingAnimatorRenderers = new List(); + internal List interlockingAnimatorRenderers = new List(); + + /// + /// 現在アンカーとして設定されているTransformのインスタンスID + /// + internal int anchorTransformId = 0; + + /// + /// 現在距離カリングの参照として設定されているオブジェクトのインスタンスID + /// + internal int distanceReferenceObjectId = 0; + + /// + /// コンポーネントの登録TransformIndex + /// tdata.componentTransformIndexのコピー + /// + //internal int componentTransformIndex = 0; + + internal Animator cameraCullingAnimator = null; + internal List cameraCullingRenderers = null; + internal CullingSettings.CameraCullingMode cameraCullingMode; + internal bool cameraCullingOldInvisible = false; //========================================================================================= /// @@ -171,12 +211,12 @@ namespace MagicaCloth2 /// CancellationTokenSource cts = new CancellationTokenSource(); volatile object lockObject = new object(); - volatile object lockState = new object(); + //volatile object lockState = new object(); /// /// 初期化待機カウンター /// - volatile int suspendCounter = 0; + //volatile int suspendCounter = 0; /// /// 破棄フラグ @@ -195,7 +235,7 @@ namespace MagicaCloth2 public BitField32 GetStateFlag() { - lock (lockState) + //lock (lockState) { // copy var state = stateFlag; @@ -205,7 +245,7 @@ namespace MagicaCloth2 public bool IsState(int state) { - lock (lockState) + //lock (lockState) { return stateFlag.IsSet(state); } @@ -213,16 +253,19 @@ namespace MagicaCloth2 public void SetState(int state, bool sw) { - lock (lockState) + //lock (lockState) { stateFlag.SetBits(state, sw); } } public bool IsValid() => IsState(State_Valid); - public bool IsCullingInvisible() => IsState(State_CullingInvisible); - public bool IsCullingKeep() => IsState(State_CullingKeep); + public bool IsRunning() => IsState(State_Running); + public bool IsCameraCullingInvisible() => IsState(State_CameraCullingInvisible); + public bool IsCameraCullingKeep() => IsState(State_CameraCullingKeep); + public bool IsDistanceCullingInvisible() => IsState(State_DistanceCullingInvisible); public bool IsSkipWriting() => IsState(State_SkipWriting); + public bool IsUpdateTangent() => IsState(State_UpdateTangent); public bool IsEnable { @@ -240,7 +283,7 @@ namespace MagicaCloth2 { if (IsValid() == false || TeamId == 0) return false; - return ProxyMesh?.IsSuccess ?? false; + return ProxyMeshContainer?.shareVirtualMesh?.IsSuccess ?? false; } } @@ -292,7 +335,7 @@ namespace MagicaCloth2 continue; // 仮想メッシュ破棄 - info.renderMesh?.Dispose(); + info.renderMeshContainer?.Dispose(); } renderMeshInfoList.Clear(); renderMeshInfoList = null; @@ -310,13 +353,24 @@ namespace MagicaCloth2 boneClothSetupData = null; // プロキシメッシュ破棄 - ProxyMesh?.Dispose(); - ProxyMesh = null; + ProxyMeshContainer?.Dispose(); + ProxyMeshContainer = null; - colliderList.Clear(); + colliderDict.Clear(); - cullingAnimator = null; - cullingAnimatorRenderers.Clear(); + interlockingAnimator = null; + interlockingAnimatorRenderers.Clear(); + + // PreBuildデータ解除 + MagicaManager.PreBuild?.UnregisterPreBuildData(cloth?.GetSerializeData2()?.preBuildData.GetSharePreBuildData()); + + // 作業バッファ破棄 + SyncTopCloth = null; + int compId = cloth.GetInstanceID(); + MagicaManager.Team?.comp2SuspendCounterMap.Remove(compId); + MagicaManager.Team?.comp2TeamIdMap.Remove(compId); + MagicaManager.Team?.comp2SyncPartnerCompMap.Remove(compId); + MagicaManager.Team?.comp2SyncTopCompMap.Remove(compId); // 完全破棄フラグ isDestoryInternal = true; @@ -324,28 +378,49 @@ namespace MagicaCloth2 Develop.DebugLog($"Cloth dispose internal."); // 破棄監視リストから削除する - MagicaManager.Team.RemoveMonitoringProcess(this); + MagicaManager.Team?.RemoveMonitoringProcess(this); } internal void IncrementSuspendCounter() { - lock (lockObject) + //suspendCounter++; + var tm = MagicaManager.Team; + int compId = cloth.GetInstanceID(); + if (tm.comp2SuspendCounterMap.TryGetValue(compId, out int cnt)) { - suspendCounter++; + cnt++; + //tm.comp2SuspendCounterMap.Add(compId, cnt); + tm.comp2SuspendCounterMap[compId] = cnt; } + else + tm.comp2SuspendCounterMap.Add(compId, 1); } internal void DecrementSuspendCounter() { - lock (lockObject) + //suspendCounter--; + var tm = MagicaManager.Team; + int compId = cloth.GetInstanceID(); + if (tm.comp2SuspendCounterMap.TryGetValue(compId, out int cnt)) { - suspendCounter--; + cnt--; + if (cnt > 0) + //tm.comp2SuspendCounterMap.Add(compId, cnt); + tm.comp2SuspendCounterMap[compId] = cnt; + else + tm.comp2SuspendCounterMap.Remove(compId); } } internal int GetSuspendCounter() { - return suspendCounter; + //return suspendCounter; + var tm = MagicaManager.Team; + int compId = cloth.GetInstanceID(); + if (tm.comp2SuspendCounterMap.TryGetValue(compId, out int cnt)) + return cnt; + else + return 0; } public RenderMeshInfo GetRenderMeshInfo(int index) @@ -364,16 +439,22 @@ namespace MagicaCloth2 public void GetUsedTransform(HashSet transformSet) { cloth.SerializeData.GetUsedTransform(transformSet); + cloth.serializeData2.GetUsedTransform(transformSet); clothTransformRecord?.GetUsedTransform(transformSet); boneClothSetupData?.GetUsedTransform(transformSet); renderHandleList.ForEach(handle => MagicaManager.Render.GetRendererData(handle).GetUsedTransform(transformSet)); customSkinningBoneRecords.ForEach(rd => rd.GetUsedTransform(transformSet)); normalAdjustmentTransformRecord?.GetUsedTransform(transformSet); + + // nullを除外する + if (transformSet.Contains(null)) + transformSet.Remove(null); } public void ReplaceTransform(Dictionary replaceDict) { cloth.SerializeData.ReplaceTransform(replaceDict); + cloth.serializeData2.ReplaceTransform(replaceDict); clothTransformRecord?.ReplaceTransform(replaceDict); boneClothSetupData?.ReplaceTransform(replaceDict); renderHandleList.ForEach(handle => MagicaManager.Render.GetRendererData(handle).ReplaceTransform(replaceDict)); @@ -386,7 +467,44 @@ namespace MagicaCloth2 // ここではフラグのみ更新する // 実際の更新はチームのAlwaysTeamUpdate()で行われる SetState(State_SkipWriting, sw); - SetState(State_SkipWritingDirty, true); + //SetState(State_SkipWritingDirty, true); + MagicaManager.Team.skipWritingDirtyList.Add(this); + } + + internal ClothUpdateMode GetClothUpdateMode() + { + switch (cloth.SerializeData.updateMode) + { + case ClothUpdateMode.Normal: + case ClothUpdateMode.UnityPhysics: + case ClothUpdateMode.Unscaled: + return cloth.SerializeData.updateMode; + case ClothUpdateMode.AnimatorLinkage: + if (interlockingAnimator) + { + switch (interlockingAnimator.updateMode) + { + case AnimatorUpdateMode.Normal: + return ClothUpdateMode.Normal; +#if UNITY_2023_1_OR_NEWER + case AnimatorUpdateMode.Fixed: + return ClothUpdateMode.UnityPhysics; +#else + case AnimatorUpdateMode.AnimatePhysics: + return ClothUpdateMode.UnityPhysics; +#endif + case AnimatorUpdateMode.UnscaledTime: + return ClothUpdateMode.Unscaled; + default: + Develop.DebugLogWarning($"[{cloth.name}] Unknown Animator UpdateMode:{interlockingAnimator.updateMode}"); + break; + } + } + return ClothUpdateMode.Normal; + default: + Develop.LogError($"[{cloth.name}] Unknown Cloth Update Mode:{cloth.SerializeData.updateMode}"); + return ClothUpdateMode.Normal; + } } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessData.cs.meta index 5ac7149c..846c46ef 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessData.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessData.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessGeneration.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessGeneration.cs index 6f68534a..0d69d07d 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessGeneration.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessGeneration.cs @@ -1,13 +1,56 @@ // Magica Cloth 2. // Copyright (c) 2023 MagicaSoft. // https://magicasoft.jp - using Unity.Mathematics; +using UnityEngine; namespace MagicaCloth2 { public partial class ClothProcess { + public ResultCode GenerateStatusCheck() + { + ResultCode result = new ResultCode(); + + // スケール値チェック + var scl = cloth.transform.lossyScale; + if (Mathf.Approximately(scl.x, 0.0f) || Mathf.Approximately(scl.y, 0.0f) || Mathf.Approximately(scl.z, 0.0f)) + { + // スケール値がゼロ + result.SetError(Define.Result.Init_ScaleIsZero); + } + else if (scl.x < 0.0f || scl.y < 0.0f || scl.z < 0.0f) + { + // 負のスケール + // 負のスケールでの初期化は、事前構築もしくは初期化データありの場合許可する + var sdata2 = cloth.GetSerializeData2(); + if (sdata2.preBuildData.UsePreBuild() || (sdata2.initData?.HasData() ?? false)) + { + // ただし許可されるのは一軸フリップのみ + int flipCount = (scl.x < 0.0f ? 1 : 0) + (scl.y < 0.0f ? 1 : 0) + (scl.z < 0.0f ? 1 : 0); + if (flipCount != 1) + { + result.SetError(Define.Result.Init_NegativeScale); + } + } + else + result.SetError(Define.Result.Init_NegativeScale); + } + else + { + float diff1 = Mathf.Abs(1.0f - scl.x / scl.y); + float diff2 = Mathf.Abs(1.0f - scl.x / scl.z); + const float diffTolerance = 0.01f; // 誤差(1%) + if (diff1 > diffTolerance || diff2 > diffTolerance) + { + // 一様スケールではない + result.SetWarning(Define.Result.Init_NonUniformScale); + } + } + + return result; + } + internal bool GenerateInitialization() { result.SetProcess(); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessGeneration.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessGeneration.cs.meta index 9c9fc9ed..a74da22e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessGeneration.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessGeneration.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothProcessGeneration.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData.cs index d37aef77..209cb672 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData.cs @@ -29,6 +29,13 @@ namespace MagicaCloth2 /// public List sourceRenderers = new List(); + /// + /// Write target to mesh in MeshCloth. + /// [OK] Runtime changes. + /// [NG] Export/Import with Presets + /// + public ClothMeshWriteMode meshWriteMode = ClothMeshWriteMode.PositionAndNormal; + public enum PaintMode { Manual = 0, @@ -55,6 +62,14 @@ namespace MagicaCloth2 /// public List paintMaps = new List(); + /// + /// The UV channel that references the paint map. + /// [NG] Runtime changes. + /// [NG] Export/Import with Presets + /// + [Range(0, 7)] + public int paintMapUvChannel = 0; + /// /// Root bone list used in BoneCloth. /// [NG] Runtime changes. @@ -92,7 +107,7 @@ namespace MagicaCloth2 /// [OK] Runtime changes. /// [NG] Export/Import with Presets /// - public ClothUpdateMode updateMode = ClothUpdateMode.Normal; + public ClothUpdateMode updateMode = ClothUpdateMode.AnimatorLinkage; /// /// Blend ratio between initial pose and animation pose. @@ -180,7 +195,7 @@ namespace MagicaCloth2 /// [OK] Runtime changes. /// [NG] Export/Import with Presets /// - [System.NonSerialized] + [Range(0.0f, 1.0f)] public float blendWeight = 1.0f; /// diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData.cs.meta index 09004c49..cac805ce 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData2.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData2.cs index 93fb8e38..fda9bd42 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData2.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData2.cs @@ -11,8 +11,14 @@ namespace MagicaCloth2 /// Parts that cannot be exported externally. /// [System.Serializable] - public class ClothSerializeData2 : IDataValidate, IValid + public class ClothSerializeData2 : IDataValidate, IValid, ITransform { + /// + /// Initialization Data. + /// + [SerializeField] + public ClothInitSerializeData initData = new ClothInitSerializeData(); + /// /// 頂点ペイントデータ /// vertex paint data. @@ -26,8 +32,23 @@ namespace MagicaCloth2 /// Transform and vertex attribute dictionary data. /// When creating BoneCloth/BoneSpring at runtime, you can store Transform and vertex attribute pairs in this dictionary and use it instead of vertex paint data. /// + [System.NonSerialized] public Dictionary boneAttributeDict = new Dictionary(); + /// + /// Rendererに対応する頂点属性データ + /// 実行時にMeshClothを構築する場合に、このリストにレンダラーごとのメッシュ頂点数分の頂点属性を格納することでセレクションデータの代わりにすることができます + /// Vertex attribute data corresponding to the Renderer. + /// When constructing MeshCloth at runtime, you can substitute selection data by storing vertex attributes in this list for the number of mesh vertices per renderer. + /// + [System.NonSerialized] + public List vertexAttributeList = new List(); + + /// + /// PreBuild Data. + /// + public PreBuildSerializeData preBuildData = new PreBuildSerializeData(); + //========================================================================================= public ClothSerializeData2() { @@ -57,5 +78,17 @@ namespace MagicaCloth2 int hash = 0; return hash; } + + public void GetUsedTransform(HashSet transformSet) + { + initData.GetUsedTransform(transformSet); + preBuildData.GetUsedTransform(transformSet); + } + + public void ReplaceTransform(Dictionary replaceDict) + { + initData.ReplaceTransform(replaceDict); + preBuildData.ReplaceTransform(replaceDict); + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData2.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData2.cs.meta index 66f53c6f..256f9c3d 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData2.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData2.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeData2.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeDataFunction.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeDataFunction.cs index 55970226..42c3a5e6 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeDataFunction.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeDataFunction.cs @@ -44,6 +44,11 @@ namespace MagicaCloth2 return false; if (rootBones.Count(x => x != null) == 0) return false; + if (rootBones.Distinct().Count() != rootBones.Count) + { + verificationResult.SetError(Define.Result.SerializeData_DuplicateRootBone); + return false; + } break; case ClothProcess.ClothType.MeshCloth: if (sourceRenderers == null || sourceRenderers.Count == 0) @@ -57,6 +62,11 @@ namespace MagicaCloth2 verificationResult.SetError(Define.Result.SerializeData_Over31Renderers); return false; } + if (sourceRenderers.Distinct().Count() != sourceRenderers.Count) + { + verificationResult.SetError(Define.Result.SerializeData_DuplicateRenderer); + return false; + } break; default: return false; @@ -107,10 +117,12 @@ namespace MagicaCloth2 /// public override int GetHashCode() { + const int NullHash = -3910836; + int hash = 0; hash += (int)clothType; foreach (var ren in sourceRenderers) - hash += ren?.GetInstanceID() ?? 0; + hash += ren?.GetInstanceID() ?? NullHash; foreach (var t in rootBones) { var stack = new Stack(30); @@ -119,7 +131,10 @@ namespace MagicaCloth2 { var t2 = stack.Pop(); if (t2 == null) + { + hash += NullHash; continue; + } hash += t2.GetInstanceID(); hash += t2.localPosition.GetHashCode(); hash += t2.localRotation.GetHashCode(); @@ -142,6 +157,7 @@ namespace MagicaCloth2 hash += map.isReadable ? 1 : 0; } } + hash += paintMapUvChannel * 123; hash += colliderCollisionConstraint.GetHashCode(); return hash; @@ -158,7 +174,7 @@ namespace MagicaCloth2 //cparams.solverFrequency = Define.System.SolverFrequency; cparams.gravity = clothType == ClothProcess.ClothType.BoneSpring ? 0.0f : gravity; // BoneSpring has no gravity. - cparams.gravityDirection = gravityDirection; + cparams.worldGravityDirection = gravityDirection; cparams.gravityFalloff = gravityFalloff; cparams.stablizationTimeAfterReset = stablizationTimeAfterReset; cparams.blendWeight = blendWeight; @@ -169,6 +185,7 @@ namespace MagicaCloth2 cparams.rotationalInterpolation = rotationalInterpolation; cparams.rootRotation = rootRotation; + cparams.culling.Convert(cullingSettings); cparams.inertiaConstraint.Convert(inertiaConstraint); cparams.tetherConstraint.Convert(tetherConstraint, clothType); cparams.distanceConstraint.Convert(distanceConstraint, clothType); @@ -187,8 +204,10 @@ namespace MagicaCloth2 { ClothProcess.ClothType clothType; List sourceRenderers; + ClothMeshWriteMode meshWriteMode; PaintMode paintMode; List paintMaps; + int paintMapUvChannel; List rootBones; RenderSetupData.BoneConnectionMode connectionMode; float rotationalInterpolation; @@ -204,9 +223,9 @@ namespace MagicaCloth2 MagicaCloth synchronization; float stablizationTimeAfterReset; float blendWeight; - CullingSettings.CameraCullingMode cullingMode; - CullingSettings.CameraCullingMethod cullingMethod; - List cullingRenderers; + CullingSettings cullingSetting; + Transform anchor; + float anchorInertia; internal TempBuffer(ClothSerializeData sdata) { @@ -217,8 +236,10 @@ namespace MagicaCloth2 { clothType = sdata.clothType; sourceRenderers = new List(sdata.sourceRenderers); + meshWriteMode = sdata.meshWriteMode; paintMode = sdata.paintMode; paintMaps = new List(sdata.paintMaps); + paintMapUvChannel = sdata.paintMapUvChannel; rootBones = new List(sdata.rootBones); connectionMode = sdata.connectionMode; rotationalInterpolation = sdata.rotationalInterpolation; @@ -234,17 +255,19 @@ namespace MagicaCloth2 synchronization = sdata.selfCollisionConstraint.syncPartner; stablizationTimeAfterReset = sdata.stablizationTimeAfterReset; blendWeight = sdata.blendWeight; - cullingMode = sdata.cullingSettings.cameraCullingMode; - cullingMethod = sdata.cullingSettings.cameraCullingMethod; - cullingRenderers = new List(sdata.cullingSettings.cameraCullingRenderers); + cullingSetting = sdata.cullingSettings.Clone(); + anchor = sdata.inertiaConstraint.anchor; + anchorInertia = sdata.inertiaConstraint.anchorInertia; } internal void Pop(ClothSerializeData sdata) { sdata.clothType = clothType; sdata.sourceRenderers = sourceRenderers; + sdata.meshWriteMode = meshWriteMode; sdata.paintMode = paintMode; sdata.paintMaps = paintMaps; + sdata.paintMapUvChannel = paintMapUvChannel; sdata.rootBones = rootBones; sdata.connectionMode = connectionMode; sdata.rotationalInterpolation = rotationalInterpolation; @@ -260,9 +283,9 @@ namespace MagicaCloth2 sdata.selfCollisionConstraint.syncPartner = synchronization; sdata.stablizationTimeAfterReset = stablizationTimeAfterReset; sdata.blendWeight = blendWeight; - sdata.cullingSettings.cameraCullingMode = cullingMode; - sdata.cullingSettings.cameraCullingMethod = cullingMethod; - sdata.cullingSettings.cameraCullingRenderers = cullingRenderers; + sdata.cullingSettings = cullingSetting; + sdata.inertiaConstraint.anchor = anchor; + sdata.inertiaConstraint.anchorInertia = anchorInertia; } } @@ -325,6 +348,7 @@ namespace MagicaCloth2 sourceRenderers = new List(sdata.sourceRenderers); paintMode = sdata.paintMode; paintMaps = new List(sdata.paintMaps); + paintMapUvChannel = sdata.paintMapUvChannel; rootBones = new List(sdata.rootBones); connectionMode = sdata.connectionMode; rotationalInterpolation = sdata.rotationalInterpolation; @@ -404,5 +428,17 @@ namespace MagicaCloth2 /// /// public bool IsBoneSpring() => clothType == ClothProcess.ClothType.BoneSpring; + + public int GetUvChannel() + { + switch (paintMode) + { + case PaintMode.Texture_Fixed_Move: + case PaintMode.Texture_Fixed_Move_Limit: + return paintMapUvChannel; + default: + return 0; + } + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeDataFunction.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeDataFunction.cs.meta index 4e391e4b..e658b794 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeDataFunction.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeDataFunction.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothSerializeDataFunction.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothUpdateMode.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothUpdateMode.cs index 47334c31..111d9366 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothUpdateMode.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothUpdateMode.cs @@ -23,5 +23,14 @@ namespace MagicaCloth2 /// Updates are independent of Unity's Time.timeScale. /// Unscaled = 2, + + /// + /// Automatically set from linked animator. + /// 連動アニメーターから自動設定する + /// - Animator.UpdateMode.Normal -> Normal + /// - Animator.UpdateMode.AnimatePhysics -> UnityPhysics + /// - Animator.UpdateMode.UnscaledTime -> Unscaled + /// + AnimatorLinkage = 10, } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothUpdateMode.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothUpdateMode.cs.meta index fd9986f0..970829f6 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothUpdateMode.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothUpdateMode.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/ClothUpdateMode.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderComponent.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderComponent.cs index 195ff59e..927ec2b4 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderComponent.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderComponent.cs @@ -2,11 +2,12 @@ // Copyright (c) 2023 MagicaSoft. // https://magicasoft.jp using System.Collections.Generic; +using System.Linq; using UnityEngine; namespace MagicaCloth2 { - public abstract class ColliderComponent : ClothBehaviour, IDataValidate + public abstract class ColliderComponent : ClothBehaviour, IDataValidate, ITransform { /// /// トランスフォームからの中心ローカルオフセット @@ -23,6 +24,17 @@ namespace MagicaCloth2 [SerializeField] protected Vector3 size; + /// + /// シンメトリーモード + /// Symmetry mode. + /// + public ColliderSymmetryMode symmetryMode = ColliderSymmetryMode.None; + + /// + /// シンメトリーの接続対象 + /// Symmetry connection target. + /// + public Transform symmetryTarget = null; //========================================================================================= /// @@ -42,6 +54,16 @@ namespace MagicaCloth2 /// private HashSet teamIdSet = new HashSet(); + /// + /// 現在登録中のシンメトリーモード + /// + public ColliderSymmetryMode? ActiveSymmetryMode { get; private set; } = null; + + /// + /// 現在登録中のシンメトリーターゲット + /// + public Transform ActiveSymmetryTarget { get; private set; } + //========================================================================================= /// /// Get collider size. @@ -52,26 +74,30 @@ namespace MagicaCloth2 /// /// /// - public virtual Vector3 GetSize() - { - return size; - } + public virtual Vector3 GetSize() => size; - public void SetSize(Vector3 size) - { - this.size = size; - } + public void SetSize(Vector3 size) => this.size = size; + + public void SetSizeX(float size) => this.size.x = size; + public void SetSizeY(float size) => this.size.y = size; + public void SetSizeZ(float size) => this.size.z = size; /// /// スケール値を取得 /// /// - public float GetScale() + public virtual float GetScale() { // X軸のみを見る return transform.lossyScale.x; } + /// + /// 方向の逆転(基本的にカプセルコライダー用) + /// + /// + public virtual bool IsReverseDirection() => false; + /// /// チームへのコライダー登録通知 /// @@ -85,9 +111,11 @@ namespace MagicaCloth2 /// チームからのコライダー解除通知 /// /// - internal void Exit(int teamId) + /// 利用者0ならtrue + internal bool Exit(int teamId) { teamIdSet.Remove(teamId); + return teamIdSet.Count == 0; } /// @@ -101,15 +129,269 @@ namespace MagicaCloth2 // パラメータの検証 DataValidate(); + // Symmetry更新 + // シンメトリーは削除もしくは追加がある。またTransformが変更される場合もある + var oldActiveSymmetryMode = ActiveSymmetryMode; + var oldActiveSymmetryTarget = ActiveSymmetryTarget; + SetActiveSymmetryMode(firstOnly: false); // 最新の状態に更新 + bool changeSymmetry = oldActiveSymmetryMode != ActiveSymmetryMode || oldActiveSymmetryTarget != ActiveSymmetryTarget; + + // 反映 foreach (int teamId in teamIdSet) { - MagicaManager.Collider.UpdateParameters(this, teamId); + MagicaManager.Collider.UpdateParameters(this, teamId, changeSymmetry); + } + } + + /// + /// 現在の状態から適切なシンメトリーモードとそのターゲットTransformを計算して返す + /// + /// + public ColliderSymmetryMode CalcSymmetryMode(out Transform symmetryParent) + { + symmetryParent = symmetryTarget; + + // 親 + var parent = transform.parent; + if (parent == null) + return ColliderSymmetryMode.None; + + switch (symmetryMode) + { + case ColliderSymmetryMode.None: + return ColliderSymmetryMode.None; + case ColliderSymmetryMode.AutomaticHumanBody: + case ColliderSymmetryMode.AutomaticTarget: + break; + case ColliderSymmetryMode.X_Symmetry: + case ColliderSymmetryMode.Y_Symmetry: + case ColliderSymmetryMode.Z_Symmetry: + case ColliderSymmetryMode.XYZ_Symmetry: + // ターゲットnullの場合は親 + if (symmetryParent == null) + symmetryParent = parent; + return symmetryMode; + default: + Develop.LogError("Unknown symmetry mode."); + return ColliderSymmetryMode.None; + } + + // Automatic + Animator ani = symmetryMode == ColliderSymmetryMode.AutomaticHumanBody ? gameObject.GetComponentInParent(true) : null; + + // 対象Transform + // AutomaticではSymmetryTargetは無視される + var target = symmetryMode == ColliderSymmetryMode.AutomaticTarget ? symmetryTarget : null; + if (target == null && ani) + { + // 自動判定 + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.Hips, HumanBodyBones.Hips); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftUpperLeg, HumanBodyBones.RightUpperLeg); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightUpperLeg, HumanBodyBones.LeftUpperLeg); + + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftLowerLeg, HumanBodyBones.RightLowerLeg); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightLowerLeg, HumanBodyBones.LeftLowerLeg); + + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftFoot, HumanBodyBones.RightFoot); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightFoot, HumanBodyBones.LeftFoot); + + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.Spine, HumanBodyBones.Spine); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.Chest, HumanBodyBones.Chest); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.Neck, HumanBodyBones.Neck); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.Head, HumanBodyBones.Head); + + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftShoulder, HumanBodyBones.RightShoulder); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightShoulder, HumanBodyBones.LeftShoulder); + + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftUpperArm, HumanBodyBones.RightUpperArm); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightUpperArm, HumanBodyBones.LeftUpperArm); + + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftLowerArm, HumanBodyBones.RightLowerArm); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightLowerArm, HumanBodyBones.LeftLowerArm); + + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftHand, HumanBodyBones.RightHand); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightHand, HumanBodyBones.LeftHand); + + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftToes, HumanBodyBones.RightToes); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightToes, HumanBodyBones.LeftToes); + + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.Jaw, HumanBodyBones.Jaw); + GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.UpperChest, HumanBodyBones.UpperChest); + } + if (target == null) + target = parent; + symmetryParent = target; + + // 親が同一かどうか + bool sameParent = target == parent; + + // 各軸 + var x = parent.right; + var y = parent.up; + var z = parent.forward; + var sx = target.right; + var sy = target.up; + var sz = target.forward; + + // ベクトルの方向性情報 + // Animatorがある場合はAnimatorから、ない場合は共通の親Transformから、それでも無い場合はワールドX軸 + Vector3 H = Vector3.right; + if (ani) + H = ani.transform.right; + else + { + var commonParent = FindCommonParent(transform, symmetryParent); + if (commonParent) + { + //Debug.Log($"Find common parent:{commonParent.name}"); + H = commonParent.right; + } + } + + float xdot = Mathf.Abs(Vector3.Dot(H, x)); + float ydot = Mathf.Abs(Vector3.Dot(H, y)); + float zdot = Mathf.Abs(Vector3.Dot(H, z)); + + bool xsign = Vector3.Dot(x, sx) >= 0.0f; + bool ysign = Vector3.Dot(y, sy) >= 0.0f; + bool zsign = Vector3.Dot(z, sz) >= 0.0f; + + if (xdot > ydot && xdot > zdot) + { + // (X) + if (sameParent) + return ColliderSymmetryMode.X_Symmetry; + if (Vector3.Dot(H, x) * Vector3.Dot(H, sx) > 0.0f) + { + if (ysign == false && zsign == false) + return ColliderSymmetryMode.XYZ_Symmetry; + else + return ColliderSymmetryMode.X_Symmetry; + } + else if (zsign) + return ColliderSymmetryMode.Y_Symmetry; + else + return ColliderSymmetryMode.Z_Symmetry; + } + else if (ydot > xdot && ydot > zdot) + { + // (Y) + if (sameParent) + return ColliderSymmetryMode.Y_Symmetry; + if (Vector3.Dot(H, y) * Vector3.Dot(H, sy) > 0.0f) + { + if (xsign == false && zsign == false) + return ColliderSymmetryMode.XYZ_Symmetry; + else + return ColliderSymmetryMode.Y_Symmetry; + } + else if (zsign) + return ColliderSymmetryMode.X_Symmetry; + else + return ColliderSymmetryMode.Z_Symmetry; + } + else + { + // (Z) + if (sameParent) + return ColliderSymmetryMode.Z_Symmetry; + if (Vector3.Dot(H, z) * Vector3.Dot(H, sz) > 0.0f) + { + if (xsign == false && ysign == false) + return ColliderSymmetryMode.XYZ_Symmetry; + else + return ColliderSymmetryMode.Z_Symmetry; + } + else if (xsign) + return ColliderSymmetryMode.Y_Symmetry; + else + return ColliderSymmetryMode.X_Symmetry; + } + } + + bool GetHumanoidSymmetryBone(ref Transform target, Transform parent, Animator ani, HumanBodyBones src, HumanBodyBones dst) + { + var bone = ani.GetBoneTransform(src); + if (bone && parent == bone) + { + var bone2 = ani.GetBoneTransform(dst); + if (bone2) + { + target = bone2; + return true; + } + } + + return false; + } + + /// + /// at/btの共通の親を返す。無い場合はnull。 + /// + /// + /// + /// + Transform FindCommonParent(Transform at, Transform bt) + { + if (at == null || bt == null) + return null; + + // ハッシュセットでatの親を格納 + var atParents = new HashSet(16); + Transform current = at; + while (current != null) + { + atParents.Add(current); + current = current.parent; + } + + // btの親をチェック + current = bt; + while (current != null) + { + if (atParents.Contains(current)) + return current; + current = current.parent; + } + + return null; + } + + /// + /// 現在のシンメトリー設定に基づいて、シンメトリーのモードと対象を決定する + /// + internal void SetActiveSymmetryMode(bool firstOnly) + { + if (ActiveSymmetryMode.HasValue == false || firstOnly == false) + { + ActiveSymmetryMode = CalcSymmetryMode(out var target); + ActiveSymmetryTarget = target; + } + } + + public int UseTeamCount => teamIdSet.Count; + + //========================================================================================= + public void GetUsedTransform(HashSet transformSet) + { + if (symmetryTarget) + transformSet.Add(symmetryTarget); + } + + public void ReplaceTransform(Dictionary replaceDict) + { + if (symmetryTarget) + { + int id = symmetryTarget.GetInstanceID(); + if (id != 0 && replaceDict.ContainsKey(id)) + symmetryTarget = replaceDict[id]; } } //========================================================================================= protected virtual void Start() { + SetActiveSymmetryMode(firstOnly: true); } protected virtual void OnValidate() @@ -131,18 +413,22 @@ namespace MagicaCloth2 // コライダーを無効にする foreach (int teamId in teamIdSet) { - MagicaManager.Collider.EnableCollider(this, teamId, false); + MagicaManager.Collider?.EnableCollider(this, teamId, false); } } protected virtual void OnDestroy() { // コライダーを削除する - foreach (int teamId in teamIdSet) + if (teamIdSet.Count > 0) { - MagicaManager.Collider.RemoveCollider(this, teamId); + var teamList = teamIdSet.ToList(); + foreach (int teamId in teamList) + { + MagicaManager.Collider?.RemoveCollider(this, teamId); + } + teamIdSet.Clear(); } - teamIdSet.Clear(); } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderComponent.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderComponent.cs.meta index 63bdbc33..a2407ce5 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderComponent.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderComponent.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderComponent.cs + uploadId: 756593 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 00000000..7be93a13 --- /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 00000000..39ece314 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderSymmetryMode.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 02f9b444838ae8a41916aab95109474e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/ColliderSymmetryMode.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaCapsuleCollider.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaCapsuleCollider.cs index 6a74354a..c832b499 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaCapsuleCollider.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaCapsuleCollider.cs @@ -29,6 +29,12 @@ namespace MagicaCloth2 /// public Direction direction = Direction.X; + /// + /// Reverse direction. + /// 方向を逆転させる + /// + public bool reverseDirection = false; + /// /// 半径をStart/End別々に設定 /// Set radius separately for Start/End. @@ -86,12 +92,14 @@ namespace MagicaCloth2 /// public Vector3 GetLocalDir() { + float rev = reverseDirection ? -1 : 1; + if (direction == Direction.X) - return Vector3.right; + return Vector3.right * rev; else if (direction == Direction.Y) - return Vector3.up; + return Vector3.up * rev; else - return Vector3.forward; + return Vector3.forward * rev; } /// @@ -108,6 +116,12 @@ namespace MagicaCloth2 return Vector3.up; } + /// + /// 方向の逆転(基本的にカプセルコライダー用) + /// + /// + public override bool IsReverseDirection() => reverseDirection; + public override void DataValidate() { size.x = Mathf.Max(size.x, 0.001f); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaCapsuleCollider.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaCapsuleCollider.cs.meta index 77a804ba..0eaabaec 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaCapsuleCollider.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaCapsuleCollider.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaCapsuleCollider.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaPlaneCollider.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaPlaneCollider.cs.meta index 099ff095..f598ae0f 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaPlaneCollider.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaPlaneCollider.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaPlaneCollider.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaSphereCollider.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaSphereCollider.cs.meta index 9f3472ec..1fd076b5 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaSphereCollider.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaSphereCollider.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Collider/MagicaSphereCollider.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/AngleConstraint.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/AngleConstraint.cs index c72604f0..5dc67fb0 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/AngleConstraint.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/AngleConstraint.cs @@ -3,9 +3,7 @@ // https://magicasoft.jp using System; using System.Text; -using Unity.Burst; using Unity.Collections; -using Unity.Jobs; using Unity.Mathematics; using UnityEngine; @@ -188,14 +186,6 @@ namespace MagicaCloth2 } } - //========================================================================================= - NativeArray lengthBuffer; - NativeArray localPosBuffer; - NativeArray localRotBuffer; - NativeArray rotationBuffer; - NativeArray restorationVectorBuffer; - - //========================================================================================= public AngleConstraint() { @@ -203,174 +193,77 @@ namespace MagicaCloth2 public void Dispose() { - lengthBuffer.DisposeSafe(); - localPosBuffer.DisposeSafe(); - localRotBuffer.DisposeSafe(); - rotationBuffer.DisposeSafe(); - restorationVectorBuffer.DisposeSafe(); - } - - internal void WorkBufferUpdate() - { - int pcnt = MagicaManager.Simulation.ParticleCount; - lengthBuffer.Resize(pcnt, options: NativeArrayOptions.UninitializedMemory); - localPosBuffer.Resize(pcnt, options: NativeArrayOptions.UninitializedMemory); - localRotBuffer.Resize(pcnt, options: NativeArrayOptions.UninitializedMemory); - rotationBuffer.Resize(pcnt, options: NativeArrayOptions.UninitializedMemory); - restorationVectorBuffer.Resize(pcnt, options: NativeArrayOptions.UninitializedMemory); } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.AppendLine($"[AngleConstraint]"); - sb.AppendLine($" -lengthBuffer:{(lengthBuffer.IsCreated ? lengthBuffer.Length : 0)}"); - sb.AppendLine($" -localPosBuffer:{(localPosBuffer.IsCreated ? localPosBuffer.Length : 0)}"); - sb.AppendLine($" -localRotBuffer:{(localRotBuffer.IsCreated ? localRotBuffer.Length : 0)}"); - sb.AppendLine($" -rotationBuffer:{(rotationBuffer.IsCreated ? rotationBuffer.Length : 0)}"); - sb.AppendLine($" -restorationVectorBuffer:{(restorationVectorBuffer.IsCreated ? restorationVectorBuffer.Length : 0)}"); - return sb.ToString(); } //========================================================================================= - /// - /// 制約の解決 - /// - /// - /// - /// - internal unsafe JobHandle SolverConstraint(JobHandle jobHandle) - { - var tm = MagicaManager.Team; - var sm = MagicaManager.Simulation; - var vm = MagicaManager.VMesh; - - // 角度復元と角度制限を1つに統合したもの - // 復元/制限ともにほぼMC1の移植。 - // 他のアルゴリズムを散々テストした結果、MC1の動きが一番映えるという結論に至る。 - // 微調整および堅牢性を上げるために反復回数を増やしている。 - var job = new AngleConstraintJob() - { - simulationPower = MagicaManager.Time.SimulationPower, - - stepBaseLineIndexArray = sm.processingStepBaseLine.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - - attributes = vm.attributes.GetNativeArray(), - vertexDepths = vm.vertexDepths.GetNativeArray(), - vertexParentIndices = vm.vertexParentIndices.GetNativeArray(), - baseLineStartDataIndices = vm.baseLineStartDataIndices.GetNativeArray(), - baseLineDataCounts = vm.baseLineDataCounts.GetNativeArray(), - baseLineData = vm.baseLineData.GetNativeArray(), - - nextPosArray = sm.nextPosArray.GetNativeArray(), - velocityPosArray = sm.velocityPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - - stepBasicPositionBuffer = sm.stepBasicPositionBuffer, - stepBasicRotationBuffer = sm.stepBasicRotationBuffer, - - lengthBufferArray = lengthBuffer, - localPosBufferArray = localPosBuffer, - localRotBufferArray = localRotBuffer, - rotationBufferArray = rotationBuffer, - restorationVectorBufferArray = restorationVectorBuffer, - }; - jobHandle = job.Schedule(sm.processingStepBaseLine.GetJobSchedulePtr(), 2, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct AngleConstraintJob : IJobParallelForDefer - { - public float4 simulationPower; - - [Unity.Collections.ReadOnly] - public NativeArray stepBaseLineIndexArray; - + // Solver + //========================================================================================= + internal static void SolverConstraint( + DataChunk chunk, + in float4 simulationPower, // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - + ref TeamManager.TeamData tdata, + ref ClothParameters param, // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [Unity.Collections.ReadOnly] - public NativeArray vertexDepths; - [Unity.Collections.ReadOnly] - public NativeArray vertexParentIndices; - [Unity.Collections.ReadOnly] - public NativeArray baseLineStartDataIndices; - [Unity.Collections.ReadOnly] - public NativeArray baseLineDataCounts; - [Unity.Collections.ReadOnly] - public NativeArray baseLineData; - + ref NativeArray attributes, + ref NativeArray vertexDepths, + ref NativeArray vertexParentIndices, + ref NativeArray baseLineStartDataIndices, + ref NativeArray baseLineDataCounts, + ref NativeArray baseLineData, // particle - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - [NativeDisableParallelForRestriction] - public NativeArray velocityPosArray; - [Unity.Collections.ReadOnly] - public NativeArray frictionArray; + ref NativeArray nextPosArray, + ref NativeArray velocityPosArray, + ref NativeArray frictionArray, + // buffer + ref NativeArray stepBasicPositionBuffer, + ref NativeArray stepBasicRotationBuffer, + // buffer2 + ref NativeArray lengthBufferArray, + ref NativeArray localPosBufferArray, + ref NativeArray localRotBufferArray, + ref NativeArray rotationBufferArray, + ref NativeArray restorationVectorBufferArray + ) + { + var angleParam = param.angleConstraint; + if (angleParam.useAngleLimit == false && angleParam.useAngleRestoration == false) + return; - // temp - [Unity.Collections.ReadOnly] - public NativeArray stepBasicPositionBuffer; - [Unity.Collections.ReadOnly] - public NativeArray stepBasicRotationBuffer; - [NativeDisableParallelForRestriction] - public NativeArray lengthBufferArray; - [NativeDisableParallelForRestriction] - public NativeArray localPosBufferArray; - [NativeDisableParallelForRestriction] - public NativeArray localRotBufferArray; - [NativeDisableParallelForRestriction] - public NativeArray rotationBufferArray; - [NativeDisableParallelForRestriction] - public NativeArray restorationVectorBufferArray; + int d_start = tdata.baseLineDataChunk.startIndex; + int p_start = tdata.particleChunk.startIndex; + int v_start = tdata.proxyCommonChunk.startIndex; + + bool useAngleLimit = angleParam.useAngleLimit; + bool useAngleRestoration = angleParam.useAngleRestoration; + + // 剛性 + float limitStiffness = angleParam.limitstiffness; + float restorationAttn = angleParam.restorationVelocityAttenuation; + + // 復元の重力減衰 + // !この減衰は重力0でも発生するので注意! + float gravityFalloff = math.lerp(1.0f - angleParam.restorationGravityFalloff, 1.0f, tdata.gravityDot); + //Debug.Log($"gravityFalloff:{gravityFalloff}"); + //float gravity = param.gravity; + //float3 gravityVector = gravity > Define.System.Epsilon ? param.gravityDirection : 0; // ベースラインごと - public void Execute(int index) + //int bindex = tdata.baseLineChunk.startIndex; + int bindex = tdata.baseLineChunk.startIndex + chunk.startIndex; + //for (int a = 0; a < tdata.baseLineChunk.dataLength; a++, bindex++) + for (int a = 0; a < chunk.dataLength; a++, bindex++) { - uint pack = (uint)stepBaseLineIndexArray[index]; - int teamId = DataUtility.Unpack32Hi(pack); - int bindex = DataUtility.Unpack32Low(pack); - - // チームは有効であることが保証されている - var tdata = teamDataArray[teamId]; - var param = parameterArray[teamId]; - var angleParam = param.angleConstraint; - if (angleParam.useAngleLimit == false && angleParam.useAngleRestoration == false) - return; - - int d_start = tdata.baseLineDataChunk.startIndex; - int p_start = tdata.particleChunk.startIndex; - int v_start = tdata.proxyCommonChunk.startIndex; - int start = baseLineStartDataIndices[bindex]; int dcnt = baseLineDataCounts[bindex]; - bool useAngleLimit = angleParam.useAngleLimit; - bool useAngleRestoration = angleParam.useAngleRestoration; - - // 剛性 - float limitStiffness = angleParam.limitstiffness; - float restorationAttn = angleParam.restorationVelocityAttenuation; - - // 復元の重力減衰 - // !この減衰は重力0でも発生するので注意! - float gravityFalloff = math.lerp(1.0f - angleParam.restorationGravityFalloff, 1.0f, tdata.gravityDot); - //Debug.Log($"gravityFalloff:{gravityFalloff}"); - //float gravity = param.gravity; - //float3 gravityVector = gravity > Define.System.Epsilon ? param.gravityDirection : 0; - // バッファリング int dataIndex = start + d_start; for (int i = 0; i < dcnt; i++, dataIndex++) @@ -402,15 +295,29 @@ namespace MagicaCloth2 // 親からの基本姿勢 var bv = bpos - pbpos; - Develop.Assert(math.length(bv) > 0.0f); - var v = math.normalize(bv); - var ipq = math.inverse(pbrot); - float3 localPos = math.mul(ipq, v); - quaternion localRot = math.mul(ipq, brot); + float bvlen = math.length(bv); + if (vlen < Define.System.Epsilon || bvlen < Define.System.Epsilon) + { + // length=0 + //Debug.Log($"NG1"); + //エッジ長0対処 + lengthBufferArray[pindex] = 0; + localPosBufferArray[pindex] = 0; + localRotBufferArray[pindex] = quaternion.identity; + } + else + { + //Develop.Assert(math.length(bv) > 0.0f); + //var v = math.normalize(bv); + var v = bv / bvlen; + var ipq = math.inverse(pbrot); + float3 localPos = math.mul(ipq, v); + quaternion localRot = math.mul(ipq, brot); - lengthBufferArray[pindex] = vlen; - localPosBufferArray[pindex] = localPos; - localRotBufferArray[pindex] = localRot; + lengthBufferArray[pindex] = vlen; + localPosBufferArray[pindex] = localPos; + localRotBufferArray[pindex] = localRot; + } } if (useAngleRestoration) @@ -418,6 +325,7 @@ namespace MagicaCloth2 // 復元ベクトル float3 rv = bpos - pbpos; restorationVectorBufferArray[pindex] = rv; + //Debug.Log($"[{pindex}] rv:{rv}"); } } } @@ -478,19 +386,46 @@ namespace MagicaCloth2 // 現在のベクトル float3 v = cpos - ppos; + float vlen = math.length(v); + if (vlen < Define.System.Epsilon) + { + //エッジ長0対処 + //Debug.Log($"NG2"); + goto EndAngleLimit; + } // 復元すべきベクトル float3 tv = math.mul(prot, localPos); + float tvlen = math.length(tv); + if (tvlen < Define.System.Epsilon) + { + //エッジ長0対処 + //Debug.Log($"NG3"); + float3 add = ppos - cpos; + nextPosArray[pindex] = ppos; + velocityPosArray[pindex] = velocityPosArray[pindex] + add; + rotationBufferArray[pindex] = math.mul(prot, localRot); + goto EndAngleLimit; + } + + v /= vlen; + tv /= tvlen; // ベクトル長修正 - float vlen = math.length(v); float blen = lengthBufferArray[pindex]; vlen = math.lerp(vlen, blen, 0.5f); // 計算前の距離に徐々に近づける - Develop.Assert(vlen > 0.0f); - v = math.normalize(v) * vlen; + if (blen < Define.System.Epsilon || vlen < Define.System.Epsilon) + { + //エッジ長0対処 + //Debug.Log($"NG4"); + goto EndAngleLimit; + } + //Develop.Assert(vlen > 0.0f); + //v = math.normalize(v) * vlen; + v = v * vlen; // ベクトル角度クランプ - float maxAngleDeg = angleParam.limitCurveData.EvaluateCurve(cdepth); + float maxAngleDeg = angleParam.limitCurveData.MC2EvaluateCurve(cdepth); float maxAngleRad = math.radians(maxAngleDeg); float angle = MathUtility.Angle(v, tv); float3 rv = v; @@ -537,12 +472,23 @@ namespace MagicaCloth2 // 回転補正 v = cpos - ppos; + vlen = math.length(v); + if (vlen < Define.System.Epsilon) + { + //エッジ長0対処 + //Debug.Log($"NG5"); + goto EndAngleLimit; + } + v /= vlen; var nrot = math.mul(prot, localRot); - var q = MathUtility.FromToRotation(tv, v); + //var q = MathUtility.FromToRotation(tv, v); + var q = MathUtility.FromToRotationWithoutNormalize(tv, v); nrot = math.mul(q, nrot); rotationBufferArray[pindex] = nrot; } + EndAngleLimit: + //===================================================== // Angle Restoration //===================================================== @@ -550,14 +496,31 @@ namespace MagicaCloth2 { //Debug.Log($"pindex:{pindex}, p_pindex:{p_pindex}"); - // 現在のベクトル - float3 v = cpos - ppos; - // 復元すべきベクトル float3 tv = restorationVectorBufferArray[pindex]; + float tvlen = math.length(tv); + if (tvlen < Define.System.Epsilon) + { + //エッジ長0対処 + //Debug.Log($"NG6"); + float3 add = ppos - cpos; + nextPosArray[pindex] = ppos; + velocityPosArray[pindex] = velocityPosArray[pindex] + add; + continue; + } + + // 現在のベクトル + float3 v = cpos - ppos; + float vlen = math.length(v); + if (vlen < Define.System.Epsilon) + { + //エッジ長0対処 + //Debug.Log($"NG7"); + continue; + } // 復元力 - float restorationStiffness = angleParam.restorationStiffness.EvaluateCurveClamp01(cdepth); + float restorationStiffness = angleParam.restorationStiffness.MC2EvaluateCurveClamp01(cdepth); restorationStiffness = math.saturate(restorationStiffness * simulationPower.w); //int _pindex = indexBuffer[i] + p_start; @@ -567,7 +530,7 @@ namespace MagicaCloth2 restorationStiffness *= gravityFalloff; // 球面線形補間 - var q = MathUtility.FromToRotation(v, tv, restorationStiffness); + var q = MathUtility.FromToRotationWithoutNormalize(v / vlen, tv / tvlen, restorationStiffness); float3 rv = math.mul(q, v); // 回転中心割合 @@ -607,6 +570,25 @@ namespace MagicaCloth2 } } } + + // バッファクリア + bindex = tdata.baseLineChunk.startIndex + chunk.startIndex; + for (int a = 0; a < chunk.dataLength; a++, bindex++) + { + int start = baseLineStartDataIndices[bindex]; + int dcnt = baseLineDataCounts[bindex]; + + int dataIndex = start + d_start; + for (int i = 0; i < dcnt; i++, dataIndex++) + { + int l_index = baseLineData[dataIndex]; + int pindex = p_start + l_index; + + lengthBufferArray[pindex] = 0; + localPosBufferArray[pindex] = 0; + restorationVectorBufferArray[pindex] = 0; + } + } } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/AngleConstraint.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/AngleConstraint.cs.meta index 5fc4bb29..96fabe85 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/AngleConstraint.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/AngleConstraint.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/AngleConstraint.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/ColliderCollisionConstraint.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/ColliderCollisionConstraint.cs index d0368824..8ed7e83d 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/ColliderCollisionConstraint.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/ColliderCollisionConstraint.cs @@ -4,10 +4,8 @@ using System; using System.Collections.Generic; using System.Text; -using Unity.Burst; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; -using Unity.Jobs; using Unity.Mathematics; using UnityEngine; @@ -113,6 +111,11 @@ namespace MagicaCloth2 public void GetUsedTransform(HashSet transformSet) { + colliderList.ForEach(x => + { + if (x) + x.GetUsedTransform(transformSet); + }); foreach (var t in collisionBones) { if (t) @@ -122,6 +125,11 @@ namespace MagicaCloth2 public void ReplaceTransform(Dictionary replaceDict) { + colliderList.ForEach(x => + { + if (x) + x.ReplaceTransform(replaceDict); + }); for (int i = 0; i < collisionBones.Count; i++) { var t = collisionBones[i]; @@ -184,9 +192,6 @@ namespace MagicaCloth2 } } - NativeArray tempFrictionArray; - NativeArray tempNormalArray; - //========================================================================================= public ColliderCollisionConstraint() { @@ -195,211 +200,69 @@ namespace MagicaCloth2 public void Dispose() { - tempFrictionArray.DisposeSafe(); - tempNormalArray.DisposeSafe(); - } - - /// - /// 作業バッファ更新 - /// - internal void WorkBufferUpdate() - { - int cnt = MagicaManager.Team.edgeColliderCollisionCount; - if (cnt == 0) - return; - - int pcnt = MagicaManager.Simulation.ParticleCount; - tempFrictionArray.Resize(pcnt); - tempNormalArray.Resize(pcnt * 3); - //if (tempFrictionArray.IsCreated == false || tempFrictionArray.Length < pcnt) - //{ - // if (tempFrictionArray.IsCreated) - // tempFrictionArray.Dispose(); - // tempFrictionArray = new NativeArray(pcnt, Allocator.Persistent); - //} - //if (tempNormalArray.IsCreated == false || tempNormalArray.Length < pcnt * 3) - //{ - // if (tempNormalArray.IsCreated) - // tempNormalArray.Dispose(); - // tempNormalArray = new NativeArray(pcnt * 3, Allocator.Persistent); - //} } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.AppendLine($"[ColliderCollisionConstraint]"); - sb.AppendLine($" -tempFrictionArray:{(tempFrictionArray.IsCreated ? tempFrictionArray.Length : 0)}"); - sb.AppendLine($" -tempNormalArray:{(tempNormalArray.IsCreated ? tempNormalArray.Length : 0)}"); - return sb.ToString(); } //========================================================================================= - /// - /// 制約の解決 - /// - /// - /// - /// - unsafe internal JobHandle SolverConstraint(JobHandle jobHandle) - { - var tm = MagicaManager.Team; - var sm = MagicaManager.Simulation; - var vm = MagicaManager.VMesh; - var cm = MagicaManager.Collider; - - // Point - var job = new PointColliderCollisionConstraintJob() - { - stepParticleIndexArray = sm.processingStepParticle.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - - attributes = vm.attributes.GetNativeArray(), - vertexDepths = vm.vertexDepths.GetNativeArray(), - - teamIdArray = sm.teamIdArray.GetNativeArray(), - nextPosArray = sm.nextPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - collisionNormalArray = sm.collisionNormalArray.GetNativeArray(), - velocityPosArray = sm.velocityPosArray.GetNativeArray(), - basePosArray = sm.basePosArray.GetNativeArray(), - - colliderFlagArray = cm.flagArray.GetNativeArray(), - colliderWorkDataArray = cm.workDataArray.GetNativeArray(), - }; - jobHandle = job.Schedule(sm.processingStepParticle.GetJobSchedulePtr(), 32, jobHandle); - - // Edge - if (tm.edgeColliderCollisionCount > 0) - { - var job2 = new EdgeColliderCollisionConstraintJob() - { - stepEdgeCollisionIndexArray = sm.processingStepEdgeCollision.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - - attributes = vm.attributes.GetNativeArray(), - vertexDepths = vm.vertexDepths.GetNativeArray(), - edgeTeamIdArray = vm.edgeTeamIdArray.GetNativeArray(), - edges = vm.edges.GetNativeArray(), - - nextPosArray = sm.nextPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - collisionNormalArray = sm.collisionNormalArray.GetNativeArray(), - velocityPosArray = sm.velocityPosArray.GetNativeArray(), - - colliderFlagArray = cm.flagArray.GetNativeArray(), - colliderWorkDataArray = cm.workDataArray.GetNativeArray(), - - countArray = sm.countArray, - sumArray = sm.sumArray, - tempFrictionArray = tempFrictionArray, - tempNormalArray = tempNormalArray, - }; - jobHandle = job2.Schedule(sm.processingStepEdgeCollision.GetJobSchedulePtr(), 32, jobHandle); - - // 集計 - var job3 = new SolveEdgeBufferAndClearJob() - { - jobParticleIndexList = sm.processingStepParticle.Buffer, - - nextPosArray = sm.nextPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - velocityPosArray = sm.velocityPosArray.GetNativeArray(), - collisionNormalArray = sm.collisionNormalArray.GetNativeArray(), - - countArray = sm.countArray, - sumArray = sm.sumArray, - tempFrictionArray = tempFrictionArray, - tempNormalArray = tempNormalArray, - }; - jobHandle = job3.Schedule(sm.processingStepParticle.GetJobSchedulePtr(), 32, jobHandle); - } - - return jobHandle; - } - + // Point Solver //========================================================================================= - /// - /// Pointコライダー衝突判定 - /// - [BurstCompile] - struct PointColliderCollisionConstraintJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray stepParticleIndexArray; - + internal static void SolverPointConstraint( + DataChunk chunk, // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - + ref TeamManager.TeamData tdata, + ref ClothParameters param, // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [Unity.Collections.ReadOnly] - public NativeArray vertexDepths; - + ref NativeArray attributes, + ref NativeArray vertexDepths, // particle - [Unity.Collections.ReadOnly] - public NativeArray teamIdArray; - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - [NativeDisableParallelForRestriction] - public NativeArray frictionArray; - [NativeDisableParallelForRestriction] - public NativeArray collisionNormalArray; - [NativeDisableParallelForRestriction] - public NativeArray velocityPosArray; - [Unity.Collections.ReadOnly] - public NativeArray basePosArray; - + ref NativeArray nextPosArray, + ref NativeArray frictionArray, + ref NativeArray collisionNormalArray, + ref NativeArray velocityPosArray, + ref NativeArray basePosArray, // collider - [Unity.Collections.ReadOnly] - public NativeArray colliderFlagArray; - [Unity.Collections.ReadOnly] - public NativeArray colliderWorkDataArray; + ref NativeArray colliderFlagArray, + ref NativeArray colliderWorkDataArray + ) + { + if (tdata.UseColliderCount == 0) + return; + if (param.colliderCollisionConstraint.mode != Mode.Point) + return; + if (chunk.IsValid == false) + return; - // ステップ実行パーティクルごと - public void Execute(int index) + bool isSpring = tdata.IsSpring; + + // ■Point + // パーティクルごと + //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++) { - // このパーティクルは有効であることが保証されている - int pindex = stepParticleIndexArray[index]; - int teamId = teamIdArray[pindex]; - var tdata = teamDataArray[teamId]; - if (tdata.colliderCount == 0) - return; - - // パラメータ - var param = parameterArray[teamId]; - - // モード判定 - var mode = param.colliderCollisionConstraint.mode; - if (mode != Mode.Point) - return; - // パーティクル情報 var nextPos = nextPosArray[pindex]; - int l_index = pindex - tdata.particleChunk.startIndex; - int vindex = tdata.proxyCommonChunk.startIndex + l_index; var attr = attributes[vindex]; if (attr.IsInvalid() || attr.IsDisableCollision()) - return; + continue; if (attr.IsMove() == false && tdata.IsSpring == false) // スプリング利用時は固定頂点も通す - return; + continue; float depth = vertexDepths[vindex]; // BoneSpringでは自動的にソフトコライダーとなる - bool isSpring = tdata.IsSpring; var basePos = isSpring ? basePosArray[pindex] : float3.zero; // ソフトコライダーのみbasePosが必要 // パーティクル半径 - float radius = math.max(param.radiusCurveData.EvaluateCurve(depth), 0.0001f); // safe; + float radius = math.max(param.radiusCurveData.MC2EvaluateCurve(depth), 0.0001f); // safe; // チームスケール倍率 radius *= tdata.scaleRatio; @@ -426,7 +289,7 @@ namespace MagicaCloth2 aabb.Expand(cfr); // BoneSpringでの最大押し出し距離 - float maxLength = isSpring ? math.max(param.colliderCollisionConstraint.limitDistance.EvaluateCurve(depth), 0.0001f) * tdata.scaleRatio : -1; // チームスケール倍率 + float maxLength = isSpring ? math.max(param.colliderCollisionConstraint.limitDistance.MC2EvaluateCurve(depth), 0.0001f) * tdata.scaleRatio : -1; // チームスケール倍率 // チーム内のコライダーをループ int cindex = tdata.colliderChunk.startIndex; @@ -447,7 +310,6 @@ namespace MagicaCloth2 { case ColliderManager.ColliderType.Sphere: // ソフトコライダーはSphereのみ - //dist = PointSphereColliderDetection(ref _nextPos, basePos, radius, aabb, cwork, maxLength, out n); dist = PointSphereColliderDetection(ref _nextPos, basePos, radius, aabb, cwork, isSpring, maxLength, out n); break; case ColliderManager.ColliderType.CapsuleX_Center: @@ -473,6 +335,7 @@ namespace MagicaCloth2 addPos += (_nextPos - nextPos); addN += n; addCnt++; + //Debug.Log($"Collision!"); } // コライダーに一定距離近づいている場合(動摩擦/静止摩擦が影響する) @@ -531,242 +394,209 @@ namespace MagicaCloth2 velocityPosArray[pindex] = velocityPosArray[pindex] + addPos; } } + } - /// - /// Point球衝突判定 - /// - /// - /// - /// - /// - /// - /// - float PointSphereColliderDetection(ref float3 nextpos, in float3 basePos, float radius, in AABB aabb, in ColliderManager.WorkData cwork, bool isSpring, float maxLength, out float3 normal) - { - // ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない! - normal = 0; + static float PointSphereColliderDetection( + ref float3 nextpos, + in float3 basePos, + float radius, + in AABB aabb, + in ColliderManager.WorkData cwork, + bool isSpring, + float maxLength, + out float3 normal + ) + { + // ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない! + normal = 0; - //========================================================= - // AABB判定 - //========================================================= - if (aabb.Overlaps(cwork.aabb) == false) - return float.MaxValue; + //========================================================= + // AABB判定 + //========================================================= + if (aabb.Overlaps(cwork.aabb) == false) + return float.MaxValue; - var oldpos = nextpos; + var oldpos = nextpos; - //========================================================= - // 衝突解決 - //========================================================= - float3 coldpos = cwork.oldPos.c0; - float3 cpos = cwork.nextPos.c0; - float cradius = cwork.radius.x; + //========================================================= + // 衝突解決 + //========================================================= + float3 coldpos = cwork.oldPos.c0; + float3 cpos = cwork.nextPos.c0; + float cradius = cwork.radius.x; - // 移動前のコライダーに対するローカル位置から移動後コライダーの押し出し平面を求める - float3 c, n, v; - v = nextpos - coldpos; - Develop.Assert(math.length(v) > 0.0f); - n = math.normalize(v); - c = cpos + n * (cradius + radius); + // 移動前のコライダーに対するローカル位置から移動後コライダーの押し出し平面を求める + float3 c, n, v; + v = nextpos - coldpos; + Develop.Assert(math.length(v) > 0.0f); + n = math.normalize(v); + c = cpos + n * (cradius + radius); - // 衝突法線 - normal = n; + // 衝突法線 + normal = n; - // c = 平面位置 - // n = 平面方向 - // 平面衝突判定と押し出し - //return MathUtility.IntersectPointPlaneDist(c, n, nextpos, out nextpos); - float dist = MathUtility.IntersectPointPlaneDist(c, n, nextpos, out nextpos); + // c = 平面位置 + // n = 平面方向 + // 平面衝突判定と押し出し + //return MathUtility.IntersectPointPlaneDist(c, n, nextpos, out nextpos); + float dist = MathUtility.IntersectPointPlaneDist(c, n, nextpos, out nextpos); #if true - // BoneSpring - if (maxLength > 0.0f) - { - // (1)距離制限 - nextpos = MathUtility.ClampDistance(basePos, nextpos, maxLength); + // BoneSpring + if (maxLength > 0.0f) + { + // (1)距離制限 + nextpos = MathUtility.ClampDistance(basePos, nextpos, maxLength); - // (2)反発力減衰 - float l = math.distance(basePos, nextpos); - float t = math.saturate(l / radius); // 半径基準 - //float t = math.saturate(l / maxLength); - t = math.lerp(0.0f, 0.85f, t); // 最低でも少し反発を残す - nextpos = math.lerp(nextpos, oldpos, t); + // (2)反発力減衰 + float l = math.distance(basePos, nextpos); + float t = math.saturate(l / radius); // 半径基準 + //float t = math.saturate(l / maxLength); + t = math.lerp(0.0f, 0.85f, t); // 最低でも少し反発を残す + nextpos = math.lerp(nextpos, oldpos, t); - // 衝突平面までの距離は摩擦影響を抑えるためスケールする - dist *= 3.0f; - } + // 衝突平面までの距離は摩擦影響を抑えるためスケールする + dist *= 3.0f; + } #endif - return dist; - } + return dist; + } - /// - /// Point平面衝突判定(無限平面) - /// - /// - /// - /// - /// - /// - float PointPlaneColliderDetction(ref float3 nextpos, float radius, in ColliderManager.WorkData cwork, out float3 normal) - { - // ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない! + static float PointPlaneColliderDetction( + ref float3 nextpos, + float radius, + in ColliderManager.WorkData cwork, + out float3 normal + ) + { + // ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない! - // コライダー情報 - var cpos = cwork.nextPos.c0; - var n = cwork.oldPos.c0; // ここに押し出し法線 + // コライダー情報 + var cpos = cwork.nextPos.c0; + var n = cwork.oldPos.c0; // ここに押し出し法線 - // 衝突法線 - normal = n; + // 衝突法線 + normal = n; - // c = 平面位置(パーティクル半径分オフセット) - // n = 平面方向 - // 平面衝突判定と押し出し - // 平面との距離を返す(押し出しの場合は0.0) - return MathUtility.IntersectPointPlaneDist(cpos + n * radius, n, nextpos, out nextpos); - } + // c = 平面位置(パーティクル半径分オフセット) + // n = 平面方向 + // 平面衝突判定と押し出し + // 平面との距離を返す(押し出しの場合は0.0) + return MathUtility.IntersectPointPlaneDist(cpos + n * radius, n, nextpos, out nextpos); + } - /// - /// Pointカプセル衝突判定 - /// - /// - /// - /// - /// - /// - /// - /// - float PointCapsuleColliderDetection(ref float3 nextpos, float radius, in AABB aabb, in ColliderManager.WorkData cwork, out float3 normal) - { - // ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない! - normal = 0; + static float PointCapsuleColliderDetection( + ref float3 nextpos, + float radius, + in AABB aabb, + in ColliderManager.WorkData cwork, + out float3 normal + ) + { + // ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない! + normal = 0; - //========================================================= - // AABB判定 - //========================================================= - if (aabb.Overlaps(cwork.aabb) == false) - return float.MaxValue; + //========================================================= + // AABB判定 + //========================================================= + if (aabb.Overlaps(cwork.aabb) == false) + return float.MaxValue; - // コライダー情報 - float3 soldpos = cwork.oldPos.c0; - float3 eoldpos = cwork.oldPos.c1; - float3 spos = cwork.nextPos.c0; - float3 epos = cwork.nextPos.c1; - float sr = cwork.radius.x; - float er = cwork.radius.y; + // コライダー情報 + float3 soldpos = cwork.oldPos.c0; + float3 eoldpos = cwork.oldPos.c1; + float3 spos = cwork.nextPos.c0; + float3 epos = cwork.nextPos.c1; + float sr = cwork.radius.x; + float er = cwork.radius.y; - //========================================================= - // 衝突解決 - //========================================================= - // 移動前のコライダー位置から押し出し平面を割り出す - float t = MathUtility.ClosestPtPointSegmentRatio(nextpos, soldpos, eoldpos); - float r = math.lerp(sr, er, t); - float3 d = math.lerp(soldpos, eoldpos, t); - float3 v = nextpos - d; + //========================================================= + // 衝突解決 + //========================================================= + // 移動前のコライダー位置から押し出し平面を割り出す + float t = MathUtility.ClosestPtPointSegmentRatio(nextpos, soldpos, eoldpos); + float r = math.lerp(sr, er, t); + float3 d = math.lerp(soldpos, eoldpos, t); + float3 v = nextpos - d; - // 移動前コライダーのローカルベクトル - float3 lv = math.mul(cwork.inverseOldRot, v); + // 移動前コライダーのローカルベクトル + float3 lv = math.mul(cwork.inverseOldRot, v); - // 移動後コライダーに変換 - d = math.lerp(spos, epos, t); - v = math.mul(cwork.rot, lv); - Develop.Assert(math.length(v) > 0.0f); - float3 n = math.normalize(v); - float3 c = d + n * (r + radius); + // 移動後コライダーに変換 + d = math.lerp(spos, epos, t); + v = math.mul(cwork.rot, lv); + Develop.Assert(math.length(v) > 0.0f); + float3 n = math.normalize(v); + float3 c = d + n * (r + radius); - // 衝突法線 - normal = n; + // 衝突法線 + normal = n; - // c = 平面位置 - // n = 平面方向 - // 平面衝突判定と押し出し - return MathUtility.IntersectPointPlaneDist(c, n, nextpos, out nextpos); - } + // c = 平面位置 + // n = 平面方向 + // 平面衝突判定と押し出し + return MathUtility.IntersectPointPlaneDist(c, n, nextpos, out nextpos); } //========================================================================================= - /// - /// Edgeコライダー衝突判定 - /// - [BurstCompile] - unsafe struct EdgeColliderCollisionConstraintJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray stepEdgeCollisionIndexArray; - + // Edge Solver + //========================================================================================= + internal unsafe static void SolverEdgeConstraint( + DataChunk chunk, // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - + ref TeamManager.TeamData tdata, + ref ClothParameters param, // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [Unity.Collections.ReadOnly] - public NativeArray vertexDepths; - [Unity.Collections.ReadOnly] - public NativeArray edgeTeamIdArray; - [Unity.Collections.ReadOnly] - public NativeArray edges; - + ref NativeArray attributes, + ref NativeArray vertexDepths, + ref NativeArray edges, // particle - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - [NativeDisableParallelForRestriction] - public NativeArray frictionArray; - [NativeDisableParallelForRestriction] - public NativeArray collisionNormalArray; - [NativeDisableParallelForRestriction] - public NativeArray velocityPosArray; - + ref NativeArray nextPosArray, // collider - [Unity.Collections.ReadOnly] - public NativeArray colliderFlagArray; - [Unity.Collections.ReadOnly] - public NativeArray colliderWorkDataArray; + ref NativeArray colliderFlagArray, + ref NativeArray colliderWorkDataArray, + // buffer2 + ref NativeArray tempVectorBufferA, + ref NativeArray tempVectorBufferB, + ref NativeArray tempCountBuffer, + ref NativeArray tempFloatBufferA + ) + { + if (tdata.UseColliderCount == 0) + return; + if (param.colliderCollisionConstraint.mode != Mode.Edge) + return; + if (chunk.IsValid == false) + return; - // output - [NativeDisableParallelForRestriction] - public NativeArray countArray; - [NativeDisableParallelForRestriction] - public NativeArray sumArray; - [NativeDisableParallelForRestriction] - public NativeArray tempFrictionArray; - [NativeDisableParallelForRestriction] - public NativeArray tempNormalArray; + // ■Edge + int* vecAPt = (int*)tempVectorBufferA.GetUnsafePtr(); + int* vecBPt = (int*)tempVectorBufferB.GetUnsafePtr(); + int* cntPt = (int*)tempCountBuffer.GetUnsafePtr(); + int* floatPt = (int*)tempFloatBufferA.GetUnsafePtr(); - // ステップ実行エッジごと - public void Execute(int index) + // ■計算 + // エッジごと + int vstart = tdata.proxyCommonChunk.startIndex; + //int eindex = tdata.proxyEdgeChunk.startIndex; + int eindex = tdata.proxyEdgeChunk.startIndex + chunk.startIndex; + //for (int k = 0; k < tdata.proxyEdgeChunk.dataLength; k++, eindex++) + for (int k = 0; k < chunk.dataLength; k++, eindex++) { - // このエッジは有効であることが保証されている - int eindex = stepEdgeCollisionIndexArray[index]; - int teamId = edgeTeamIdArray[eindex]; - var tdata = teamDataArray[teamId]; - if (tdata.colliderCount == 0) - return; - - // パラメータ - var param = parameterArray[teamId]; - - // モード判定 - var mode = param.colliderCollisionConstraint.mode; - if (mode != Mode.Edge) - return; - // エッジ情報 - int vstart = tdata.proxyCommonChunk.startIndex; int2 edge = edges[eindex]; int2 vE = edge + vstart; var attrE0 = attributes[vE.x]; var attrE1 = attributes[vE.y]; // 両方とも固定なら不要 if (attrE0.IsMove() == false && attrE1.IsMove() == false) - return; + continue; int pstart = tdata.particleChunk.startIndex; int2 pE = edge + pstart; float3x2 nextPosE = new float3x2(nextPosArray[pE.x], nextPosArray[pE.y]); float2 depthE = new float2(vertexDepths[vE.x], vertexDepths[vE.y]); - float2 radiusE = new float2(param.radiusCurveData.EvaluateCurve(depthE.x), param.radiusCurveData.EvaluateCurve(depthE.y)); + float2 radiusE = new float2(param.radiusCurveData.MC2EvaluateCurve(depthE.x), param.radiusCurveData.MC2EvaluateCurve(depthE.y)); // チームスケール倍率 radiusE *= tdata.scaleRatio; @@ -781,12 +611,6 @@ namespace MagicaCloth2 float3 collisionNormal = 0; float3 n = 0; - // 書き込みポインタ - int* cntPt = (int*)countArray.GetUnsafePtr(); - int* sumPt = (int*)sumArray.GetUnsafePtr(); - int* frictionPt = (int*)tempFrictionArray.GetUnsafePtr(); - int* normalPt = (int*)tempNormalArray.GetUnsafePtr(); - // エッジAABB var aabbE = new AABB(nextPosE.c0 - radiusE.x, nextPosE.c0 + radiusE.x); var aabbE1 = new AABB(nextPosE.c1 - radiusE.y, nextPosE.c1 + radiusE.y); @@ -868,8 +692,8 @@ namespace MagicaCloth2 addPos *= t; // 書き戻し - InterlockUtility.AddFloat3(pE.x, addPos.c0, cntPt, sumPt); - InterlockUtility.AddFloat3(pE.y, addPos.c1, cntPt, sumPt); + InterlockUtility.AddFloat3(pE.x, addPos.c0, cntPt, vecAPt); + InterlockUtility.AddFloat3(pE.y, addPos.c1, cntPt, vecAPt); } } @@ -881,316 +705,356 @@ namespace MagicaCloth2 var friction = 1.0f - math.saturate(mindist / cfr); // 大きい場合のみ上書き - InterlockUtility.Max(pE.x, friction, frictionPt); - InterlockUtility.Max(pE.y, friction, frictionPt); + InterlockUtility.Max(pE.x, friction, floatPt); + InterlockUtility.Max(pE.y, friction, floatPt); // 摩擦用接触法線平均化 //Develop.Assert(math.length(collisionNormal) > 0.0f); collisionNormal = math.normalize(collisionNormal); // 接触法線集計(すべて加算する) - InterlockUtility.AddFloat3(pE.x, collisionNormal, normalPt); - InterlockUtility.AddFloat3(pE.y, collisionNormal, normalPt); + InterlockUtility.AddFloat3(pE.x, collisionNormal, vecBPt); + InterlockUtility.AddFloat3(pE.y, collisionNormal, vecBPt); } } - - float EdgeSphereColliderDetection(ref float3x2 nextPosE, in float2 radiusE, in AABB aabbE, float cfr, in ColliderManager.WorkData cwork, out float3 normal) - { - // ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない! - normal = 0; - - //========================================================= - // AABB判定 - //========================================================= - if (aabbE.Overlaps(cwork.aabb) == false) - return float.MaxValue; - - // コライダー情報 - float3 coldpos = cwork.oldPos.c0; - float3 cpos = cwork.nextPos.c0; - float cradius = cwork.radius.x; - - //========================================================= - // 衝突判定 - //========================================================= - // 移動前球に対する線分の最近接点 - float s; - s = MathUtility.ClosestPtPointSegmentRatio(coldpos, nextPosE.c0, nextPosE.c1); - float3 c = math.lerp(nextPosE.c0, nextPosE.c1, s); - - // 最近接点の距離 - var v = c - coldpos; - float clen = math.length(v); - if (clen < 1e-09f) - return float.MaxValue; - - // 押し出し法線 - float3 n = v / clen; - normal = n; - - // 変位 - float3 db = cpos - coldpos; - - // 変位をnに投影して距離チェック - float l1 = math.dot(n, db); - float l = clen - l1; - - // 厚み - float rA = math.lerp(radiusE.x, radiusE.y, s); - float rB = cradius; - float thickness = rA + rB; - - // 接触判定 - if (l > (thickness + cfr)) - return float.MaxValue; - - //========================================================= - // 衝突解決 - //========================================================= - // 接触法線に現在の距離を投影させる - v = c - cpos; - l = math.dot(n, v); - if (l > thickness) - { - // 接触なし - // 接触面までの距離を返す - return l - thickness; - } - - // 離す距離 - float C = thickness - l; - - // エッジのみを引き離す - //float b0 = 1.0f - t; - //float b1 = t; - float2 b = new float2(1.0f - s, s); - - //float3 grad0 = n * b0; - //float3 grad1 = n * b1; - float3x2 grad = new float3x2(n * b.x, n * b.y); - - //float S = b0 * b0 + b1 * b1; - float S = math.dot(b, b); - if (S == 0.0f) - return float.MaxValue; - - S = C / S; - - //float3 corr0 = S * grad0; - //float3 corr1 = S * grad1; - float3x2 corr = grad * S; - - //========================================================= - // 反映 - //========================================================= - nextPosE += corr; - - // 押し出し距離を返す - return -C; - } - - float EdgeCapsuleColliderDetection(ref float3x2 nextPosE, in float2 radiusE, in AABB aabbE, float cfr, in ColliderManager.WorkData cwork, out float3 normal) - { - // ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない! - normal = 0; - - //========================================================= - // AABB判定 - //========================================================= - if (aabbE.Overlaps(cwork.aabb) == false) - return float.MaxValue; - - // コライダー情報 - float3 soldpos = cwork.oldPos.c0; - float3 eoldpos = cwork.oldPos.c1; - float3 spos = cwork.nextPos.c0; - float3 epos = cwork.nextPos.c1; - float sr = cwork.radius.x; - float er = cwork.radius.y; - - //========================================================= - // 衝突判定 - //========================================================= - // 移動前の2つの線分の最近接点 - float s, t; - float3 cA, cB; - float csqlen = MathUtility.ClosestPtSegmentSegment(nextPosE.c0, nextPosE.c1, soldpos, eoldpos, out s, out t, out cA, out cB); - float clen = math.sqrt(csqlen); // 最近接点の距離 - if (clen < 1e-09f) - return float.MaxValue; - - // 押出法線 - var v = cA - cB; - Develop.Assert(math.length(v) > 0.0f); - float3 n = math.normalize(v); - normal = n; - - // 変位 - float3 dB0 = spos - soldpos; - float3 dB1 = epos - eoldpos; - - - // 最近接点での変位 - float3 db = math.lerp(dB0, dB1, t); - - // 変位da,dbをnに投影して距離チェック - float l1 = math.dot(n, db); - float l = clen - l1; - - // 厚み - float rA = math.lerp(radiusE.x, radiusE.y, s); - float rB = math.lerp(sr, er, t); - float thickness = rA + rB; - - // 接触判定 - if (l > (thickness + cfr)) - return float.MaxValue; - - //========================================================= - // 衝突解決 - //========================================================= - // 接触法線に現在の距離を投影させる - var d = math.lerp(spos, epos, t); - v = cA - d; - l = math.dot(n, v); - //Debug.Log($"l:{l}"); - if (l > thickness) - { - // 接触なし - // 接触面までの距離を返す - return l - thickness; - } - - // 離す距離 - float C = thickness - l; - //Debug.Log($"C:{C}"); - - // エッジのみを引き離す - //float b0 = 1.0f - s; - //float b1 = s; - float2 b = new float2(1.0f - s, s); - - //float3 grad0 = n * b0; - //float3 grad1 = n * b1; - float3x2 grad = new float3x2(n * b.x, n * b.y); - - //float S = invMass0 * b0 * b0 + invMass1 * b1 * b1; - float S = math.dot(b, b); - if (S == 0.0f) - return float.MaxValue; - - S = C / S; - - //float3 corr0 = S * invMass0 * grad0; - //float3 corr1 = S * invMass1 * grad1; - float3x2 corr = grad * S; - - //========================================================= - // 反映 - //========================================================= - nextPosE += corr; - - // 押し出し距離を返す - return -C; - } - - float EdgePlaneColliderDetection(ref float3x2 nextPosE, in float2 radiusE, in ColliderManager.WorkData cwork, out float3 normal) - { - // ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない! - - // コライダー情報 - var cpos = cwork.nextPos.c0; - var n = cwork.oldPos.c0; // ここに押し出し法線 - - // 衝突法線 - normal = n; - - // c = 平面位置 - // n = 平面方向 - // 平面衝突判定と押し出し - // 平面との距離を返す(押し出しの場合は0.0) - float dist0 = MathUtility.IntersectPointPlaneDist(cpos + n * radiusE.x, n, nextPosE.c0, out nextPosE.c0); - float dist1 = MathUtility.IntersectPointPlaneDist(cpos + n * radiusE.y, n, nextPosE.c1, out nextPosE.c1); - - return math.min(dist0, dist1); - } } - /// - /// エッジコライダーコリジョン結果の集計 - /// - [BurstCompile] - struct SolveEdgeBufferAndClearJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray jobParticleIndexList; - + internal unsafe static void SumEdgeConstraint( + DataChunk chunk, + // team + ref TeamManager.TeamData tdata, + ref ClothParameters param, // particle - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - [NativeDisableParallelForRestriction] - public NativeArray frictionArray; - [NativeDisableParallelForRestriction] - public NativeArray collisionNormalArray; - [NativeDisableParallelForRestriction] - public NativeArray velocityPosArray; + ref NativeArray nextPosArray, + ref NativeArray frictionArray, + ref NativeArray collisionNormalArray, + // buffer2 + ref NativeArray tempVectorBufferA, + ref NativeArray tempVectorBufferB, + ref NativeArray tempCountBuffer, + ref NativeArray tempFloatBufferA + ) + { + if (tdata.UseColliderCount == 0) + return; + if (param.colliderCollisionConstraint.mode != Mode.Edge) + return; + if (chunk.IsValid == false) + return; - // aggregate - [NativeDisableParallelForRestriction] - public NativeArray countArray; - [NativeDisableParallelForRestriction] - public NativeArray sumArray; - [NativeDisableParallelForRestriction] - public NativeArray tempFrictionArray; - [NativeDisableParallelForRestriction] - public NativeArray tempNormalArray; + // ■Edge + int* vecAPt = (int*)tempVectorBufferA.GetUnsafePtr(); + int* vecBPt = (int*)tempVectorBufferB.GetUnsafePtr(); + int* cntPt = (int*)tempCountBuffer.GetUnsafePtr(); + int* floatPt = (int*)tempFloatBufferA.GetUnsafePtr(); - // ステップ有効パーティクルごと - public void Execute(int index) + // ■集計 + // パーティクルごと + //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++) { - int pindex = jobParticleIndexList[index]; - // nextpos - int count = countArray[pindex]; - int dataIndex = pindex * 3; + int count = tempCountBuffer[pindex]; if (count > 0) { - float3 add = InterlockUtility.ReadAverageFloat3(pindex, countArray, sumArray); + float3 add = InterlockUtility.ReadAverageFloat3(pindex, cntPt, vecAPt); // 書き出し nextPosArray[pindex] = nextPosArray[pindex] + add; - - // 速度影響 - //float attn = param.colliderCollisionConstraint.colliderVelocityAttenuation; - //float attn = Define.System.ColliderCollisionVelocityAttenuation; - //velocityPosArray[pindex] = velocityPosArray[pindex] + add * attn; - - // バッファクリア - countArray[pindex] = 0; - sumArray[dataIndex] = 0; - sumArray[dataIndex + 1] = 0; - sumArray[dataIndex + 2] = 0; } // friction - float f = InterlockUtility.ReadFloat(pindex, tempFrictionArray); + float f = InterlockUtility.ReadFloat(pindex, floatPt); if (f > 0.0f && f > frictionArray[pindex]) { frictionArray[pindex] = f; - tempFrictionArray[pindex] = 0; } // collision normal - float3 n = InterlockUtility.ReadFloat3(pindex, tempNormalArray); + float3 n = InterlockUtility.ReadFloat3(pindex, vecBPt); if (math.lengthsq(n) > 0.0f) { n = math.normalize(n); collisionNormalArray[pindex] = n; - tempNormalArray[dataIndex] = 0; - tempNormalArray[dataIndex + 1] = 0; - tempNormalArray[dataIndex + 2] = 0; } + + // バッファクリア + tempVectorBufferA[pindex] = 0; + tempVectorBufferB[pindex] = 0; + tempCountBuffer[pindex] = 0; + tempFloatBufferA[pindex] = 0; } } + + static float EdgeSphereColliderDetection( + ref float3x2 nextPosE, + in float2 radiusE, + in AABB aabbE, + float cfr, + in ColliderManager.WorkData cwork, + out float3 normal + ) + { + // ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない! + normal = 0; + + //========================================================= + // AABB判定 + //========================================================= + if (aabbE.Overlaps(cwork.aabb) == false) + return float.MaxValue; + + // コライダー情報 + float3 coldpos = cwork.oldPos.c0; + float3 cpos = cwork.nextPos.c0; + float cradius = cwork.radius.x; + + //========================================================= + // 衝突判定 + //========================================================= + // 移動前球に対する線分の最近接点 + float s; + s = MathUtility.ClosestPtPointSegmentRatio(coldpos, nextPosE.c0, nextPosE.c1); + float3 c = math.lerp(nextPosE.c0, nextPosE.c1, s); + + // 最近接点の距離 + var v = c - coldpos; + float clen = math.length(v); + if (clen < 1e-09f) + return float.MaxValue; + + // 押し出し法線 + float3 n = v / clen; + normal = n; + + // 変位 + float3 db = cpos - coldpos; + + // 変位をnに投影して距離チェック + float l1 = math.dot(n, db); + float l = clen - l1; + + // 厚み + float rA = math.lerp(radiusE.x, radiusE.y, s); + float rB = cradius; + float thickness = rA + rB; + + // 接触判定 + if (l > (thickness + cfr)) + return float.MaxValue; + + //========================================================= + // 衝突解決 + //========================================================= + // 接触法線に現在の距離を投影させる + v = c - cpos; + l = math.dot(n, v); + if (l > thickness) + { + // 接触なし + // 接触面までの距離を返す + return l - thickness; + } + + // 離す距離 + float C = thickness - l; + + // エッジのみを引き離す + //float b0 = 1.0f - t; + //float b1 = t; + float2 b = new float2(1.0f - s, s); + + //float3 grad0 = n * b0; + //float3 grad1 = n * b1; + float3x2 grad = new float3x2(n * b.x, n * b.y); + + //float S = b0 * b0 + b1 * b1; + float S = math.dot(b, b); + if (S == 0.0f) + return float.MaxValue; + + S = C / S; + + //float3 corr0 = S * grad0; + //float3 corr1 = S * grad1; + float3x2 corr = grad * S; + + //========================================================= + // 反映 + //========================================================= + nextPosE += corr; + + // 押し出し距離を返す + return -C; + } + + static float EdgeCapsuleColliderDetection( + ref float3x2 nextPosE, + in float2 radiusE, + in AABB aabbE, + float cfr, + in ColliderManager.WorkData cwork, + out float3 normal + ) + { + // ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない! + normal = 0; + + //========================================================= + // AABB判定 + //========================================================= + if (aabbE.Overlaps(cwork.aabb) == false) + return float.MaxValue; + + // コライダー情報 + float3 soldpos = cwork.oldPos.c0; + float3 eoldpos = cwork.oldPos.c1; + float3 spos = cwork.nextPos.c0; + float3 epos = cwork.nextPos.c1; + float sr = cwork.radius.x; + float er = cwork.radius.y; + + //========================================================= + // 衝突判定 + //========================================================= + // 移動前の2つの線分の最近接点 + float s, t; + float3 cA, cB; + float csqlen = MathUtility.ClosestPtSegmentSegment(nextPosE.c0, nextPosE.c1, soldpos, eoldpos, out s, out t, out cA, out cB); + float clen = math.sqrt(csqlen); // 最近接点の距離 + if (clen < 1e-09f) + return float.MaxValue; + + // 押出法線 + var v = cA - cB; + float3 n = v / clen; + normal = n; + +#if !MC2_DISABLE_EDGE_COLLISION_EXTENSION + // ★カプセル半径を考慮した補正 + // これまでのエッジ-カプセル判定はカプセルの半径が始点と終点で同じであることが前提となっていた + // そのためカプセルの始点と終点の半径が異なると間違った衝突判定が行われてしまい、それが原因で大きな振動が発生していた + // (これはBoneClothのようにカプセルエッジよりメッシュエッジのほうが長い場合に顕著になる) + // そこで始点と終点の半径が異なる場合は、最初の計算の最近接点方向からカプセルエッジを半径分シフトし、 + // それをもとに再度エッジ-エッジ判定を行うように修正した + // これは完璧ではないがおおよそ理想的な判定を行うようになり、また振動の問題も大幅に解決できる + // (ただし小刻みな振動はまだ発生することがある) + if (sr != er) + { + // 押し出し法線方向にカプセル半径を考慮してカプセルの中心線をシフトさせる + float3 soldpos2 = soldpos + n * sr; + float3 eoldpos2 = eoldpos + n * er; + + // この線分で再び最近接点(s/t)を計算する + MathUtility.ClosestPtSegmentSegment2(nextPosE.c0, nextPosE.c1, soldpos2, eoldpos2, out s, out t); + + // 最終的にはこのシフト後のsとtを利用するように結果を書き換える + cA = math.lerp(nextPosE.c0, nextPosE.c1, s); + cB = math.lerp(soldpos, eoldpos, t); + v = cA - cB; + clen = math.length(v); + n = v / clen; + normal = n; + } +#endif + + // 変位 + float3 dB0 = spos - soldpos; + float3 dB1 = epos - eoldpos; + + + // 最近接点での変位 + float3 db = math.lerp(dB0, dB1, t); + + // 変位da,dbをnに投影して距離チェック + float l1 = math.dot(n, db); + float l = clen - l1; + + // 厚み + float rA = math.lerp(radiusE.x, radiusE.y, s); + float rB = math.lerp(sr, er, t); + float thickness = rA + rB; + + // 接触判定 + if (l > (thickness + cfr)) + return float.MaxValue; + + //========================================================= + // 衝突解決 + //========================================================= + // 接触法線に現在の距離を投影させる + var d = math.lerp(spos, epos, t); + v = cA - d; + l = math.dot(n, v); + //Debug.Log($"l:{l}"); + if (l > thickness) + { + // 接触なし + // 接触面までの距離を返す + return l - thickness; + } + + // 離す距離 + float C = thickness - l; + //Debug.Log($"C:{C}"); + + // エッジのみを引き離す + //float b0 = 1.0f - s; + //float b1 = s; + float2 b = new float2(1.0f - s, s); + + //float3 grad0 = n * b0; + //float3 grad1 = n * b1; + float3x2 grad = new float3x2(n * b.x, n * b.y); + + //float S = invMass0 * b0 * b0 + invMass1 * b1 * b1; + float S = math.dot(b, b); + if (S == 0.0f) + return float.MaxValue; + + S = C / S; + + //float3 corr0 = S * invMass0 * grad0; + //float3 corr1 = S * invMass1 * grad1; + float3x2 corr = grad * S; + + //========================================================= + // 反映 + //========================================================= + nextPosE += corr; + + // 押し出し距離を返す + return -C; + } + + static float EdgePlaneColliderDetection( + ref float3x2 nextPosE, + in float2 radiusE, + in ColliderManager.WorkData cwork, + out float3 normal + ) + { + // ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない! + + // コライダー情報 + var cpos = cwork.nextPos.c0; + var n = cwork.oldPos.c0; // ここに押し出し法線 + + // 衝突法線 + normal = n; + + // c = 平面位置 + // n = 平面方向 + // 平面衝突判定と押し出し + // 平面との距離を返す(押し出しの場合は0.0) + float dist0 = MathUtility.IntersectPointPlaneDist(cpos + n * radiusE.x, n, nextPosE.c0, out nextPosE.c0); + float dist1 = MathUtility.IntersectPointPlaneDist(cpos + n * radiusE.y, n, nextPosE.c1, out nextPosE.c1); + + return math.min(dist0, dist1); + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/ColliderCollisionConstraint.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/ColliderCollisionConstraint.cs.meta index afa12400..7c3aa3d9 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/ColliderCollisionConstraint.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/ColliderCollisionConstraint.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/ColliderCollisionConstraint.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/DistanceConstraint.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/DistanceConstraint.cs index acfbc158..5ffbd703 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/DistanceConstraint.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/DistanceConstraint.cs @@ -4,9 +4,7 @@ using System; using System.Collections.Generic; using System.Text; -using Unity.Burst; using Unity.Collections; -using Unity.Jobs; using Unity.Mathematics; using UnityEngine; @@ -85,9 +83,10 @@ namespace MagicaCloth2 /// /// 制約データ /// - internal class ConstraintData : IValid + [System.Serializable] + public class ConstraintData : IValid { - internal ResultCode result; + public ResultCode result; public uint[] indexArray; public ushort[] dataArray; @@ -151,7 +150,7 @@ namespace MagicaCloth2 /// 制約データの作成 /// /// - internal static ConstraintData CreateData(VirtualMesh proxyMesh, in ClothParameters parameters) + public static ConstraintData CreateData(VirtualMesh proxyMesh, in ClothParameters parameters) { var constraintData = new ConstraintData(); @@ -216,7 +215,7 @@ namespace MagicaCloth2 for (int l = 0; l < ecnt; l++) { int2 edge = proxyMesh.edges[l]; - var tset = proxyMesh.edgeToTriangles.ToFixedList128Bytes(edge); + var tset = proxyMesh.edgeToTriangles.MC2ToFixedList128Bytes(edge); int tcnt = tset.Length; if (tcnt < 2) continue; @@ -377,124 +376,55 @@ namespace MagicaCloth2 } //========================================================================================= - /// - /// 制約の解決 - /// - /// - /// - /// - unsafe internal JobHandle SolverConstraint(JobHandle jobHandle) - { - var tm = MagicaManager.Team; - var sm = MagicaManager.Simulation; - var vm = MagicaManager.VMesh; - - var job = new DistanceConstraintJob() - { - simulationPower = MagicaManager.Time.SimulationPower, - - stepParticleIndexArray = sm.processingStepParticle.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - - attributes = vm.attributes.GetNativeArray(), - depthArray = vm.vertexDepths.GetNativeArray(), - - teamIdArray = sm.teamIdArray.GetNativeArray(), - nextPosArray = sm.nextPosArray.GetNativeArray(), - basePosArray = sm.basePosArray.GetNativeArray(), - velocityPosArray = sm.velocityPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - - //stepBasicPositionBuffer = sm.stepBasicPositionBuffer, - - indexArray = indexArray.GetNativeArray(), - dataArray = dataArray.GetNativeArray(), - distanceArray = distanceArray.GetNativeArray(), - }; - jobHandle = job.Schedule(sm.processingStepParticle.GetJobSchedulePtr(), 32, jobHandle); - - return jobHandle; - } - - /// - /// 距離制約の解決 - /// - [BurstCompile] - struct DistanceConstraintJob : IJobParallelForDefer - { - public float4 simulationPower; - - [Unity.Collections.ReadOnly] - public NativeArray stepParticleIndexArray; - + // Solver + //========================================================================================= + internal static void SolverConstraint( + DataChunk chunk, + float4 simulationPower, // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - + ref TeamManager.TeamData tdata, + ref ClothParameters param, // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [Unity.Collections.ReadOnly] - public NativeArray depthArray; - + ref NativeArray attributes, + ref NativeArray depthArray, // particle - [Unity.Collections.ReadOnly] - public NativeArray teamIdArray; - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - [Unity.Collections.ReadOnly] - public NativeArray basePosArray; - [NativeDisableParallelForRestriction] - public NativeArray velocityPosArray; - [Unity.Collections.ReadOnly] - public NativeArray frictionArray; - - // buffer - //[Unity.Collections.ReadOnly] - //public NativeArray stepBasicPositionBuffer; - + ref NativeArray nextPosArray, + ref NativeArray basePosArray, + ref NativeArray velocityPosArray, + ref NativeArray frictionArray, // constrants - [Unity.Collections.ReadOnly] - public NativeArray indexArray; - [Unity.Collections.ReadOnly] - public NativeArray dataArray; - [Unity.Collections.ReadOnly] - public NativeArray distanceArray; + ref NativeArray indexArray, + ref NativeArray dataArray, + ref NativeArray distanceArray + ) + { + var sc = tdata.distanceStartChunk; + var dc = tdata.distanceDataChunk; + if (sc.dataLength == 0) + return; + int c_start = sc.startIndex; + int d_start = dc.startIndex; - // ステップ有効パーティクルごと - public void Execute(int index) + // 復元を基本姿勢で行うかアニメーション後の姿勢で行うかの判定 + float blendRatio = tdata.animationPoseRatio; + + // スケール倍率 + float scl = tdata.InitScale * tdata.scaleRatio; + + bool isSpring = tdata.IsSpring; + + // パーティクルごと + int p_start = tdata.particleChunk.startIndex; + int pindex = p_start + chunk.startIndex; + //int pindex = p_start; + int v_start = tdata.proxyCommonChunk.startIndex; + int vindex = v_start + chunk.startIndex; + //int vindex = v_start; + int dataIndex = chunk.startIndex; + //int dataIndex = 0; + //for (int k = 0; k < tdata.particleChunk.dataLength; k++, pindex++, vindex++, dataIndex++) + for (int k = 0; k < chunk.dataLength; k++, pindex++, vindex++, dataIndex++) { - // pindexのチームは有効であることが保証されている - int pindex = stepParticleIndexArray[index]; - - int teamId = teamIdArray[pindex]; - var tdata = teamDataArray[teamId]; - var parameter = parameterArray[teamId]; - - // 復元を基本姿勢で行うかアニメーション後の姿勢で行うかの判定 - float blendRatio = tdata.animationPoseRatio; - - // スケール倍率 - float scl = tdata.InitScale * tdata.scaleRatio; - - int p_start = tdata.particleChunk.startIndex; - int l_index = pindex - p_start; - - var sc = tdata.distanceStartChunk; - var dc = tdata.distanceDataChunk; - - if (sc.dataLength == 0) - return; - - int c_start = sc.startIndex; - int d_start = dc.startIndex; - int v_start = tdata.proxyCommonChunk.startIndex; - int vindex = v_start + l_index; - // パーティクル情報 var nextPos = nextPosArray[pindex]; var attr = attributes[vindex]; @@ -502,36 +432,31 @@ namespace MagicaCloth2 float friction = frictionArray[pindex]; if (attr.IsInvalid()) - return; + continue; // Spring利用中は固定も通す - bool isSpring = tdata.IsSpring; if (attr.IsDontMove() && isSpring == false) - return; + continue; // 固定点の重量 float fixMass = isSpring ? 10.0f : 50.0f; // 重量 // BoneSpringでは固定点の重量加算を行わない - //float invMass = MathUtility.CalcInverseMass(friction, depth, attr.IsDontMove() && isSpring == false); float invMass = MathUtility.CalcInverseMass(friction, depth, attr.IsDontMove(), fixMass); - //float invMass = isSpring && attr.IsDontMove() ? 1.0f / 2.0f : MathUtility.CalcInverseMass(friction, depth, attr.IsDontMove()); // 基本剛性 - float stiffness = parameter.distanceConstraint.restorationStiffness.EvaluateCurveClamp01(depth); - //stiffness *= simulationPower; - //stiffness *= (simulationPower * simulationPower); + float stiffness = param.distanceConstraint.restorationStiffness.MC2EvaluateCurveClamp01(depth); stiffness *= simulationPower.y; - var pack = indexArray[c_start + l_index]; + //var pack = indexArray[c_start + k]; + var pack = indexArray[c_start + dataIndex]; DataUtility.Unpack12_20(pack, out int dcnt, out int dstart); if (dcnt > 0) { // 基準座標を切り替え float3 basePos = basePosArray[pindex]; - //float3 basicPos = stepBasicPositionBuffer[pindex]; float3 addPos = 0; int addCnt = 0; @@ -550,22 +475,18 @@ namespace MagicaCloth2 int tvindex = v_start + t_l_index; var t_nextPos = nextPosArray[tpindex]; float3 t_basePos = basePosArray[tpindex]; - //float3 t_basicPos = stepBasicPositionBuffer[tpindex]; float t_depth = depthArray[tvindex]; float t_friction = frictionArray[tpindex]; var t_attr = attributes[tvindex]; // 重量 // BoneSpringでは固定点の重量加算を行わない - //float t_invMass = MathUtility.CalcInverseMass(t_friction, t_depth, t_attr.IsDontMove() && isSpring == false); float t_invMass = MathUtility.CalcInverseMass(t_friction, t_depth, t_attr.IsDontMove(), fixMass); - //float t_invMass = isSpring && t_attr.IsDontMove() ? 1.0f / 2.0f : MathUtility.CalcInverseMass(t_friction, t_depth, t_attr.IsDontMove()); // 復元する長さ // !Distance制約は初期化時に保存した距離を見るようにしないと駄目 // フラグにより初期値かアニメーション後の姿勢かを切り替える float restLength = math.lerp(math.abs(restDist) * scl, math.distance(basePos, t_basePos), blendRatio); - //float restLength = math.distance(basicPos, t_basicPos); var v = t_nextPos - nextPos; @@ -595,7 +516,7 @@ namespace MagicaCloth2 nextPosArray[pindex] = nextPos; // 速度影響 - float attn = parameter.distanceConstraint.velocityAttenuation; + float attn = param.distanceConstraint.velocityAttenuation; velocityPosArray[pindex] = velocityPosArray[pindex] + addPos * attn; } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/DistanceConstraint.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/DistanceConstraint.cs.meta index 36511876..2fec340c 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/DistanceConstraint.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/DistanceConstraint.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/DistanceConstraint.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/InertiaConstraint.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/InertiaConstraint.cs index 066b91b1..02892b47 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/InertiaConstraint.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/InertiaConstraint.cs @@ -39,6 +39,28 @@ namespace MagicaCloth2 [System.Serializable] public class SerializeData : IDataValidate { + /// + /// Anchor that cancels inertia. + /// Anchor translation and rotation are excluded from simulation. + /// This is useful if your character rides a vehicle. + /// 慣性を打ち消すアンカー + /// アンカーの移動と回転はシミュレーションから除外されます + /// これはキャラクターが乗り物に乗る場合に便利です + /// [OK] Runtime changes. + /// [NG] Export/Import with Presets + /// + public Transform anchor; + + /// + /// Anchor Influence (0.0 ~ 1.0) + /// アンカーの影響(0.0 ~ 1.0) + /// [OK] Runtime changes. + /// [NG] Export/Import with Presets + /// + [Range(0.0f, 1.0f)] + public float anchorInertia; + + /// /// World Influence (0.0 ~ 1.0). /// ワールド移動影響(0.0 ~ 1.0) @@ -49,6 +71,15 @@ namespace MagicaCloth2 [Range(0.0f, 1.0f)] public float worldInertia; + /// + /// World Influence Smoothing (0.0 ~ 1.0). + /// ワールド移動影響平滑化(0.0 ~ 1.0) + /// [OK] Runtime changes. + /// [OK] Export/Import with Presets + /// + [Range(0.0f, 1.0f)] + public float movementInertiaSmoothing; + /// /// World movement speed limit (m/s). /// ワールド移動速度制限(m/s) @@ -144,7 +175,12 @@ namespace MagicaCloth2 public SerializeData() { + anchor = null; + anchorInertia = 0.0f; worldInertia = 1.0f; + //movementInertiaSmoothing = 0.65f; // ->0.0524 + //movementInertiaSmoothing = 0.5f; // ->0.13375 + movementInertiaSmoothing = 0.4f; movementSpeedLimit = new CheckSliderSerializeData(true, 5.0f); rotationSpeedLimit = new CheckSliderSerializeData(true, 720.0f); localInertia = 1.0f; @@ -162,7 +198,10 @@ namespace MagicaCloth2 { return new SerializeData() { + anchor = anchor, + anchorInertia = anchorInertia, worldInertia = worldInertia, + movementInertiaSmoothing = movementInertiaSmoothing, movementSpeedLimit = movementSpeedLimit.Clone(), rotationSpeedLimit = rotationSpeedLimit.Clone(), localInertia = localInertia, @@ -179,7 +218,9 @@ namespace MagicaCloth2 public void DataValidate() { + anchorInertia = Mathf.Clamp01(anchorInertia); worldInertia = Mathf.Clamp01(worldInertia); + movementInertiaSmoothing = Mathf.Clamp01(movementInertiaSmoothing); movementSpeedLimit.DataValidate(0.0f, Define.System.MaxMovementSpeedLimit); rotationSpeedLimit.DataValidate(0.0f, Define.System.MaxRotationSpeedLimit); localInertia = Mathf.Clamp01(localInertia); @@ -195,18 +236,30 @@ namespace MagicaCloth2 public struct InertiaConstraintParams { + /// + /// アンカー影響率(0.0 ~ 1.0) + /// + public float anchorInertia; + /// /// ワールド慣性影響(0.0 ~ 1.0) /// public float worldInertia; + /// + /// ワールド慣性スムージング率(0.0 ~ 1.0) + /// + public float movementInertiaSmoothing; + /// /// ワールド移動速度制限(m/s) + /// 無制限時は(-1) /// public float movementSpeedLimit; /// /// ワールド回転速度制限(deg/s) + /// 無制限時は(-1) /// public float rotationSpeedLimit; @@ -258,7 +311,9 @@ namespace MagicaCloth2 public void Convert(SerializeData sdata) { + anchorInertia = sdata.anchorInertia; worldInertia = sdata.worldInertia; + movementInertiaSmoothing = sdata.movementInertiaSmoothing; movementSpeedLimit = sdata.movementSpeedLimit.GetValue(-1); rotationSpeedLimit = sdata.rotationSpeedLimit.GetValue(-1); localInertia = sdata.localInertia; @@ -277,8 +332,26 @@ namespace MagicaCloth2 /// /// センタートランスフォームのデータ /// + [System.Serializable] public struct CenterData { + /// + /// 現在のアンカー姿勢 + /// + public float3 anchorPosition; + public quaternion anchorRotation; + + /// + /// 前フレームのアンカー姿勢 + /// + public float3 oldAnchorPosition; + public quaternion oldAnchorRotation; + + /// + /// アンカー空間でのコンポーネントのローカル座標 + /// + public float3 anchorComponentLocalPosition; + /// /// 参照すべきセンタートランスフォームインデックス /// 同期時は同期先チームのもにになる @@ -290,12 +363,14 @@ namespace MagicaCloth2 /// public float3 componentWorldPosition; public quaternion componentWorldRotation; + public float3 componentWorldScale; /// /// 前フレームのコンポーネント姿勢 /// public float3 oldComponentWorldPosition; public quaternion oldComponentWorldRotation; + public float3 oldComponentWorldScale; /// /// 現フレームのコンポーネント移動量 @@ -329,7 +404,7 @@ namespace MagicaCloth2 /// public float3 nowWorldPosition; public quaternion nowWorldRotation; - public float3 nowWorldScale; // ※現在未使用 + //public float3 nowWorldScale; // ※現在未使用 /// /// 前回ステップでの姿勢 @@ -395,10 +470,26 @@ namespace MagicaCloth2 /// public float3 initLocalGravityDirection; + /// + /// スムージングされた現在のワールド慣性速度ベクトル + /// + public float3 smoothingVelocity; // (m/s) + + /// + /// マイナススケールによる反転を打ち消すための変換マトリックス + /// センター空間 + /// + public float4x4 negativeScaleMatrix; + internal void Initialize() { + anchorRotation = quaternion.identity; + oldAnchorRotation = quaternion.identity; + componentWorldRotation = quaternion.identity; + componentWorldScale = 1; oldComponentWorldRotation = quaternion.identity; + oldComponentWorldScale = 1; frameComponentShiftRotation = quaternion.identity; frameWorldRotation = quaternion.identity; @@ -412,6 +503,7 @@ namespace MagicaCloth2 /// /// 制約データ /// + [System.Serializable] public class ConstraintData { public ResultCode result; @@ -450,7 +542,7 @@ namespace MagicaCloth2 /// 制約データの作成 /// /// - internal static ConstraintData CreateData(VirtualMesh proxyMesh, in ClothParameters parameters) + public static ConstraintData CreateData(VirtualMesh proxyMesh, in ClothParameters parameters) { var constraintData = new ConstraintData(); @@ -489,7 +581,7 @@ namespace MagicaCloth2 // 初期センター姿勢からローカル重力方向を算出する var rot = MathUtility.ToRotation(math.normalize(nor), math.normalize(tan)); var irot = math.inverse(rot); - localGravityDirection = math.mul(irot, parameters.gravityDirection); + localGravityDirection = math.mul(irot, parameters.worldGravityDirection); } constraintData.initLocalGravityDirection = localGravityDirection; @@ -519,12 +611,13 @@ namespace MagicaCloth2 // 初期化時のローカル重力方向 cdata.initLocalGravityDirection = cprocess.inertiaConstraintData.initLocalGravityDirection; + //Debug.Log($"[{cprocess.TeamId}] initLocalGravityDirection:{cdata.initLocalGravityDirection}"); // 固定点リスト var c = new DataChunk(); - if (cprocess.ProxyMesh.CenterFixedPointCount > 0) + if (cprocess.ProxyMeshContainer.shareVirtualMesh.CenterFixedPointCount > 0) { - c = fixedArray.AddRange(cprocess.ProxyMesh.centerFixedList); + c = fixedArray.AddRange(cprocess.ProxyMeshContainer.shareVirtualMesh.centerFixedList); } tdata.fixedDataChunk = c; } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/InertiaConstraint.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/InertiaConstraint.cs.meta index 65f1cffa..b014fcfb 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/InertiaConstraint.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/InertiaConstraint.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/InertiaConstraint.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/MotionConstraint.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/MotionConstraint.cs index 4df0e17d..d856e0d3 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/MotionConstraint.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/MotionConstraint.cs @@ -2,9 +2,7 @@ // Copyright (c) 2023 MagicaSoft. // https://magicasoft.jp using System; -using Unity.Burst; using Unity.Collections; -using Unity.Jobs; using Unity.Mathematics; using UnityEngine; @@ -134,97 +132,45 @@ namespace MagicaCloth2 } //========================================================================================= - /// - /// 制約の解決 - /// - /// - /// - unsafe internal JobHandle SolverConstraint(JobHandle jobHandle) - { - var tm = MagicaManager.Team; - var sm = MagicaManager.Simulation; - var vm = MagicaManager.VMesh; - - var job = new MotionConstraintJob() - { - stepParticleIndexArray = sm.processingStepMotionParticle.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - - attributes = vm.attributes.GetNativeArray(), - vertexDepths = vm.vertexDepths.GetNativeArray(), - - teamIdArray = sm.teamIdArray.GetNativeArray(), - basePosArray = sm.basePosArray.GetNativeArray(), - baseRotArray = sm.baseRotArray.GetNativeArray(), - nextPosArray = sm.nextPosArray.GetNativeArray(), - velocityPosArray = sm.velocityPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - collisionNormalArray = sm.collisionNormalArray.GetNativeArray(), - }; - jobHandle = job.Schedule(sm.processingStepMotionParticle.GetJobSchedulePtr(), 32, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct MotionConstraintJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray stepParticleIndexArray; - + // Solver + //========================================================================================= + internal static void SolverConstraint( + DataChunk chunk, // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - + ref TeamManager.TeamData tdata, + ref ClothParameters param, // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [Unity.Collections.ReadOnly] - public NativeArray vertexDepths; - + ref NativeArray attributes, + ref NativeArray vertexDepths, // particle - [Unity.Collections.ReadOnly] - public NativeArray teamIdArray; - [Unity.Collections.ReadOnly] - public NativeArray basePosArray; - [Unity.Collections.ReadOnly] - public NativeArray baseRotArray; - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - [NativeDisableParallelForRestriction] - public NativeArray velocityPosArray; - [NativeDisableParallelForRestriction] - public NativeArray frictionArray; - [NativeDisableParallelForRestriction] - public NativeArray collisionNormalArray; + ref NativeArray basePosArray, + ref NativeArray baseRotArray, + ref NativeArray nextPosArray, + ref NativeArray velocityPosArray, + ref NativeArray frictionArray, + ref NativeArray collisionNormalArray + ) + { + if (param.motionConstraint.useMaxDistance == false && param.motionConstraint.useBackstop == false) + return; + // stiffness + float stiffness = param.motionConstraint.stiffness; - public void Execute(int index) + float backstopRadius = param.motionConstraint.backstopRadius; + + // パーティクルごと + //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++) { - // pindexのチームは有効であることが保証されている - int pindex = stepParticleIndexArray[index]; - - int teamId = teamIdArray[pindex]; - var tdata = teamDataArray[teamId]; - var param = parameterArray[teamId]; - var motionParam = param.motionConstraint; - var normalAxis = param.normalAxis; - if (motionParam.useMaxDistance == false && motionParam.useBackstop == false) - return; - - int p_start = tdata.particleChunk.startIndex; - int l_index = pindex - p_start; - int v_start = tdata.proxyCommonChunk.startIndex; - int vindex = v_start + l_index; - // 移動パーティクルのみ var attr = attributes[vindex]; if (attr.IsMove() == false) - return; + continue; var nextPos = nextPosArray[pindex]; var basePos = basePosArray[pindex]; @@ -233,17 +179,13 @@ namespace MagicaCloth2 // !MaxDistanceとBackstop制約は常にアニメーション姿勢(basePose)から計算されるので注意! // !そのためAnimationBlendRatioは影響しない。 - // stiffness - float stiffness = motionParam.stiffness; - // 適用頂点属性チェック if (attr.IsMotion()) { var opos = nextPos; // パーティクル半径 - float radius = math.max(param.radiusCurveData.EvaluateCurve(depth), 0.0001f); // safe - //radius *= tdata.scaleRatio; + float radius = math.max(param.radiusCurveData.MC2EvaluateCurve(depth), 0.0001f); // safe // 摩擦影響距離 float cfr = radius * 1.0f; @@ -256,7 +198,7 @@ namespace MagicaCloth2 //========================================================= var baseRot = baseRotArray[pindex]; float3 dir = math.up(); - switch (normalAxis) + switch (param.normalAxis) { case ClothNormalAxis.Right: dir = math.right(); @@ -282,9 +224,9 @@ namespace MagicaCloth2 //========================================================= // Max Distance //========================================================= - if (motionParam.useMaxDistance) + if (param.motionConstraint.useMaxDistance) { - float maxDistance = motionParam.maxDistanceCurveData.EvaluateCurve(depth); + float maxDistance = param.motionConstraint.maxDistanceCurveData.MC2EvaluateCurve(depth); //var cen = basePos + dir * (motionParam.maxDistanceOffset * maxDistance); var cen = basePos; var v = MathUtility.ClampVector(nextPos - cen, maxDistance); @@ -294,10 +236,9 @@ namespace MagicaCloth2 //========================================================= // Backstop //========================================================= - if (motionParam.useBackstop) + if (param.motionConstraint.useBackstop) { - float backstopRadius = motionParam.backstopRadius; - float backstopDistance = motionParam.backstopDistanceCurveData.EvaluateCurve(depth); + float backstopDistance = param.motionConstraint.backstopDistanceCurveData.MC2EvaluateCurve(depth); if (backstopRadius > 0.0f) { // バックストップは法線逆方向 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/MotionConstraint.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/MotionConstraint.cs.meta index fa88e762..af72c547 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/MotionConstraint.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/MotionConstraint.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/MotionConstraint.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SelfCollisionConstraint.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SelfCollisionConstraint.cs index 84ffa613..8388a90e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SelfCollisionConstraint.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SelfCollisionConstraint.cs @@ -1,5 +1,5 @@ // Magica Cloth 2. -// Copyright (c) 2023 MagicaSoft. +// Copyright (c) 2025 MagicaSoft. // https://magicasoft.jp using System; using System.Runtime.CompilerServices; @@ -13,7 +13,7 @@ using UnityEngine; namespace MagicaCloth2 { - public class SelfCollisionConstraint : IDisposable + public partial class SelfCollisionConstraint : IDisposable { public enum SelfCollisionMode { @@ -116,6 +116,10 @@ namespace MagicaCloth2 } //========================================================================================= + /// + /// プリミティブ + /// Point/Edge/Triangleの管理 + /// public const uint KindPoint = 0; public const uint KindEdge = 1; public const uint KindTriangle = 2; @@ -127,31 +131,41 @@ namespace MagicaCloth2 public const uint Flag_AllFix = 0x20000000; public const uint Flag_Ignore = 0x40000000; // 無効もしくは無視頂点が含まれる public const uint Flag_Enable = 0x80000000; // 接触判定有効 + public const uint Flag_Intersect0 = 0x00000001; + public const uint Flag_Intersect1 = 0x00000002; + public const uint Flag_Intersect2 = 0x00000004; - struct Primitive + public const uint Flag_FixIntersect0 = (Flag_Fix0 | Flag_Intersect0); + public const uint Flag_FixIntersect1 = (Flag_Fix1 | Flag_Intersect1); + public const uint Flag_FixIntersect2 = (Flag_Fix2 | Flag_Intersect2); + + unsafe internal struct Primitive : IComparable { /// - /// フラグとチームID - /// 上位8bit = フラグ - /// 下位24bit = チームID + /// フラグ /// - public uint flagAndTeamId; + public uint flag; /// - /// ソートリストへのインデックス(グローバル) - /// - public int sortIndex; - - /// - /// プリミティグを構成するパーティクルインデックス + /// プリミティブを構成するパーティクルインデックス + /// 不要な軸は(-1)が設定されている /// public int3 particleIndices; - public float3x3 nextPos; - public float3x3 oldPos; - //public float3x3 basePos; public float3 invMass; + /// + /// プリミティブAABB + /// + public AABB aabb; + + /// + /// UniformGird座標 + /// + public int3 grid; + + public float depth; + /// /// 厚み /// @@ -160,36 +174,13 @@ namespace MagicaCloth2 [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsIgnore() { - return (flagAndTeamId & Flag_Ignore) != 0; + return (flag & Flag_Ignore) != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool HasParticle(int p) + public bool IsAllFix() { - return p >= 0 && math.all(particleIndices - p) == false; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public uint GetKind() - { - return (flagAndTeamId & Flag_KindMask) >> 24; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetTeamId() - { - return (int)(flagAndTeamId & 0xffffff); - } - - /// - /// 解決時のthicknessを計算する - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float GetSolveThickness(in Primitive pri) - { - return thickness + pri.thickness; + return (flag & Flag_AllFix) != 0; } /// @@ -198,53 +189,104 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyParticle(in Primitive pri) + public bool AnyParticle(ref Primitive pri) { - for (int i = 0; i < 3; i++) + uint kind = ((flag & Flag_KindMask) >> 24) + 1; + + for (int i = 0; i < kind; i++) { int p = particleIndices[i]; - if (p >= 0) - { - if (math.all(pri.particleIndices - p) == false) - return true; - } + + // 入力すべてが非0ならtrue + if (math.all(pri.particleIndices - p) == false) + return true; } + return false; } - } - ExNativeArray primitiveArray; - - struct SortData : IComparable - { - /// - /// フラグとチームID - /// 上位8bit = フラグ - /// 下位24bit = チームID - /// - public uint flagAndTeamId; /// - /// プリミティブインデックス(グローバル) + /// ソート用 + /// グリッドX->Y->Zの順でソート /// - public int primitiveIndex; - - public float2 firstMinMax; - public float2 secondMinMax; - public float2 thirdMinMax; - - public int CompareTo(SortData other) + /// + /// + public int CompareTo(Primitive other) { - return (int)math.sign(firstMinMax.x - other.firstMinMax.x); + if (grid.x != other.grid.x) + return grid.x - other.grid.x; + if (grid.y != other.grid.y) + return grid.y - other.grid.y; + return grid.z - other.grid.z; } + } + internal ExNativeArray primitiveArrayB; + + /// + /// グリッド + /// プリミティブ検出用のグリッド情報 + /// + internal struct GridInfo : IComparable + { + // このグリッドのハッシュ値 + public int hash; + + // このグリッドの開始プリミティブインデックス + public int start; + + // このグリッドに格納されているプリミティブ数 + public int count; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public uint GetKind() + public int CompareTo(GridInfo other) { - return (flagAndTeamId & Flag_KindMask) >> 24; + if (hash < other.hash) + return -1; + else if (hash > other.hash) + return 1; + else + return 0; } } - ExNativeArray sortAndSweepArray; + internal ExNativeArray uniformGridStartCountBuffer; + /// + /// コンタクト + /// 衝突プリミティブペアの管理 + /// + internal const byte ContactType_EdgeEdge = 0; + internal const byte ContactType_PointTriangle = 1; + internal const byte ContactType_TrianglePoint = 2; + + internal struct ContactInfo + { + public int primitiveIndex0; + public int primitiveIndex1; + public byte contactType; + public byte enable; + public half thickness; + public half s; + public half t; + public half3 n; + } + + internal NativeQueue contactQueue; + internal NativeList contactList; + + /// + /// インターセクト + /// 絡まり防止のEdgeTriangleペアの管理 + /// + internal struct IntersectInfo + { + public int2 edgeParticeIndices; + public int3 triangleParticleIndices; + } + + internal NativeQueue intersectQueue; + internal NativeList intersectList; + + //========================================================================================= /// /// ポイントプリミティブ総数 /// @@ -261,87 +303,49 @@ namespace MagicaCloth2 public int TrianglePrimitiveCount { get; private set; } = 0; //========================================================================================= - internal struct EdgeEdgeContact - { - public uint flagAndTeamId0; - public uint flagAndTeamId1; - public half thickness; - public half s; - public half t; - public half3 n; - public half2 edgeInvMass0; - public half2 edgeInvMass1; - public int2 edgeParticleIndex0; - public int2 edgeParticleIndex1; - - public override string ToString() - { - return $"EdgeEdge f0:{flagAndTeamId0:X}, f1:{flagAndTeamId1:X}, p0:{edgeParticleIndex0}, p1:{edgeParticleIndex1}, inv0:{edgeInvMass0}, inv1:{edgeInvMass1}"; - } - } - NativeQueue edgeEdgeContactQueue; - NativeList edgeEdgeContactList; - - internal struct PointTriangleContact - { - public uint flagAndTeamId0; // point - public uint flagAndTeamId1; // triangle - public half thickness; - public half sign; // 押出方向(-1/+1) - public int pointParticleIndex; - public int3 triangleParticleIndex; - public half pointInvMass; - public half3 triangleInvMass; - - public override string ToString() - { - return $"PointTriangle f0:{flagAndTeamId0:X}, f1:{flagAndTeamId1:X}, pp:{pointParticleIndex}, pt:{triangleParticleIndex}, pinv:{pointInvMass}, tinv:{triangleInvMass}"; - } - } - NativeQueue pointTriangleContactQueue; - NativeList pointTriangleContactList; - /// /// 交差解決フラグ(パーティクルと連動) /// - NativeArray intersectFlagArray; + internal NativeArray intersectFlagArray; - public int IntersectCount { get; private set; } = 0; + internal int IntersectCount { get; private set; } = 0; //========================================================================================= public SelfCollisionConstraint() { - primitiveArray = new ExNativeArray(0, true); - sortAndSweepArray = new ExNativeArray(0, true); - - edgeEdgeContactQueue = new NativeQueue(Allocator.Persistent); - pointTriangleContactQueue = new NativeQueue(Allocator.Persistent); - edgeEdgeContactList = new NativeList(Allocator.Persistent); - pointTriangleContactList = new NativeList(Allocator.Persistent); - intersectFlagArray = new NativeArray(0, Allocator.Persistent); + primitiveArrayB = new ExNativeArray(0, true); + uniformGridStartCountBuffer = new ExNativeArray(0, true); + contactQueue = new NativeQueue(Allocator.Persistent); + contactList = new NativeList(Allocator.Persistent); + intersectQueue = new NativeQueue(Allocator.Persistent); + intersectList = new NativeList(Allocator.Persistent); + //Develop.DebugLog($"UseQueueCount:{UseQueueCount}"); } public void Dispose() { - primitiveArray?.Dispose(); - primitiveArray = null; - - sortAndSweepArray?.Dispose(); - sortAndSweepArray = null; - PointPrimitiveCount = 0; EdgePrimitiveCount = 0; TrianglePrimitiveCount = 0; - edgeEdgeContactQueue.Dispose(); - pointTriangleContactQueue.Dispose(); - edgeEdgeContactList.Dispose(); - pointTriangleContactList.Dispose(); + intersectFlagArray.MC2DisposeSafe(); - intersectFlagArray.DisposeSafe(); + primitiveArrayB?.Dispose(); + primitiveArrayB = null; + uniformGridStartCountBuffer?.Dispose(); + uniformGridStartCountBuffer = null; + + if (contactQueue.IsCreated) + contactQueue.Dispose(); + if (contactList.IsCreated) + contactList.Dispose(); + if (intersectQueue.IsCreated) + intersectQueue.Dispose(); + if (intersectList.IsCreated) + intersectList.Dispose(); IntersectCount = 0; } @@ -359,70 +363,11 @@ namespace MagicaCloth2 { StringBuilder sb = new StringBuilder(); sb.AppendLine($"[SelfCollisionConstraint]"); - sb.AppendLine($" -primitiveArray:{primitiveArray.ToSummary()}"); - sb.AppendLine($" -sortAndSweepArray:{sortAndSweepArray.ToSummary()}"); - - sb.AppendLine($" -edgeEdgeContactQueue:{(edgeEdgeContactQueue.IsCreated ? edgeEdgeContactQueue.Count : 0)}"); - sb.AppendLine($" -edgeEdgeContactList:{(edgeEdgeContactList.IsCreated ? edgeEdgeContactList.Length : 0)}"); - sb.AppendLine($" -pointTriangleContactQueue:{(pointTriangleContactQueue.IsCreated ? pointTriangleContactQueue.Count : 0)}"); - sb.AppendLine($" -pointTriangleContactList:{(pointTriangleContactList.IsCreated ? pointTriangleContactList.Length : 0)}"); sb.AppendLine($" -intersectFlagArray:{(intersectFlagArray.IsCreated ? intersectFlagArray.Length : 0)}"); return sb.ToString(); } - //========================================================================================= -#if false - internal class ConstraintData : IValid - { - public ResultCode result; - - /// - /// 同期先proxyMeshのlocalPosを自proxyMesh空間に変換するマトリックス - /// - public float4x4 syncToSelfMatrix; - - public bool IsValid() - { - return math.any(syncToSelfMatrix.c0); - } - } - - internal static ConstraintData CreateData( - int teamId, TeamManager.TeamData teamData, VirtualMesh proxyMesh, in ClothParameters parameters, - int syncTeamId, TeamManager.TeamData syncTeamData, VirtualMesh syncProxyMesh) - { - var constraintData = new ConstraintData(); - - try - { - if (proxyMesh.VertexCount == 0) - return null; - - var self2Params = parameters.selfCollisionConstraint2; - - // 同期チームとのFullMesh判定が必要な場合は、同期ProxyMeshのローカル頂点を時チームの座標空間に変換しておく - //var syncMode = parameters.selfCollisionConstraint.syncMode; - //if (syncTeamId > 0 && syncProxyMesh != null) - //{ - // // 同期proxyMeshを自proxyMesh空間に変換するマトリックス - // var toM = syncProxyMesh.CenterTransformTo(proxyMesh); - // constraintData.syncToSelfMatrix = toM; - //} - } - catch (Exception exception) - { - Debug.LogException(exception); - constraintData.result.SetError(Define.Result.Constraint_CreateSelfCollisionException); - } - finally - { - } - - return constraintData; - } -#endif - //========================================================================================= /// /// 制約データを登録する @@ -464,6 +409,13 @@ namespace MagicaCloth2 // チームが消滅中かどうか bool exit = tdata.flag.IsSet(TeamManager.Flag_Exit); + // sync解除 + if (exit && tdata.syncTeamId != 0 && tm.ContainsTeamData(tdata.syncTeamId)) + { + ref var stdata = ref tm.GetTeamDataRef(tdata.syncTeamId); + tm.RemoveSyncParent(ref stdata, teamId); + } + // 自身の状況を判定する ref var parameter = ref tm.GetParametersRef(teamId); var selfMode = exit ? SelfCollisionMode.None : parameter.selfCollisionConstraint.selfMode; @@ -495,15 +447,15 @@ namespace MagicaCloth2 { if (tdata.EdgeCount > 0) { - selfEdgeEdge = true; useEdgePrimitive = true; + selfEdgeEdge = true; } if (tdata.TriangleCount > 0) { - selfPointTriangle = true; - selfTrianglePoint = true; usePointPrimitive = true; useTrianglePrimitive = true; + selfPointTriangle = true; + selfTrianglePoint = true; } if (tdata.EdgeCount > 0 && tdata.TriangleCount > 0) { @@ -520,18 +472,18 @@ namespace MagicaCloth2 { if (tdata.EdgeCount > 0 && stdata.EdgeCount > 0) { - syncEdgeEdge = true; useEdgePrimitive = true; + syncEdgeEdge = true; } if (tdata.TriangleCount > 0) { - syncTrianglePoint = true; useTrianglePrimitive = true; + syncTrianglePoint = true; } if (stdata.TriangleCount > 0) { - syncPointTriangle = true; usePointPrimitive = true; + syncPointTriangle = true; } if (tdata.EdgeCount > 0 && stdata.TriangleCount > 0) { @@ -559,18 +511,18 @@ namespace MagicaCloth2 { if (ptdata.EdgeCount > 0 && tdata.EdgeCount > 0) { - PsyncEdgeEdge = true; useEdgePrimitive = true; + PsyncEdgeEdge = true; } if (ptdata.TriangleCount > 0) { - PsyncPointTriangle = true; usePointPrimitive = true; + PsyncPointTriangle = true; } if (tdata.TriangleCount > 0) { - PsyncTrianglePoint = true; useTrianglePrimitive = true; + PsyncTrianglePoint = true; } if (tdata.EdgeCount > 0 && ptdata.TriangleCount > 0) { @@ -613,17 +565,17 @@ namespace MagicaCloth2 { // init int pointCount = tdata.ParticleCount; - tdata.selfPointChunk = primitiveArray.AddRange(pointCount); - sortAndSweepArray.AddRange(pointCount); + tdata.selfPointChunk = primitiveArrayB.AddRange(pointCount); + uniformGridStartCountBuffer.AddRange(pointCount); int start = tdata.selfPointChunk.startIndex; - InitPrimitive(teamId, tdata, KindPoint, start, start, pointCount); + InitPrimitive(teamId, tdata, KindPoint, start, pointCount); PointPrimitiveCount += pointCount; } else if (usePointPrimitive == false && tdata.selfPointChunk.IsValid) { // remove - primitiveArray.Remove(tdata.selfPointChunk); - sortAndSweepArray.Remove(tdata.selfPointChunk); + primitiveArrayB.Remove(tdata.selfPointChunk); + uniformGridStartCountBuffer.Remove(tdata.selfPointChunk); PointPrimitiveCount -= tdata.selfPointChunk.dataLength; tdata.selfPointChunk.Clear(); } @@ -633,17 +585,17 @@ namespace MagicaCloth2 { // init int edgeCount = tdata.EdgeCount; - tdata.selfEdgeChunk = primitiveArray.AddRange(edgeCount); - sortAndSweepArray.AddRange(edgeCount); + tdata.selfEdgeChunk = primitiveArrayB.AddRange(edgeCount); + uniformGridStartCountBuffer.AddRange(edgeCount); int start = tdata.selfEdgeChunk.startIndex; - InitPrimitive(teamId, tdata, KindEdge, start, start, edgeCount); + InitPrimitive(teamId, tdata, KindEdge, start, edgeCount); EdgePrimitiveCount += edgeCount; } else if (useEdgePrimitive == false && tdata.selfEdgeChunk.IsValid) { // remove - primitiveArray.Remove(tdata.selfEdgeChunk); - sortAndSweepArray.Remove(tdata.selfEdgeChunk); + primitiveArrayB.Remove(tdata.selfEdgeChunk); + uniformGridStartCountBuffer.Remove(tdata.selfEdgeChunk); EdgePrimitiveCount -= tdata.selfEdgeChunk.dataLength; tdata.selfEdgeChunk.Clear(); } @@ -653,17 +605,17 @@ namespace MagicaCloth2 { // init int triangleCount = tdata.TriangleCount; - tdata.selfTriangleChunk = primitiveArray.AddRange(triangleCount); - sortAndSweepArray.AddRange(triangleCount); + tdata.selfTriangleChunk = primitiveArrayB.AddRange(triangleCount); + uniformGridStartCountBuffer.AddRange(triangleCount); int start = tdata.selfTriangleChunk.startIndex; - InitPrimitive(teamId, tdata, KindTriangle, start, start, triangleCount); + InitPrimitive(teamId, tdata, KindTriangle, start, triangleCount); TrianglePrimitiveCount += triangleCount; } else if (useTrianglePrimitive == false && tdata.selfTriangleChunk.IsValid) { // remove - primitiveArray.Remove(tdata.selfTriangleChunk); - sortAndSweepArray.Remove(tdata.selfTriangleChunk); + primitiveArrayB.Remove(tdata.selfTriangleChunk); + uniformGridStartCountBuffer.Remove(tdata.selfTriangleChunk); TrianglePrimitiveCount -= tdata.selfTriangleChunk.dataLength; tdata.selfTriangleChunk.Clear(); } @@ -683,27 +635,38 @@ namespace MagicaCloth2 } // 同期対象に対して再帰する - if (syncMode != SelfCollisionMode.None && tm.ContainsTeamData(tdata.syncTeamId)) + if (tdata.syncTeamId != 0 && tm.ContainsTeamData(tdata.syncTeamId)) { UpdateTeam(tdata.syncTeamId); } } - void InitPrimitive(int teamId, TeamManager.TeamData tdata, uint kind, int startPrimitive, int startSort, int length) + /// + /// プリミティブ初期化 + /// + /// + /// + /// + /// + /// + void InitPrimitive(int teamId, TeamManager.TeamData tdata, uint kind, int startPrimitive, int length) { + var vm = MagicaManager.VMesh; + var job = new InitPrimitiveJob() { teamId = teamId, tdata = tdata, + kind = kind, startPrimitive = startPrimitive, - startSort = startSort, - edges = MagicaManager.VMesh.edges.GetNativeArray(), - triangles = MagicaManager.VMesh.triangles.GetNativeArray(), + edges = vm.edges.GetNativeArray(), + triangles = vm.triangles.GetNativeArray(), + attributes = vm.attributes.GetNativeArray(), + vertexDepths = vm.vertexDepths.GetNativeArray(), - primitiveArray = primitiveArray.GetNativeArray(), - sortArray = sortAndSweepArray.GetNativeArray(), + primitiveArrayB = primitiveArrayB.GetNativeArray(), }; job.Run(length); // ここではRun()で実行する } @@ -716,30 +679,29 @@ namespace MagicaCloth2 public uint kind; public int startPrimitive; - public int startSort; // vmesh [Unity.Collections.ReadOnly] public NativeArray edges; [Unity.Collections.ReadOnly] public NativeArray triangles; + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray vertexDepths; [NativeDisableParallelForRestriction] - public NativeArray primitiveArray; - [NativeDisableParallelForRestriction] - public NativeArray sortArray; + public NativeArray primitiveArrayB; public void Execute(int index) { int pri_index = startPrimitive + index; - int sort_index = startSort + index; - var p = primitiveArray[pri_index]; - var s = sortArray[sort_index]; + var p = primitiveArrayB[pri_index]; + int pstart = tdata.particleChunk.startIndex; // プリミティブを構成するパーティクルインデックス int3 particleIndices = -1; - int pstart = tdata.particleChunk.startIndex; if (kind == KindPoint) { particleIndices[0] = pstart + index; @@ -755,494 +717,16 @@ namespace MagicaCloth2 particleIndices.xyz = triangles[tstart + index] + pstart; } - p.flagAndTeamId = (uint)teamId | (kind << 24); - p.sortIndex = sort_index; - p.particleIndices = particleIndices; - - s.primitiveIndex = pri_index; - s.flagAndTeamId = (uint)teamId; - - primitiveArray[pri_index] = p; - sortArray[sort_index] = s; - } - } - - /// - /// 作業バッファ更新 - /// - internal void WorkBufferUpdate() - { - // 交差フラグバッファ - if (IntersectCount > 0) - { - int pcnt = MagicaManager.Simulation.ParticleCount; - intersectFlagArray.Resize(pcnt, options: NativeArrayOptions.ClearMemory); - } - -#if MC2_DEBUG && false - // debug - Develop.DebugLog($"PointPrimitive:{PointPrimitiveCount}, EdgePrimitive:{EdgePrimitiveCount}, TrianglePrimitive:{TrianglePrimitiveCount}, Intersect:{IntersectCount}"); - if (edgeEdgeContactQueue.Count > 0 || pointTriangleContactQueue.Count > 0) - Develop.DebugLog($"EdgeEdge Contact:{edgeEdgeContactQueue.Count}, PointTriangle Contact:{pointTriangleContactQueue.Count}"); - edgeEdgeContactQueue.Clear(); - pointTriangleContactQueue.Clear(); -#endif - - } - - /// - /// ソート&スイープ配列をデータsdで二分探索しその開始インデックスを返す - /// - /// - /// - /// - /// - static unsafe int BinarySearchSortAndlSweep(ref NativeArray sortAndSweepArray, in SortData sd, in DataChunk chunk) - { - SortData* pt = (SortData*)sortAndSweepArray.GetUnsafeReadOnlyPtr(); - pt += chunk.startIndex; - int sortIndex = NativeSortExtension.BinarySearch(pt, chunk.dataLength, sd); - if (sortIndex < 0) - { - // インデックスが正の場合は値が正確に発見されたのでそのインデックスが返る - // インデックスが負の場合は値が見つからずに最終的な探索インデックスが返る - // この場合はそのインデックスを正に戻しそこから-1した場所が値の次のインデックスとなっている - // 例:(-7) = 検索値はインデックス5と6の間 - sortIndex = math.max(-sortIndex - 1, 0); - } - sortIndex += chunk.startIndex; - - return sortIndex; - } - - //========================================================================================= - /// - /// 制約の解決 - /// - /// - /// - internal JobHandle SolverConstraint(int updateIndex, JobHandle jobHandle) - { - // 実行時セルフコリジョンの解決 - jobHandle = SolverRuntimeSelfCollision(updateIndex, jobHandle); - - // 絡まり解決 - jobHandle = SolveIntersect(jobHandle); - - return jobHandle; - } - - /// - /// 実行時セルフコリジョンの解決 - /// - /// - /// - unsafe JobHandle SolverRuntimeSelfCollision(int updateIndex, JobHandle jobHandle) - { - if (HasPrimitive() == false) - return jobHandle; - - // Broad phase ==================================================== - // コンタクトバッファ生成 - // !コンタクトバッファ生成は1フレームに1回しか実行しない - // !ステップ2回目以降は各パーティクルが線形に移動するだけでコンタクト生成結果にあまり変化が無いためスキップさせる - // !これは本来ならNGだがクオリティよりパフォーマンスを優先した実装となる - // !そもそも毎ステップ生成したとしてもMagicaClothは反復が少ないので絡まるときは絡まる。 - // !MagicaClothではその絡まりを最後のSolveIntersect()で解くことに重点を置く - if (updateIndex == 0) - { - // この生成が大変重い! - jobHandle = SolverBroadPhase(jobHandle); - } - else - { - // !ステップ2回目以降はコンタクトバッファの内容に対して再度ブロードフェーズのみを実行する - jobHandle = UpdateBroadPhase(jobHandle); - } - - // Solver phase ==================================================== - // 接触の解決 - // !直列1回と同程度の堅牢さは並列では反復3~4回ほど必要 - var sm = MagicaManager.Simulation; - for (int i = 0; i < Define.System.SelfCollisionSolverIteration; i++) - { - var solverEdgeEdgeJob = new SolverEdgeEdgeJob() - { - nextPosArray = sm.nextPosArray.GetNativeArray(), - edgeEdgeContactArray = edgeEdgeContactList.AsDeferredJobArray(), - countArray = sm.countArray, - sumArray = sm.sumArray, - }; - jobHandle = solverEdgeEdgeJob.Schedule(edgeEdgeContactList, 16, jobHandle); - - var solverPointTriangleJob = new SolverPointTriangleJob() - { - nextPosArray = sm.nextPosArray.GetNativeArray(), - pointTriangleContactArray = pointTriangleContactList.AsDeferredJobArray(), - countArray = sm.countArray, - sumArray = sm.sumArray, - }; - jobHandle = solverPointTriangleJob.Schedule(pointTriangleContactList, 16, jobHandle); - - // 集計 - const float attn = 0.0f; // 0.0f - jobHandle = InterlockUtility.SolveAggregateBufferAndClear(sm.processingSelfParticle, attn, jobHandle); - } - - return jobHandle; - } - - /// - /// コンタクトバッファ生成 - /// - /// - /// - unsafe JobHandle SolverBroadPhase(JobHandle jobHandle) - { - var tm = MagicaManager.Team; - var sm = MagicaManager.Simulation; - var vm = MagicaManager.VMesh; - - // バッファクリア - jobHandle = new ClearBufferJob() - { - edgeEdgeContactQueue = edgeEdgeContactQueue, - pointTriangleContactQueue = pointTriangleContactQueue, - }.Schedule(jobHandle); - - // プリミティブ更新 ======================================================= - if (PointPrimitiveCount > 0) - { - // PointTriangle - var job2 = new UpdatePrimitiveJob() - { - kind = KindPoint, - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - - attributes = vm.attributes.GetNativeArray(), - depthArray = vm.vertexDepths.GetNativeArray(), - - nextPosArray = sm.nextPosArray.GetNativeArray(), - oldPosArray = sm.oldPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - //stepBasicPositionBuffer = sm.stepBasicPositionBuffer, - - primitiveArray = primitiveArray.GetNativeArray(), - sortAndSweepArray = sortAndSweepArray.GetNativeArray(), - - processingArray = sm.processingSelfPointTriangle.Buffer, - }; - jobHandle = job2.Schedule(sm.processingSelfPointTriangle.GetJobSchedulePtr(), 16, jobHandle); - } - if (EdgePrimitiveCount > 0) - { - // EdgeEdge - var job = new UpdatePrimitiveJob() - { - kind = KindEdge, - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - - attributes = vm.attributes.GetNativeArray(), - depthArray = vm.vertexDepths.GetNativeArray(), - - nextPosArray = sm.nextPosArray.GetNativeArray(), - oldPosArray = sm.oldPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - //stepBasicPositionBuffer = sm.stepBasicPositionBuffer, - - primitiveArray = primitiveArray.GetNativeArray(), - sortAndSweepArray = sortAndSweepArray.GetNativeArray(), - - processingArray = sm.processingSelfEdgeEdge.Buffer, - }; - jobHandle = job.Schedule(sm.processingSelfEdgeEdge.GetJobSchedulePtr(), 16, jobHandle); - } - if (TrianglePrimitiveCount > 0) - { - // TrianglePoint - var job = new UpdatePrimitiveJob() - { - kind = KindTriangle, - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - - attributes = vm.attributes.GetNativeArray(), - depthArray = vm.vertexDepths.GetNativeArray(), - - nextPosArray = sm.nextPosArray.GetNativeArray(), - oldPosArray = sm.oldPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - //stepBasicPositionBuffer = sm.stepBasicPositionBuffer, - - primitiveArray = primitiveArray.GetNativeArray(), - sortAndSweepArray = sortAndSweepArray.GetNativeArray(), - - processingArray = sm.processingSelfTrianglePoint.Buffer, - }; - jobHandle = job.Schedule(sm.processingSelfTrianglePoint.GetJobSchedulePtr(), 16, jobHandle); - } - - // sort =========================================================== - // チームごと、およびpoint/edge/triangle別 - var sortJob = new SortJob() - { - teamDataArray = tm.teamDataArray.GetNativeArray(), - primitiveArray = primitiveArray.GetNativeArray(), - sortAndSweepArray = sortAndSweepArray.GetNativeArray(), - }; - jobHandle = sortJob.Schedule(tm.TeamCount * 3, 1, jobHandle); // 3 = (Point/Edge/Triangle) - - // Broad phase ==================================================== - // EdgeEdge - if (EdgePrimitiveCount > 0) - { - // Edge -> Edge - var broadEdgeEdgeJob = new EdgeEdgeBroadPhaseJob() - { - teamDataArray = tm.teamDataArray.GetNativeArray(), - - primitiveArray = primitiveArray.GetNativeArray(), - sortAndSweepArray = sortAndSweepArray.GetNativeArray(), - - processingEdgeEdgeArray = sm.processingSelfEdgeEdge.Buffer, - - edgeEdgeContactQueue = edgeEdgeContactQueue.AsParallelWriter(), - - intersectFlagArray = intersectFlagArray, - }; - jobHandle = broadEdgeEdgeJob.Schedule(sm.processingSelfEdgeEdge.GetJobSchedulePtr(), 16, jobHandle); - } - - // PointTriangle - if (PointPrimitiveCount > 0) - { - // Point -> Triangle - var broadPointTriangleJob = new PointTriangleBroadPhaseJob() - { - mainKind = KindPoint, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - - triangles = vm.triangles.GetNativeArray(), - attributes = vm.attributes.GetNativeArray(), - - nextPosArray = sm.nextPosArray.GetNativeArray(), - oldPosArray = sm.oldPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - - primitiveArray = primitiveArray.GetNativeArray(), - sortAndSweepArray = sortAndSweepArray.GetNativeArray(), - - processingPointTriangleArray = sm.processingSelfPointTriangle.Buffer, - - pointTriangleContactQueue = pointTriangleContactQueue.AsParallelWriter(), - - intersectFlagArray = intersectFlagArray, - }; - jobHandle = broadPointTriangleJob.Schedule(sm.processingSelfPointTriangle.GetJobSchedulePtr(), 16, jobHandle); - } - if (TrianglePrimitiveCount > 0) - { - // Triangle -> Point - var broadTrianglePointJob = new PointTriangleBroadPhaseJob() - { - mainKind = KindTriangle, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - - triangles = vm.triangles.GetNativeArray(), - attributes = vm.attributes.GetNativeArray(), - - nextPosArray = sm.nextPosArray.GetNativeArray(), - oldPosArray = sm.oldPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - - primitiveArray = primitiveArray.GetNativeArray(), - sortAndSweepArray = sortAndSweepArray.GetNativeArray(), - - processingPointTriangleArray = sm.processingSelfTrianglePoint.Buffer, - - pointTriangleContactQueue = pointTriangleContactQueue.AsParallelWriter(), - - intersectFlagArray = intersectFlagArray, - }; - jobHandle = broadTrianglePointJob.Schedule(sm.processingSelfTrianglePoint.GetJobSchedulePtr(), 16, jobHandle); - } - - // ToList - var toListJob1 = new EdgeEdgeToListJob() - { - edgeEdgeContactQueue = edgeEdgeContactQueue, - edgeEdgeContactList = edgeEdgeContactList, - }.Schedule(jobHandle); - var toListJob2 = new PointTriangleToListJob() - { - pointTriangleContactQueue = pointTriangleContactQueue, - pointTriangleContactList = pointTriangleContactList, - }.Schedule(jobHandle); - jobHandle = JobHandle.CombineDependencies(toListJob1, toListJob2); - - return jobHandle; - } - - [BurstCompile] - struct ClearBufferJob : IJob - { - [Unity.Collections.WriteOnly] - public NativeQueue edgeEdgeContactQueue; - - [Unity.Collections.WriteOnly] - public NativeQueue pointTriangleContactQueue; - - public void Execute() - { - edgeEdgeContactQueue.Clear(); - pointTriangleContactQueue.Clear(); - } - } - -#if false - [BurstCompile] - struct SetupContactGroupJob : IJob - { - public int teamCount; - public int useQueueCount; - - // team - public NativeArray teamDataArray; - - public void Execute() - { - // まずセルフコリジョンが有効で同期していないチームのグループインデックスを決定する - int groupIndex = 0; - var restTeam = new NativeList(teamCount, Allocator.Temp); - for (int i = 1; i < teamCount; i++) - { - var tdata = teamDataArray[i]; - if (tdata.IsValid == false || tdata.IsEnable == false || tdata.IsStepRunning == false) - continue; - if (tdata.flag.TestAny(TeamManager.Flag_Self_PointPrimitive, 3) == false) - continue; - - // このチームはセルフコリジョンを実行する - if (tdata.flag.IsSet(TeamManager.Flag_Synchronization)) - { - // 同期 - // 後で解決する - restTeam.Add(i); - } - else - { - // コンタクトグループを割り振る - tdata.selfQueueIndex = groupIndex % useQueueCount; - //Debug.Log($"tid:{i} Main selfQueueIndex:{tdata.selfQueueIndex}"); - teamDataArray[i] = tdata; - groupIndex++; - } - } - - // 同期チームは同期先のグループIDを指す - if (restTeam.Length > 0) - { - foreach (var teamId in restTeam) - { - var tdata = teamDataArray[teamId]; - var stdata = teamDataArray[tdata.syncTeamId]; - while (stdata.syncTeamId != 0) - { - stdata = teamDataArray[stdata.syncTeamId]; - } - tdata.selfQueueIndex = stdata.selfQueueIndex; - teamDataArray[teamId] = tdata; - //Debug.Log($"tid:{teamId} Sync selfQueueIndex:{tdata.selfQueueIndex}"); - } - } - } - } -#endif - - [BurstCompile] - struct UpdatePrimitiveJob : IJobParallelForDefer - { - // プリミティブ種類 - public uint kind; - - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - - // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [Unity.Collections.ReadOnly] - public NativeArray depthArray; - - // particle - [Unity.Collections.ReadOnly] - public NativeArray nextPosArray; - [Unity.Collections.ReadOnly] - public NativeArray oldPosArray; - [Unity.Collections.ReadOnly] - public NativeArray frictionArray; - //[Unity.Collections.ReadOnly] - //public NativeArray stepBasicPositionBuffer; - - // constraint - [NativeDisableParallelForRestriction] - public NativeArray primitiveArray; - [NativeDisableParallelForRestriction] - public NativeArray sortAndSweepArray; - - // processing - [Unity.Collections.ReadOnly] - public NativeArray processingArray; - - // プリミティブごと - public void Execute(int index) - { - uint pack = processingArray[index]; - int teamId = DataUtility.Unpack32Hi(pack); - int l_index = DataUtility.Unpack32Low(pack); - - // チームはこのステップで有効であることが保証されている - var tdata = teamDataArray[teamId]; - int pstart = tdata.particleChunk.startIndex; - - var param = parameterArray[teamId].selfCollisionConstraint; - - // primitive - int pri_index = 0; - switch (kind) - { - case KindPoint: - pri_index = tdata.selfPointChunk.startIndex + l_index; - break; - case KindEdge: - pri_index = tdata.selfEdgeChunk.startIndex + l_index; - break; - case KindTriangle: - pri_index = tdata.selfTriangleChunk.startIndex + l_index; - break; - } - var primitive = primitiveArray[pri_index]; - uint flag = primitive.flagAndTeamId; - - // プリミティブ更新 - int ac = (int)kind + 1; // 軸の数 + // フラグなど + uint flag = 0; uint fix_flag = Flag_Fix0; bool ignore = false; int fixcnt = 0; float depth = 0; + int ac = (int)kind + 1; // 軸の数 for (int i = 0; i < ac; i++) { - int pindex = primitive.particleIndices[i]; - primitive.nextPos[i] = nextPosArray[pindex]; - primitive.oldPos[i] = oldPosArray[pindex]; - //primitive.basePos[i] = stepBasicPositionBuffer[pindex]; + int pindex = particleIndices[i]; int vindex = tdata.proxyCommonChunk.startIndex + pindex - pstart; var attr = attributes[vindex]; if (attr.IsMove()) @@ -1255,8 +739,7 @@ namespace MagicaCloth2 fix_flag <<= 1; if (attr.IsInvalid()) ignore = true; - primitive.invMass[i] = MathUtility.CalcSelfCollisionInverseMass(frictionArray[pindex], attr.IsDontMove(), param.clothMass); - depth += depthArray[vindex]; + depth += vertexDepths[vindex]; } if (fixcnt == ac) flag |= Flag_AllFix; @@ -1264,110 +747,49 @@ namespace MagicaCloth2 flag &= ~Flag_AllFix; if (ignore) flag |= Flag_Ignore; - primitive.flagAndTeamId = flag; depth /= ac; - //float thickness = parameterArray[teamId].selfCollisionConstraint.surfaceThicknessCurveData.EvaluateCurve(depth); - float thickness = param.surfaceThicknessCurveData.EvaluateCurve(depth); - thickness *= tdata.scaleRatio; // team scale - primitive.thickness = thickness; - primitiveArray[pri_index] = primitive; - // AABB - var aabb = new AABB(math.min(primitive.nextPos[0], primitive.oldPos[0]), math.max(primitive.nextPos[0], primitive.oldPos[0])); - for (int i = 1; i < ac; i++) - { - aabb.Encapsulate(primitive.nextPos[i]); - aabb.Encapsulate(primitive.oldPos[i]); - } - aabb.Expand(thickness); // 厚み - //aabb.Expand(0.03f); // 厚み + p.flag = (kind << 24) | flag; + p.particleIndices = particleIndices; + p.depth = depth; + p.grid = Define.System.SelfCollisionIgnoreGrid; // 無効グリッド - // update sort - int sortIndex = primitive.sortIndex; - var sd = sortAndSweepArray[sortIndex]; - sd.flagAndTeamId = primitive.flagAndTeamId; - sd.firstMinMax = new float2(aabb.Min.y, aabb.Max.y); - sd.secondMinMax = new float2(aabb.Min.x, aabb.Max.x); - sd.thirdMinMax = new float2(aabb.Min.z, aabb.Max.z); - sortAndSweepArray[sortIndex] = sd; - //Debug.Log($"Update Primitive[{pri_index}] pindices:{primitive.particleIndices}, flag:0x{primitive.flagAndTeamId >> 24:X}"); + primitiveArrayB[pri_index] = p; + + //Debug.Log($"pri[{pri_index}] p:{p.particleIndices}, {p.GetKind()}"); } } - [BurstCompile] - unsafe struct SortJob : IJobParallelFor + /// + /// 作業バッファ更新 + /// + internal void WorkBufferUpdate() { - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - - // constraint - [NativeDisableParallelForRestriction] - public NativeArray primitiveArray; - [NativeDisableParallelForRestriction] - public NativeArray sortAndSweepArray; - - // チームごと(Point/Edge/Triangle) - public void Execute(int index) + // 交差フラグバッファ + if (IntersectCount > 0) { - int teamId = index / 3; - int type = index % 3; // 0=Point, 1=Edge, 2=Triangle - - if (teamId == 0) - return; - - var tdata = teamDataArray[teamId]; - if (tdata.IsProcess == false) - return; - - DataChunk sortChunk = default(DataChunk); - switch (type) - { - case 0: - sortChunk = tdata.selfPointChunk; - break; - case 1: - sortChunk = tdata.selfEdgeChunk; - break; - case 2: - sortChunk = tdata.selfTriangleChunk; - break; - } - if (sortChunk.IsValid == false) - return; - - // 書き込みポインタ - SortData* pt = (SortData*)sortAndSweepArray.GetUnsafePtr(); - pt += sortChunk.startIndex; - NativeSortExtension.Sort(pt, sortChunk.dataLength); - - // ソート後のインデックスをプリミティブに書き戻す - for (int i = 0; i < sortChunk.dataLength; i++) - { - int sortIndex = sortChunk.startIndex + i; - var sd = sortAndSweepArray[sortIndex]; - var primitive = primitiveArray[sd.primitiveIndex]; - primitive.sortIndex = sortIndex; - primitiveArray[sd.primitiveIndex] = primitive; - //Debug.Log($"sort[{i}] primitive:{sd.primitiveIndex}, prisortidx:{primitive.sortIndex}, first:{sd.firstMinMax}, second:{sd.secondMinMax}, third:{sd.thirdMinMax}"); - } + int pcnt = MagicaManager.Simulation.ParticleCount; + intersectFlagArray.MC2Resize(pcnt, options: NativeArrayOptions.ClearMemory); } } + //========================================================================================= + // Primitive + //========================================================================================= [BurstCompile] - struct PointTriangleBroadPhaseJob : IJobParallelForDefer + unsafe internal struct SelfStep_UpdatePrimitiveJob : IJobParallelFor { - public uint mainKind; + public int workerCount; + public int updateIndex; + public float4 simulationPower; // team [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] public NativeArray teamDataArray; - - // vmesh [Unity.Collections.ReadOnly] - public NativeArray triangles; - [Unity.Collections.ReadOnly] - public NativeArray attributes; + public NativeArray parameterArray; // particle [Unity.Collections.ReadOnly] @@ -1377,536 +799,755 @@ namespace MagicaCloth2 [Unity.Collections.ReadOnly] public NativeArray frictionArray; - // constraint - [Unity.Collections.ReadOnly] - public NativeArray primitiveArray; - [Unity.Collections.ReadOnly] - public NativeArray sortAndSweepArray; - - // processing - [Unity.Collections.ReadOnly] - public NativeArray processingPointTriangleArray; - - // contact buffer - [Unity.Collections.WriteOnly] - public NativeQueue.ParallelWriter pointTriangleContactQueue; - + // self collision + public bool useIntersect; + [NativeDisableParallelForRestriction] + public NativeArray primitiveArrayB; [Unity.Collections.ReadOnly] public NativeArray intersectFlagArray; - // 解決PointTriangleごと + // バッチ内のローカルチームインデックスごと + // ワーカー分割(3固定) public void Execute(int index) { - uint pack = processingPointTriangleArray[index]; - int teamId = DataUtility.Unpack32Hi(pack); - int l_index = DataUtility.Unpack32Low(pack); + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; - // チームはこのステップで有効であることが保証されている - var tdata = teamDataArray[teamId]; + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); - // メインとサブのチャンク - bool isPoint = mainKind == KindPoint; - var mainChunk = isPoint ? tdata.selfPointChunk : tdata.selfTriangleChunk; - var subChunk = isPoint ? tdata.selfTriangleChunk : tdata.selfPointChunk; + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); - // Main Primitive - int pri_index = mainChunk.startIndex + l_index; - var primitive0 = primitiveArray[pri_index]; - var sd0 = sortAndSweepArray[primitive0.sortIndex]; - - // 無効判定 - if (primitive0.IsIgnore()) + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) return; - // 交差中ならば無効 - if (tdata.flag.TestAny(TeamManager.Flag_Self_EdgeTriangleIntersect, 6)) + // セルフコリジョン + // ■プリミティブとグリッドの更新 + // 範囲 + //var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + //if (chunk.IsValid) { - int ac = isPoint ? 1 : 3; - for (int i = 0; i < ac; i++) - { - if (intersectFlagArray[primitive0.particleIndices[i]] > 0) - return; - } - } - - //============================================================= - // Self - //============================================================= - if (tdata.flag.IsSet(isPoint ? TeamManager.Flag_Self_PointTriangle : TeamManager.Flag_Self_TrianglePoint)) - { - SweepTest(-1, ref primitive0, sd0, subChunk, true); - } - - //============================================================= - // Sync - //============================================================= - if (tdata.flag.IsSet(isPoint ? TeamManager.Flag_Sync_PointTriangle : TeamManager.Flag_Sync_TrianglePoint) && tdata.syncTeamId > 0) - { - var stdata = teamDataArray[tdata.syncTeamId]; - SweepTest(-1, ref primitive0, sd0, isPoint ? stdata.selfTriangleChunk : stdata.selfPointChunk, false); - } - - //============================================================= - // Parent Sync - //============================================================= - if (tdata.flag.IsSet(isPoint ? TeamManager.Flag_PSync_PointTriangle : TeamManager.Flag_PSync_TrianglePoint)) - { - int cnt = tdata.syncParentTeamId.Length; - for (int j = 0; j < cnt; j++) - { - int parentTeamId = tdata.syncParentTeamId[j]; - var stdata = teamDataArray[parentTeamId]; - if (stdata.flag.IsSet(isPoint ? TeamManager.Flag_Sync_TrianglePoint : TeamManager.Flag_Sync_PointTriangle)) - { - SweepTest(-1, ref primitive0, sd0, isPoint ? stdata.selfTriangleChunk : stdata.selfPointChunk, false); - } - } - } - } - - void SweepTest(int sortIndex, ref Primitive primitive0, in SortData sd0, in DataChunk subChunk, bool connectionCheck) - { - Debug.Assert(subChunk.IsValid); - - // スイープ - if (sortIndex < 0) - sortIndex = BinarySearchSortAndlSweep(ref sortAndSweepArray, sd0, subChunk); - - float end = sd0.firstMinMax.y; - int endIndex = subChunk.startIndex + subChunk.dataLength; - while (sortIndex < endIndex) - { - var sd1 = sortAndSweepArray[sortIndex]; - sortIndex++; - - // first - if (sd1.firstMinMax.x <= end) - { - // second - if (sd1.secondMinMax.y < sd0.secondMinMax.x || sd1.secondMinMax.x > sd0.secondMinMax.y) - continue; - - // third - if (sd1.thirdMinMax.y < sd0.thirdMinMax.x || sd1.thirdMinMax.x > sd0.thirdMinMax.y) - continue; - - // この時点で両方のAABBは衝突している - var primitive1 = primitiveArray[sd1.primitiveIndex]; - - // 無効判定 - if (primitive1.IsIgnore()) - continue; - - // プリミティブ同士が接続している場合は無効 - if (connectionCheck && primitive0.AnyParticle(primitive1)) - continue; - - // 両方のプリミティブが完全固定ならば無効 - if ((primitive0.flagAndTeamId & Flag_AllFix) != 0 && (primitive1.flagAndTeamId & Flag_AllFix) != 0) - continue; - - // 交差判定 - // 厚みとSCR - float solveThickness = primitive0.GetSolveThickness(primitive1); - float scr = solveThickness * Define.System.SelfCollisionSCR; - if (solveThickness < 0.0001f) - continue; - - // 接触予測判定 - if (mainKind == KindPoint) - BroadPointTriangle(ref primitive0, ref primitive1, solveThickness, scr, Define.System.SelfCollisionPointTriangleAngleCos); - else - BroadPointTriangle(ref primitive1, ref primitive0, solveThickness, scr, Define.System.SelfCollisionPointTriangleAngleCos); - } - else - break; - } - } - - void BroadPointTriangle(ref Primitive p_pri, ref Primitive t_pri, float thickness, float scr, float ang) - { - // 変位 - var dA = p_pri.nextPos.c0 - p_pri.oldPos.c0; - var dB0 = t_pri.nextPos.c0 - t_pri.oldPos.c0; - var dB1 = t_pri.nextPos.c1 - t_pri.oldPos.c1; - var dB2 = t_pri.nextPos.c2 - t_pri.oldPos.c2; - - //========================================================= - // 衝突予測と格納 - //========================================================= - float3 uvw, cp; - // 移動前ポイントと移動前トライアングルへの最近接点 - cp = MathUtility.ClosestPtPointTriangle(p_pri.oldPos.c0, t_pri.oldPos.c0, t_pri.oldPos.c1, t_pri.oldPos.c2, out uvw); - - // 最近接点座標の変位を求める - float3 dt = dB0 * uvw.x + dB1 * uvw.y + dB2 * uvw.z; - - // 最近接点ベクトル - float3 cv = cp - p_pri.oldPos.c0; - float cvlen = math.length(cv); - if (cvlen > Define.System.Epsilon) - { - var n = cv / cvlen; - - // 変位dp,dtをnに投影して距離チェック - float l0 = math.dot(n, dA); - float l1 = math.dot(n, dt); - float l = cvlen - l0 + l1; - - // ダイナミックThicknessテスト -#if false - if (p_pri.GetTeamId() == t_pri.GetTeamId()) - { - var bcp = MathUtility.ClosestPtPointTriangle(p_pri.basePos.c0, t_pri.basePos.c0, t_pri.basePos.c1, t_pri.basePos.c2, out _); - float blen = math.distance(p_pri.basePos.c0, bcp); - //blen *= 0.7f; - if (blen < 0.005f) - return; - //if (thickness > blen) - // Debug.Log($"PT thickness:{thickness}, blen:{blen}"); - thickness = math.min(thickness, blen); - scr = thickness * Define.System.SelfCollisionSCR; - } -#endif - - // 接続判定 - if (l < (thickness + scr)) - { - //========================================================= - // 方向性判定 - //========================================================= - float sign = 0; - // 移動前トライアングル法線 - float3 otn = MathUtility.TriangleNormal(t_pri.oldPos.c0, t_pri.oldPos.c1, t_pri.oldPos.c2); - - // 移動前のパーティクル方向性 - n = math.normalize(p_pri.oldPos.c0 - cp); - float dot = math.dot(otn, n); - - // 移動前にトライアングル面に対してほぼ水平ならば無視する - if (math.abs(dot) >= ang) - sign = math.sign(dot); - else - return; - - //========================================================= - // 接触情報作成 - //========================================================= - var contact = new PointTriangleContact(); - contact.flagAndTeamId0 = p_pri.flagAndTeamId | Flag_Enable; - contact.flagAndTeamId1 = t_pri.flagAndTeamId; - contact.thickness = (half)thickness; - contact.sign = (half)sign; - contact.pointParticleIndex = p_pri.particleIndices.x; - contact.triangleParticleIndex = t_pri.particleIndices; - contact.pointInvMass = (half)p_pri.invMass.x; - contact.triangleInvMass = (half3)t_pri.invMass; - //Debug.Log(contact.ToString()); - - pointTriangleContactQueue.Enqueue(contact); - } + UpdatePrimitive( + workerIndex, + // team + teamId, + ref tdata, + ref param, + // particle + ref nextPosArray, + ref oldPosArray, + ref frictionArray, + // self collisiotn + useIntersect, + ref primitiveArrayB, + ref intersectFlagArray + ); } } } - [BurstCompile] - struct EdgeEdgeBroadPhaseJob : IJobParallelForDefer - { + /// + /// ブロードフェーズ + /// プリミティブ更新 + /// + unsafe static void UpdatePrimitive( + int k, // team + int teamId, + ref TeamManager.TeamData tdata, + ref ClothParameters param, + // particle + ref NativeArray nextPosArray, + ref NativeArray oldPosArray, + ref NativeArray frictionArray, + // self collision + bool useIntersect, + ref NativeArray primitiveArrayB, + ref NativeArray intersectFlagArray + ) + { + // チームの種類ごと(0:Point,1:Edge,2:Triangle) + + // ■プリミティブ更新 =================================================================== + Primitive* pt = (Primitive*)primitiveArrayB.GetUnsafePtr(); + + int pstart = tdata.particleChunk.startIndex; + + // (0)Point/(1)Edge/(2)Triangle + float maxPrimitiveSize = 0; + //for (int k = 0; k < 3; k++) + { + DataChunk pc = k == KindPoint ? tdata.selfPointChunk : (k == KindEdge ? tdata.selfEdgeChunk : tdata.selfTriangleChunk); + //Debug.Log($"[{teamId}] kind:{k} pc:{pc.ToString()}"); + + if (pc.IsValid) + { + uint kind = (uint)k; + + float3x3 nextPos = 0; + float3x3 oldPos = 0; + + int priIndex = pc.startIndex; + for (int j = 0; j < pc.dataLength; j++, priIndex++) + { + ref var p = ref *(pt + priIndex); + + if (p.IsIgnore()) + continue; + + // プリミティブ更新 + int ac = k + 1; // 軸の数 + uint fix_flag = Flag_Fix0; + uint intersect_flag = 0; + for (int i = 0; i < ac; i++) + { + int pindex = p.particleIndices[i]; + nextPos[i] = nextPosArray[pindex]; + oldPos[i] = oldPosArray[pindex]; + bool fix = (p.flag & fix_flag) != 0; + p.invMass[i] = MathUtility.CalcSelfCollisionInverseMass(frictionArray[pindex], fix, param.selfCollisionConstraint.clothMass); + fix_flag <<= 1; + + if (useIntersect && intersectFlagArray[pindex] != 0) + intersect_flag |= (Flag_Intersect0 << i); + } + float thickness = param.selfCollisionConstraint.surfaceThicknessCurveData.MC2EvaluateCurve(p.depth); + thickness *= tdata.scaleRatio; // team scale + p.thickness = thickness; + + // プリミティブAABB + var aabb = new AABB(math.min(nextPos[0], oldPos[0]), math.max(nextPos[0], oldPos[0])); + for (int i = 1; i < ac; i++) + { + aabb.Encapsulate(nextPos[i]); + aabb.Encapsulate(oldPos[i]); + } + float aabbSize = aabb.MaxSideLength; + maxPrimitiveSize = math.max(maxPrimitiveSize, aabbSize); + aabb.Expand(thickness); // 厚み + p.aabb = aabb; + + // インターセクトフラグ更新 + p.flag = (p.flag & 0xfffffff8) | intersect_flag; + } + } + } + + // ■UniformGridサイズ決定 ============================================================== + // 種類がEdgeの場合のみ設定 + if (k == KindEdge) + { + const float uniformGridScale = 3.0f; // 一旦これで 3.0? + float gridSize = maxPrimitiveSize * uniformGridScale; + tdata.selfGridSize = gridSize; + tdata.selfMaxPrimitiveSize = maxPrimitiveSize; // 最大プリミティブサイズ + //Debug.Log($"[{teamId}] maxPrimitiveSize:{maxPrimitiveSize} gridSize:{gridSize}"); + } + //Debug.Log($"[{teamId}] kind:{k}, maxPrimitiveSize:{maxPrimitiveSize}"); + } + + [BurstCompile] + unsafe internal struct SelfStep_UpdateGridJob : IJobParallelFor + { + public int kindCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; [Unity.Collections.ReadOnly] public NativeArray teamDataArray; - // constraint + // self collision [Unity.Collections.ReadOnly] - public NativeArray primitiveArray; - [Unity.Collections.ReadOnly] - public NativeArray sortAndSweepArray; + public NativeArray primitiveArrayB; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray uniformGridStartCountBuffer; - // processing - [Unity.Collections.ReadOnly] - public NativeArray processingEdgeEdgeArray; - - // contact buffer - [Unity.Collections.WriteOnly] - public NativeQueue.ParallelWriter edgeEdgeContactQueue; - - [Unity.Collections.ReadOnly] - public NativeArray intersectFlagArray; - - // 解決エッジごと + // バッチ内のローカルチームインデックスごと + // ワーカー分割(3固定) public void Execute(int index) { - uint pack = processingEdgeEdgeArray[index]; - int teamId = DataUtility.Unpack32Hi(pack); - int l_index = DataUtility.Unpack32Low(pack); + // チームIDとワーカーID + int localIndex = index / kindCount; + int kindIndex = index % kindCount; - // チームはこのステップで有効であることが保証されている - var tdata = teamDataArray[teamId]; + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); - int pri_index = tdata.selfEdgeChunk.startIndex + l_index; - var primitive0 = primitiveArray[pri_index]; + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); - // 無効 - if (primitive0.IsIgnore()) + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) return; - // 交差中ならば無効 - if (tdata.flag.TestAny(TeamManager.Flag_Self_EdgeTriangleIntersect, 6)) + // セルフコリジョン + // ■プリミティブとグリッドの更新(初回ステップのみ) + if (updateIndex == 0) { - if (intersectFlagArray[primitive0.particleIndices.x] > 0) - return; - if (intersectFlagArray[primitive0.particleIndices.y] > 0) - return; + UpdateGrid( + kindIndex, + // team + teamId, + ref tdata, + // self collisiotn + ref primitiveArrayB, + ref uniformGridStartCountBuffer + ); } + } + } - // sort - var sd0 = sortAndSweepArray[primitive0.sortIndex]; + unsafe static void UpdateGrid( + int k, + // team + int teamId, + ref TeamManager.TeamData tdata, + // self collision + ref NativeArray primitiveArrayB, + ref NativeArray uniformGridStartCountBuffer + ) + { + // チームの種類ごと(0:Point,1:Edge,2:Triangle) - //============================================================= - // Self - //============================================================= - if (tdata.flag.IsSet(TeamManager.Flag_Self_EdgeEdge)) + // ■プリミティブ更新 =================================================================== + Primitive* pt = (Primitive*)primitiveArrayB.GetUnsafeReadOnlyPtr(); + GridInfo* gt = (GridInfo*)uniformGridStartCountBuffer.GetUnsafePtr(); + + //int pstart = tdata.particleChunk.startIndex; + + // ■ここからは自身のグリッドが参照される場合のみで良い + // つまり自身のセルフコリジョンか親からの相互コリジョン + if (tdata.flag.IsSet(TeamManager.Flag_Self_EdgeEdge) + || tdata.flag.IsSet(TeamManager.Flag_Self_PointTriangle) + || tdata.flag.IsSet(TeamManager.Flag_Self_TrianglePoint) + || tdata.flag.IsSet(TeamManager.Flag_PSync_EdgeEdge) + || tdata.flag.IsSet(TeamManager.Flag_PSync_PointTriangle) + || tdata.flag.IsSet(TeamManager.Flag_PSync_TrianglePoint) + ) + { { - SweepTest(primitive0.sortIndex + 1, ref primitive0, sd0, tdata.selfEdgeChunk, true); - } - - //============================================================= - // Sync - //============================================================= - if (tdata.flag.IsSet(TeamManager.Flag_Sync_EdgeEdge) && tdata.syncTeamId > 0) - { - var stdata = teamDataArray[tdata.syncTeamId]; - SweepTest(-1, ref primitive0, sd0, stdata.selfEdgeChunk, false); - } - - //============================================================= - // Parent Sync - //============================================================= - if (tdata.flag.IsSet(TeamManager.Flag_PSync_EdgeEdge)) - { - int cnt = tdata.syncParentTeamId.Length; - for (int j = 0; j < cnt; j++) + DataChunk pc = k == KindPoint ? tdata.selfPointChunk : (k == KindEdge ? tdata.selfEdgeChunk : tdata.selfTriangleChunk); + //Debug.Log($"[{teamId}] calc grid. kind:{k} pstart:{pc.startIndex}, pcount:{pc.dataLength}"); + if (pc.IsValid) { - int parentTeamId = tdata.syncParentTeamId[j]; - var stdata = teamDataArray[parentTeamId]; - if (stdata.flag.IsSet(TeamManager.Flag_Sync_EdgeEdge)) + // ■プリミティブのグリッド座標算出 ======================================================= + int priIndex = pc.startIndex; + for (int j = 0; j < pc.dataLength; j++, priIndex++) { - SweepTest(-1, ref primitive0, sd0, stdata.selfEdgeChunk, false); + ref var p = ref *(pt + priIndex); + if (p.IsIgnore()) + p.grid = Define.System.SelfCollisionIgnoreGrid; // 無効グリッド + else + p.grid = GetGrid(p.aabb.Center, tdata.selfGridSize); } + + // ■プリミティブをグリッド順にソートする ================================================= + NativeSortExtension.Sort(pt + pc.startIndex, pc.dataLength); + + // ■グリッドの開始位置と数を摘出する ===================================================== + int3 nowGrid = 0; + int nowGridStart = 0; + int nowGridCount = 0; + int gridBufferStart = pc.startIndex; + int gridBufferIndex = gridBufferStart; + int gridBufferCount = 0; + priIndex = pc.startIndex; + for (int i = 0; i < pc.dataLength; i++, priIndex++) + { + ref var p = ref *(pt + priIndex); + + if (i == 0) + { + // 初回グリッド + nowGrid = p.grid; + nowGridStart = priIndex; + nowGridCount = 0; + } + else if (p.grid.Equals(nowGrid.xyz) == false) + { + // 現在のグリッドを保存 + uniformGridStartCountBuffer[gridBufferIndex] = new GridInfo() { hash = nowGrid.GetHashCode(), start = nowGridStart, count = nowGridCount }; + gridBufferIndex++; + gridBufferCount++; + //Debug.Log(nowGrid.GetHashCode()); + + // 次のグリッドの開始 + nowGrid = p.grid; + nowGridStart = priIndex; + nowGridCount = 0; + } + nowGridCount++; + } + // 最後のグリッドを記録 + if (nowGridCount > 0) + { + uniformGridStartCountBuffer[gridBufferIndex] = new GridInfo() { hash = nowGrid.GetHashCode(), start = nowGridStart, count = nowGridCount }; + gridBufferIndex++; + gridBufferCount++; + //Debug.Log(nowGrid.GetHashCode()); + } + + // グリッド数を記録 + switch (k) + { + case 0: + tdata.selfPointGridCount = gridBufferCount; + break; + case 1: + tdata.selfEdgeGridCount = gridBufferCount; + break; + case 2: + tdata.selfTriangleGridCount = gridBufferCount; + break; + } + + // グリッド情報をハッシュでソート + // 2分探索のため + NativeSortExtension.Sort(gt + gridBufferStart, gridBufferCount); + + //Debug.Log($"[{teamId}] calc grid. kind:{k} pstart:{pc.startIndex}, pcount:{pc.dataLength}, grid count:{gridBufferCount}"); } } } - - void SweepTest(int sortIndex, ref Primitive primitive0, in SortData sd0, in DataChunk subChunk, bool connectionCheck) - { - // スイープ - if (sortIndex < 0) - sortIndex = BinarySearchSortAndlSweep(ref sortAndSweepArray, sd0, subChunk); - float end = sd0.firstMinMax.y; - int endIndex = subChunk.startIndex + subChunk.dataLength; - while (sortIndex < endIndex) - { - var sd1 = sortAndSweepArray[sortIndex]; - sortIndex++; - - // first - if (sd1.firstMinMax.x <= end) - { - // second - if (sd1.secondMinMax.y < sd0.secondMinMax.x || sd1.secondMinMax.x > sd0.secondMinMax.y) - continue; - - // third - if (sd1.thirdMinMax.y < sd0.thirdMinMax.x || sd1.thirdMinMax.x > sd0.thirdMinMax.y) - continue; - - // この時点で両方のAABBは衝突している - var primitive1 = primitiveArray[sd1.primitiveIndex]; - - // 無効判定 - if (primitive1.IsIgnore()) - continue; - - // プリミティブ同士が接続している場合は無効 - if (connectionCheck && primitive0.AnyParticle(primitive1)) - continue; - - // 両方のプリミティブが完全固定ならば無効 - if ((primitive0.flagAndTeamId & Flag_AllFix) != 0 && (primitive1.flagAndTeamId & Flag_AllFix) != 0) - continue; - - // 交差判定 - // 厚みとSCR - float solveThickness = primitive0.GetSolveThickness(primitive1); - float scr = solveThickness * Define.System.SelfCollisionSCR; - if (solveThickness < 0.0001f) - continue; - - // 接触予測判定 - BroadEdgeEdge(ref primitive0, ref primitive1, solveThickness, scr); - } - else - break; - } - } - - void BroadEdgeEdge(ref Primitive pri0, ref Primitive pri1, float thickness, float scr) - { - // 移動前の2つの線分の最近接点 - float s, t; - float3 cA, cB; - float csqlen = MathUtility.ClosestPtSegmentSegment(pri0.oldPos[0], pri0.oldPos[1], pri1.oldPos[0], pri1.oldPos[1], out s, out t, out cA, out cB); - float clen = math.sqrt(csqlen); // 最近接点の距離 - if (clen < 1e-09f) - return; - - // 押出法線 - float3 n = (cA - cB) / clen; - - // 最近接点での変位 - var dA0 = pri0.nextPos[0] - pri0.oldPos[0]; - var dA1 = pri0.nextPos[1] - pri0.oldPos[1]; - var dB0 = pri1.nextPos[0] - pri1.oldPos[0]; - var dB1 = pri1.nextPos[1] - pri1.oldPos[1]; - float3 da = math.lerp(dA0, dA1, s); - float3 db = math.lerp(dB0, dB1, t); - - // 変位da,dbをnに投影して距離チェック - float l0 = math.dot(n, da); - float l1 = math.dot(n, db); - float l = clen + l0 - l1; - - // ダイナミックThicknessテスト -#if false - if (pri0.GetTeamId() == pri1.GetTeamId()) - { - float bsqlen = MathUtility.ClosestPtSegmentSegment(pri0.basePos[0], pri0.basePos[1], pri1.basePos[0], pri1.basePos[1], out _, out _, out _, out _); - float blen = math.sqrt(bsqlen); - //blen *= 0.7f; - if (blen < 0.005f) - return; - //if (thickness > blen) - // Debug.Log($"EE thickness:{thickness}, blen:{blen}"); - thickness = math.min(thickness, blen); - scr = thickness * Define.System.SelfCollisionSCR; - } -#endif - - // 接触判定 - if (l > (thickness + scr)) - return; - - //========================================================= - // 接触情報作成 - //========================================================= - var contact = new EdgeEdgeContact(); - contact.flagAndTeamId0 = pri0.flagAndTeamId | Flag_Enable; - contact.flagAndTeamId1 = pri1.flagAndTeamId; - contact.thickness = (half)thickness; - contact.s = (half)s; - contact.t = (half)t; - contact.n = (half3)n; - contact.edgeInvMass0 = (half2)pri0.invMass.xy; - contact.edgeInvMass1 = (half2)pri1.invMass.xy; - contact.edgeParticleIndex0 = pri0.particleIndices.xy; - contact.edgeParticleIndex1 = pri1.particleIndices.xy; - //Debug.Log(contact.ToString()); - - // キューへの振り分け - edgeEdgeContactQueue.Enqueue(contact); - } } - [BurstCompile] - struct EdgeEdgeToListJob : IJob + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static int3 GetGrid(float3 pos, float gridSize) { + //Debug.Assert(gridSize > 0.0f); + return new int3(math.floor(pos / gridSize)); + } + + //========================================================================================= + // Contact + //========================================================================================= + [BurstCompile] + unsafe internal struct SelfStep_DetectionContactJob : IJobParallelFor + { + public int updateIndex; + public int workerCount; + public int teamCount; + + // team [Unity.Collections.ReadOnly] - public NativeQueue edgeEdgeContactQueue; - - [NativeDisableParallelForRestriction] - public NativeList edgeEdgeContactList; - - public void Execute() - { - edgeEdgeContactList.Clear(); - if (edgeEdgeContactQueue.Count > 0) - edgeEdgeContactList.AddRange(edgeEdgeContactQueue.ToArray(Allocator.Temp)); - } - } - - [BurstCompile] - struct PointTriangleToListJob : IJob - { + public NativeList batchSelfTeamList; [Unity.Collections.ReadOnly] - public NativeQueue pointTriangleContactQueue; + public NativeArray teamDataArray; - [NativeDisableParallelForRestriction] - public NativeList pointTriangleContactList; - - public void Execute() - { - pointTriangleContactList.Clear(); - if (pointTriangleContactQueue.Count > 0) - pointTriangleContactList.AddRange(pointTriangleContactQueue.ToArray(Allocator.Temp)); - } - } - - JobHandle UpdateBroadPhase(JobHandle jobHandle) - { - var sm = MagicaManager.Simulation; - - // EdgeEdge - var updateJob1 = new UpdateEdgeEdgeBroadPhaseJob() - { - nextPosArray = sm.nextPosArray.GetNativeArray(), - oldPosArray = sm.oldPosArray.GetNativeArray(), - edgeEdgeContactList = edgeEdgeContactList, - }; - jobHandle = updateJob1.Schedule(edgeEdgeContactList, 16, jobHandle); - - // PointTriangle - var updateJob2 = new UpdatePointTriangleBroadPhaseJob() - { - nextPosArray = sm.nextPosArray.GetNativeArray(), - oldPosArray = sm.oldPosArray.GetNativeArray(), - pointTriangleContactList = pointTriangleContactList, - }; - jobHandle = updateJob2.Schedule(pointTriangleContactList, 16, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct UpdateEdgeEdgeBroadPhaseJob : IJobParallelForDefer - { // particle [Unity.Collections.ReadOnly] public NativeArray nextPosArray; [Unity.Collections.ReadOnly] public NativeArray oldPosArray; + // self collision + [Unity.Collections.ReadOnly] + public NativeArray primitiveArrayB; + [Unity.Collections.ReadOnly] + public NativeArray uniformGridStartCountBuffer; + + // buffer [NativeDisableParallelForRestriction] - public NativeList edgeEdgeContactList; + public NativeQueue.ParallelWriter contactQueue; + + // 1チーム6インデックス分割 x ワーカー数 + public void Execute(int index) + { + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + // チームインデックス + int teamIndex = index / (6 * workerCount); + index = index % (6 * workerCount); + int teamId = batchSelfTeamList[teamIndex]; + ref var tdata = ref *(teamPt + teamId); + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // ワーカー番号 + int workerIndex = index / 6; + index = index % 6; + + // セルフコリジョン or 相互コリジョン + int collisionMode = index / 3; + index = index % 3; + + // コリジョン種類 + int contactKind = index; + + uint myKind = 0, tarKind = 0; + switch (contactKind) + { + case ContactType_EdgeEdge: + myKind = KindEdge; + tarKind = KindEdge; + break; + case ContactType_PointTriangle: + myKind = KindPoint; + tarKind = KindTriangle; + break; + case ContactType_TrianglePoint: + myKind = KindTriangle; + tarKind = KindPoint; + break; + } + + // ■コンタクトバッファ作成(ステップ初回のみ) + + if (collisionMode == 0) + { + // セルフコリジョン + // セルフコリジョンではTrianglePointは不要 + if (contactKind == ContactType_TrianglePoint) + return; + + int selfFlag = TeamManager.Flag_Self_EdgeEdge + (contactKind * 3); + if (tdata.flag.IsSet(selfFlag)) + { + //Debug.Log($"Self detection contact. myTeam:{teamId}, myKind:{myKind}, tarTeam:{teamId}, tarKind:{tarKind}"); + + DetectionContacts( + workerCount, + workerIndex, + teamId, + ref tdata, + myKind, + teamId, + ref tdata, + tarKind, + ref nextPosArray, + ref oldPosArray, + ref primitiveArrayB, + ref uniformGridStartCountBuffer, + ref contactQueue + ); + } + } + else if (collisionMode == 1 && tdata.syncTeamId > 0) + { + // 相互コリジョン + ref var stdata = ref *(teamPt + tdata.syncTeamId); + int syncFlag = TeamManager.Flag_Sync_EdgeEdge + (contactKind * 3); + if (tdata.flag.IsSet(syncFlag)) + { + //Debug.Log($"Sync detection contact. myTeam:{teamId}, myKind:{myKind}, tarTeam:{teamId}, tarKind:{tarKind}"); + + DetectionContacts( + workerCount, + workerIndex, + teamId, + ref tdata, + myKind, + tdata.syncTeamId, + ref stdata, + tarKind, + ref nextPosArray, + ref oldPosArray, + ref primitiveArrayB, + ref uniformGridStartCountBuffer, + ref contactQueue + ); + } + } + + //Debug.Log($"Detection contact. team:{teamId}, collisionMode:{collisionMode}, contactKind:{contactKind}, writeCount:{writeCount}"); + } + } + + unsafe static void DetectionContacts( + int workerCount, + int workerIndex, + // my + int myTeamId, + ref TeamManager.TeamData myTeam, + uint myKind, + // target + int targetTeamId, + ref TeamManager.TeamData targetTeam, + uint targetKind, + // particle + ref NativeArray nextPosArray, + ref NativeArray oldPosArray, + // self collision + ref NativeArray primitiveArrayB, + ref NativeArray uniformGridStartCountBuffer, + // contact buffer + ref NativeQueue.ParallelWriter contactQueue + ) + { + Primitive* pt = (Primitive*)primitiveArrayB.GetUnsafeReadOnlyPtr(); + GridInfo* gt = (GridInfo*)uniformGridStartCountBuffer.GetUnsafeReadOnlyPtr(); + + // 参照元 + DataChunk myPriChunk = myKind == KindPoint ? myTeam.selfPointChunk : (myKind == KindEdge ? myTeam.selfEdgeChunk : myTeam.selfTriangleChunk); + if (myPriChunk.IsValid == false) + return; + + // ワーカー分散による範囲 + int2 range = MathUtility.CalcSplitRange(myPriChunk.dataLength, workerCount, workerIndex); + myPriChunk.startIndex += range.x; + myPriChunk.dataLength = range.y - range.x; + + // 対象 + DataChunk tarPriChunk = targetKind == KindPoint ? targetTeam.selfPointChunk : (targetKind == KindEdge ? targetTeam.selfEdgeChunk : targetTeam.selfTriangleChunk); + if (tarPriChunk.IsValid == false) + return; + int gridBufferStart = tarPriChunk.startIndex; + int gridBufferIndex = gridBufferStart; + int gridBufferCount = 0; + switch (targetKind) + { + case KindPoint: + gridBufferCount = targetTeam.selfPointGridCount; + break; + case KindEdge: + gridBufferCount = targetTeam.selfEdgeGridCount; + break; + case KindTriangle: + gridBufferCount = targetTeam.selfTriangleGridCount; + break; + } + float maxPrimitiveSize = targetTeam.selfMaxPrimitiveSize; + float gridSize = targetTeam.selfGridSize; + + // 重複判定の有無 + bool duplicateDetection = (myTeamId == targetTeamId && myKind == targetKind); + + // プリミティブの接続判定 + bool connectionCheck = myTeamId == targetTeamId; + + // 接触タイプ + bool primitiveFlip = false; + byte contactType = ContactType_EdgeEdge; + if (myKind == KindPoint && targetKind == KindTriangle) + contactType = ContactType_PointTriangle; + else if (myKind == KindTriangle && targetKind == KindPoint) + { + contactType = ContactType_PointTriangle; + primitiveFlip = true; + } + + // プリミティブごと + GridInfo searchGridInfo = new GridInfo(); + int priIndex = myPriChunk.startIndex; + for (int i = 0; i < myPriChunk.dataLength; i++, priIndex++) + { + ref var p = ref *(pt + priIndex); + + // 無効判定 + if (p.IsIgnore()) + continue; + + bool pFix = (p.flag & Flag_AllFix) != 0; + + // このプリミティブの検索範囲 + float3 areaMin = p.aabb.Min - maxPrimitiveSize * 0.5f; + float3 areaMax = p.aabb.Max + maxPrimitiveSize * 0.5f; + + // グリッド範囲に変換する + int3 startGrid = GetGrid(areaMin, gridSize); + int3 endGrid = GetGrid(areaMax, gridSize); + + // グリッド範囲を調べる + int3 currentGrid = startGrid; + bool finish = false; + while (finish == false) + { + // グリッド情報検索(ハッシュ値による2分探索) + int currentHash = currentGrid.GetHashCode(); + searchGridInfo.hash = currentHash; + int infoIndex = NativeSortExtension.BinarySearch(gt + gridBufferStart, gridBufferCount, searchGridInfo); + if (infoIndex >= 0) + { + // このグリッドにはプリミティブが存在する + ref var gridInfo = ref *(gt + gridBufferStart + infoIndex); + int startPriIndex2 = gridInfo.start; + int endPriIndex2 = startPriIndex2 + gridInfo.count; + + // 重複判定:グリッド全体が現在のpriIndexより下ならば検索不要 + if (duplicateDetection == false || endPriIndex2 >= priIndex) + { + // 重複判定:現在のpindexより上のものだけを調べる + int priIndex2 = duplicateDetection ? math.max(startPriIndex2, priIndex) : startPriIndex2; + for (; priIndex2 < endPriIndex2; priIndex2++) + { + if (duplicateDetection && priIndex == priIndex2) + continue; + + ref var p2 = ref *(pt + priIndex2); + + // AABB判定 + if (p.aabb.Overlaps(p2.aabb) == false) + continue; + + // 無効判定 + if (p2.IsIgnore()) + continue; + + // 両方のプリミティブが完全固定ならば無効 + if (pFix && ((p2.flag & Flag_AllFix) != 0)) + continue; + + // プリミティブ同士が接続している場合は無効 + if (connectionCheck && p.AnyParticle(ref p2)) + continue; + + // !衝突検出! + // コンタクトバッファ生成 + var contact = new ContactInfo() + { + primitiveIndex0 = primitiveFlip == false ? priIndex : priIndex2, + primitiveIndex1 = primitiveFlip == false ? priIndex2 : priIndex, + contactType = contactType, + thickness = (half)(p.thickness + p2.thickness), + }; + + // コンタクト変位判定 + UpdateContactInfo( + ref contact, + pt, + ref nextPosArray, + ref oldPosArray, + Define.System.SelfCollisionSCR, + true + ); + if (contact.enable == 0) + continue; + + contactQueue.Enqueue(contact); + //Debug.Log($"Contact! myTeamId:{myTeamId}, myKind:{myKind}, targetTeamId:{targetTeamId}, targetKind:{targetKind}, ({priIndex}->{priIndex2})"); + } + } + } + + // next + currentGrid.x++; + if (currentGrid.x > endGrid.x) + { + currentGrid.x = startGrid.x; + currentGrid.y++; + if (currentGrid.y > endGrid.y) + { + currentGrid.y = startGrid.y; + currentGrid.z++; + if (currentGrid.z > endGrid.z) + { + finish = true; + } + } + } + } + } + } + + [BurstCompile] + unsafe internal struct SelfStep_ConvertContactListJob : IJob + { + [Unity.Collections.ReadOnly] + public NativeQueue contactQueue; + + [NativeDisableParallelForRestriction] + public NativeList contactList; + + public void Execute() + { + contactList.Clear(); + if (contactQueue.Count > 0) + contactList.AddRange(contactQueue.ToArray(Allocator.Temp)); + + //Debug.Log($"contact count:{contactList.Length}"); + } + } + + [BurstCompile] + unsafe internal struct SelfStep_UpdateContactJob : IJobParallelForDefer + { + public bool first; + [NativeDisableParallelForRestriction] + public NativeList contactList; + + // particle + [Unity.Collections.ReadOnly] + public NativeArray nextPosArray; + [Unity.Collections.ReadOnly] + public NativeArray oldPosArray; + // self collision + [Unity.Collections.ReadOnly] + public NativeArray primitiveArrayB; // コンタクトごと public void Execute(int index) { - var contact = edgeEdgeContactList[index]; + Primitive* pt = (Primitive*)primitiveArrayB.GetUnsafeReadOnlyPtr(); + ContactInfo* ct = (ContactInfo*)contactList.GetUnsafePtr(); - var oldPosA0 = oldPosArray[contact.edgeParticleIndex0.x]; - var oldPosA1 = oldPosArray[contact.edgeParticleIndex0.y]; - var oldPosB0 = oldPosArray[contact.edgeParticleIndex1.x]; - var oldPosB1 = oldPosArray[contact.edgeParticleIndex1.y]; + ref ContactInfo contact = ref *(ct + index); - var nextPosA0 = nextPosArray[contact.edgeParticleIndex0.x]; - var nextPosA1 = nextPosArray[contact.edgeParticleIndex0.y]; - var nextPosB0 = nextPosArray[contact.edgeParticleIndex1.x]; - var nextPosB1 = nextPosArray[contact.edgeParticleIndex1.y]; + // 反復計算用にコンタクト情報を更新する + UpdateContactInfo( + ref contact, + pt, + ref nextPosArray, + ref oldPosArray, + Define.System.SelfCollisionSCR, + first + ); + } + } + + unsafe static void UpdateContactInfo( + ref ContactInfo contact, + Primitive* pt, + ref NativeArray nextPosArray, + ref NativeArray oldPosArray, + float scrScale, + bool first + ) + { + ref var p0 = ref *(pt + contact.primitiveIndex0); + ref var p1 = ref *(pt + contact.primitiveIndex1); + + float thickness = contact.thickness; + float scr = thickness * scrScale; + + contact.enable = 0; + + // AABB + + + // コンタクト解決 + if (contact.contactType == ContactType_EdgeEdge) + { + var nextPosA0 = nextPosArray[p0.particleIndices.x]; + var nextPosA1 = nextPosArray[p0.particleIndices.y]; + var nextPosB0 = nextPosArray[p1.particleIndices.x]; + var nextPosB1 = nextPosArray[p1.particleIndices.y]; + var oldPosA0 = oldPosArray[p0.particleIndices.x]; + var oldPosA1 = oldPosArray[p0.particleIndices.y]; + var oldPosB0 = oldPosArray[p1.particleIndices.x]; + var oldPosB1 = oldPosArray[p1.particleIndices.y]; // 移動前の2つの線分の最近接点 - float s, t; - float3 cA, cB; - float csqlen = MathUtility.ClosestPtSegmentSegment(oldPosA0, oldPosA1, oldPosB0, oldPosB1, out s, out t, out cA, out cB); + float csqlen = MathUtility.ClosestPtSegmentSegment(oldPosA0, oldPosA1, oldPosB0, oldPosB1, out var s, out var t, out var cA, out var cB); float clen = math.sqrt(csqlen); // 最近接点の距離 if (clen < 1e-09f) return; @@ -1926,596 +1567,708 @@ namespace MagicaCloth2 float l0 = math.dot(n, da); float l1 = math.dot(n, db); float l = clen + l0 - l1; + if (l > (thickness + scr)) + return; - // 接触判定 - float scr = contact.thickness; - if (l > (contact.thickness + scr)) - { - contact.flagAndTeamId0 &= ~Flag_Enable; - } - else - { - contact.flagAndTeamId0 |= Flag_Enable; - contact.s = (half)s; - contact.t = (half)t; - contact.n = (half3)n; - } - - edgeEdgeContactList[index] = contact; + // 有効 + contact.enable = 1; + contact.s = (half)s; + contact.t = (half)t; + contact.n = (half3)n; } - } - - [BurstCompile] - struct UpdatePointTriangleBroadPhaseJob : IJobParallelForDefer - { - // particle - [Unity.Collections.ReadOnly] - public NativeArray nextPosArray; - [Unity.Collections.ReadOnly] - public NativeArray oldPosArray; - - [NativeDisableParallelForRestriction] - public NativeList pointTriangleContactList; - - // コンタクトごと - public void Execute(int index) + else if (contact.contactType == ContactType_PointTriangle) { - var contact = pointTriangleContactList[index]; + var nextPosA0 = nextPosArray[p0.particleIndices.x]; + var oldPosA0 = oldPosArray[p0.particleIndices.x]; - bool enable = false; - - var oldPosA = oldPosArray[contact.pointParticleIndex]; - var oldPosB0 = oldPosArray[contact.triangleParticleIndex.x]; - var oldPosB1 = oldPosArray[contact.triangleParticleIndex.y]; - var oldPosB2 = oldPosArray[contact.triangleParticleIndex.z]; - - var nextPosA = nextPosArray[contact.pointParticleIndex]; - var nextPosB0 = nextPosArray[contact.triangleParticleIndex.x]; - var nextPosB1 = nextPosArray[contact.triangleParticleIndex.y]; - var nextPosB2 = nextPosArray[contact.triangleParticleIndex.z]; + var nextPosB0 = nextPosArray[p1.particleIndices.x]; + var nextPosB1 = nextPosArray[p1.particleIndices.y]; + var nextPosB2 = nextPosArray[p1.particleIndices.z]; + var oldPosB0 = oldPosArray[p1.particleIndices.x]; + var oldPosB1 = oldPosArray[p1.particleIndices.y]; + var oldPosB2 = oldPosArray[p1.particleIndices.z]; // 変位 - var dA = nextPosA - oldPosA; + var dA = nextPosA0 - oldPosA0; var dB0 = nextPosB0 - oldPosB0; var dB1 = nextPosB1 - oldPosB1; var dB2 = nextPosB2 - oldPosB2; - //========================================================= // 衝突予測と格納 - //========================================================= - float3 uvw, cp; + float3 cp; // 移動前ポイントと移動前トライアングルへの最近接点 - cp = MathUtility.ClosestPtPointTriangle(oldPosA, oldPosB0, oldPosB1, oldPosB2, out uvw); + cp = MathUtility.ClosestPtPointTriangle(oldPosA0, oldPosB0, oldPosB1, oldPosB2, out var uvw); // 最近接点座標の変位を求める float3 dt = dB0 * uvw.x + dB1 * uvw.y + dB2 * uvw.z; // 最近接点ベクトル - float3 cv = cp - oldPosA; + float3 cv = cp - oldPosA0; float cvlen = math.length(cv); - if (cvlen > Define.System.Epsilon) + if (cvlen <= Define.System.Epsilon) + return; + + var n = cv / cvlen; + + // 変位dp,dtをnに投影して距離チェック + float l0 = math.dot(n, dA); + float l1 = math.dot(n, dt); + float l = cvlen - l0 + l1; + + // 接続判定 + if (l >= (thickness + scr)) + return; + + // 方向性判定 + // !signの算出はオリジナルでは登録時に1回しか行っていない。 + float sign = contact.s; + if (first) { - var n = cv / cvlen; + // 移動前トライアングル法線 + float3 otn = MathUtility.TriangleNormal(oldPosB0, oldPosB1, oldPosB2); - // 変位dp,dtをnに投影して距離チェック - float l0 = math.dot(n, dA); - float l1 = math.dot(n, dt); - float l = cvlen - l0 + l1; + // 移動前のパーティクル方向性 + n = math.normalize(oldPosA0 - cp); + float dot = math.dot(otn, n); + // 移動前にトライアングル面に対してほぼ水平ならば無視する + if (math.abs(dot) >= Define.System.SelfCollisionPointTriangleAngleCos) + sign = math.sign(dot); + else + return; + } + contact.s = (half)sign; - // 接続判定 - float scr = contact.thickness; - if (l < (contact.thickness + scr)) + // 有効 + contact.enable = 1; + } + } + + [BurstCompile] + unsafe internal struct SelfStep_SolverContactJob : IJobParallelForDefer + { + // particle + [Unity.Collections.ReadOnly] + public NativeArray nextPosArray; + + // self collision + [Unity.Collections.ReadOnly] + public NativeArray primitiveArrayB; + [Unity.Collections.ReadOnly] + public NativeList contactList; + + // buffer2 + [NativeDisableParallelForRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + public NativeArray tempCountBuffer; + + // コンタクトごと + public void Execute(int index) + { + ContactInfo* ct = (ContactInfo*)contactList.GetUnsafeReadOnlyPtr(); + Primitive* pt = (Primitive*)primitiveArrayB.GetUnsafeReadOnlyPtr(); + int* cntPt = (int*)tempCountBuffer.GetUnsafePtr(); + int* sumPt = (int*)tempVectorBufferA.GetUnsafePtr(); + + ref var contact = ref *(ct + index); + + // 解決 + if (contact.enable == 0) + return; + + ref var p0 = ref *(pt + contact.primitiveIndex0); + ref var p1 = ref *(pt + contact.primitiveIndex1); + + float thickness = contact.thickness; + float scr = thickness * Define.System.SelfCollisionSCR; + + // コンタクト解決 + if (contact.contactType == ContactType_EdgeEdge) + { + var nextPosA0 = nextPosArray[p0.particleIndices.x]; + var nextPosA1 = nextPosArray[p0.particleIndices.y]; + var nextPosB0 = nextPosArray[p1.particleIndices.x]; + var nextPosB1 = nextPosArray[p1.particleIndices.y]; + + float s = contact.s; + float t = contact.t; + float3 n = contact.n; + + // 移動前に接触判定を行った位置の移動後の位置a/bと方向ベクトル + float3 a = math.lerp(nextPosA0, nextPosA1, s); + float3 b = math.lerp(nextPosB0, nextPosB1, t); + float3 v = a - b; + + // 接触法線に現在の距離を投影させる + float l = math.dot(n, v); + //Debug.Log($"A({pA0}-{pA1}), B({pB0}-{pB1}) s:{s}, t:{t} l:{l}"); + if (l > thickness) + return; + + float invMassA0 = p0.invMass.x; + float invMassA1 = p0.invMass.y; + float invMassB0 = p1.invMass.x; + float invMassB1 = p1.invMass.y; + + // 離す距離 + float C = thickness - l; + + // お互いを離す + float b0 = 1.0f - s; + float b1 = s; + float b2 = 1.0f - t; + float b3 = t; + float3 grad0 = n * b0; + float3 grad1 = n * b1; + float3 grad2 = -n * b2; + float3 grad3 = -n * b3; + + float S = invMassA0 * b0 * b0 + invMassA1 * b1 * b1 + invMassB0 * b2 * b2 + invMassB1 * b3 * b3; + if (S == 0.0f) + return; + + S = C / S; + + float3 _A0 = S * invMassA0 * grad0; + float3 _A1 = S * invMassA1 * grad1; + float3 _B0 = S * invMassB0 * grad2; + float3 _B1 = S * invMassB1 * grad3; + +#if true + // 書き込み + if ((p0.flag & Flag_FixIntersect0) == 0) { - enable = true; + InterlockUtility.AddFloat3(p0.particleIndices.x, _A0, cntPt, sumPt); + } + if ((p0.flag & Flag_FixIntersect1) == 0) + { + InterlockUtility.AddFloat3(p0.particleIndices.y, _A1, cntPt, sumPt); + } + if ((p1.flag & Flag_FixIntersect0) == 0) + { + InterlockUtility.AddFloat3(p1.particleIndices.x, _B0, cntPt, sumPt); + } + if ((p1.flag & Flag_FixIntersect1) == 0) + { + InterlockUtility.AddFloat3(p1.particleIndices.y, _B1, cntPt, sumPt); + } +#endif + } + else if (contact.contactType == ContactType_PointTriangle) + { + // トライアングル情報 + float3 nextPos0 = nextPosArray[p1.particleIndices.x]; + float3 nextPos1 = nextPosArray[p1.particleIndices.y]; + float3 nextPos2 = nextPosArray[p1.particleIndices.z]; + float invMass0 = p1.invMass.x; + float invMass1 = p1.invMass.y; + float invMass2 = p1.invMass.z; + + // 移動後トライアングル法線 + float3 tn = MathUtility.TriangleNormal(nextPos0, nextPos1, nextPos2); + + // 対象パーティクル情報 + float3 nextPos = nextPosArray[p0.particleIndices.x]; + float invMass = p0.invMass.x; + + // 衝突の解決 + // 移動後ポイントと移動後トライアングルへの最近接点 + float3 uvw; + MathUtility.ClosestPtPointTriangle(nextPos, nextPos0, nextPos1, nextPos2, out uvw); + + // 押し出し方向(移動後のトライアングル法線) + // 移動前に裏側ならば反転させる + float sign = contact.s; + float3 n = tn * sign; + + // 押し出し法線方向に投影した距離 + float dist = math.dot(n, nextPos - nextPos0); + //Debug.Log($"dist:{dist}"); + if (dist >= thickness) + return; + + // 引き離す距離 + float restDist = thickness; + + // 押し出し + float C = dist - restDist; + + float3 grad = n; + float3 grad0 = -n * uvw[0]; + float3 grad1 = -n * uvw[1]; + float3 grad2 = -n * uvw[2]; + + float s = invMass + invMass0 * uvw.x * uvw.x + invMass1 * uvw.y * uvw.y + invMass2 * uvw.z * uvw.z; + if (s == 0.0f) + return; + s = C / s; + + float3 corr = -s * invMass * grad; + float3 corr0 = -s * invMass0 * grad0; + float3 corr1 = -s * invMass1 * grad1; + float3 corr2 = -s * invMass2 * grad2; + +#if true + // 書き込み + if ((p0.flag & Flag_FixIntersect0) == 0) + { + InterlockUtility.AddFloat3(p0.particleIndices.x, corr, cntPt, sumPt); + } + if ((p1.flag & Flag_FixIntersect0) == 0) + { + InterlockUtility.AddFloat3(p1.particleIndices.x, corr0, cntPt, sumPt); + } + if ((p1.flag & Flag_FixIntersect1) == 0) + { + InterlockUtility.AddFloat3(p1.particleIndices.y, corr1, cntPt, sumPt); + } + if ((p1.flag & Flag_FixIntersect2) == 0) + { + InterlockUtility.AddFloat3(p1.particleIndices.z, corr2, cntPt, sumPt); + } +#endif + } + } + } + + [BurstCompile] + unsafe internal struct SelfStep_SumContactJob : IJobParallelFor + { + public int updateIndex; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + + // particle + [NativeDisableParallelForRestriction] + public NativeArray nextPosArray; + + // buffer2 + [NativeDisableParallelForRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + public NativeArray tempCountBuffer; + + // ローカルチームインデックスごと + public void Execute(int localIndex) + { + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + int* cntPt = (int*)tempCountBuffer.GetUnsafePtr(); + int* sumPt = (int*)tempVectorBufferA.GetUnsafePtr(); + float3* nextPosT = (float3*)nextPosArray.GetUnsafePtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + if (updateIndex < tdata.updateCount) + { + int pindex = tdata.particleChunk.startIndex; + int pindex2 = pindex * 3; + for (int i = 0; i < tdata.particleChunk.dataLength; i++, pindex++, pindex2 += 3) + { + int cnt = cntPt[pindex]; + if (cnt > 0) + { + float3 add = new float3(sumPt[pindex2], sumPt[pindex2 + 1], sumPt[pindex2 + 2]); + add /= cnt; + // データは固定小数点なので戻す + add *= InterlockUtility.ToFloat; + + // 反映 + *(nextPosT + pindex) += add; + } } } - if (enable) - contact.flagAndTeamId0 |= Flag_Enable; - else - contact.flagAndTeamId0 &= ~Flag_Enable; - - pointTriangleContactList[index] = contact; - } - } - - [BurstCompile] - unsafe struct SolverEdgeEdgeJob : IJobParallelForDefer - { - // particle - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - - // contact - [Unity.Collections.ReadOnly] - public NativeArray edgeEdgeContactArray; - - // output - [NativeDisableParallelForRestriction] - public NativeArray countArray; - [NativeDisableParallelForRestriction] - public NativeArray sumArray; - - // コンタクトごと - public void Execute(int index) - { - //Debug.Log($"EdgeEdgeContactCount:{edgeEdgeContactQueue.Count}"); - - var contact = edgeEdgeContactArray[index]; - if ((contact.flagAndTeamId0 & Flag_Enable) == 0) - return; - - var nextPosA0 = nextPosArray[contact.edgeParticleIndex0.x]; - var nextPosA1 = nextPosArray[contact.edgeParticleIndex0.y]; - var nextPosB0 = nextPosArray[contact.edgeParticleIndex1.x]; - var nextPosB1 = nextPosArray[contact.edgeParticleIndex1.y]; - - float s = contact.s; - float t = contact.t; - float3 n = contact.n; - float thickness = contact.thickness; - - // 移動前に接触判定を行った位置の移動後の位置a/bと方向ベクトル - float3 a = math.lerp(nextPosA0, nextPosA1, s); - float3 b = math.lerp(nextPosB0, nextPosB1, t); - float3 v = a - b; - - // 接触法線に現在の距離を投影させる - float l = math.dot(n, v); - //Debug.Log($"A({pA0}-{pA1}), B({pB0}-{pB1}) s:{s}, t:{t} l:{l}"); - if (l > thickness) - return; - - float invMassA0 = contact.edgeInvMass0.x; - float invMassA1 = contact.edgeInvMass0.y; - float invMassB0 = contact.edgeInvMass1.x; - float invMassB1 = contact.edgeInvMass1.y; - - // 離す距離 - float C = thickness - l; - - // お互いを離す - float b0 = 1.0f - s; - float b1 = s; - float b2 = 1.0f - t; - float b3 = t; - float3 grad0 = n * b0; - float3 grad1 = n * b1; - float3 grad2 = -n * b2; - float3 grad3 = -n * b3; - - float S = invMassA0 * b0 * b0 + invMassA1 * b1 * b1 + invMassB0 * b2 * b2 + invMassB1 * b3 * b3; - if (S == 0.0f) - return; - - S = C / S; - - float3 _A0 = S * invMassA0 * grad0; - float3 _A1 = S * invMassA1 * grad1; - float3 _B0 = S * invMassB0 * grad2; - float3 _B1 = S * invMassB1 * grad3; - - //===================================================== - // 書き込み - //===================================================== - int* cntPt = (int*)countArray.GetUnsafePtr(); - int* sumPt = (int*)sumArray.GetUnsafePtr(); - if ((contact.flagAndTeamId0 & Flag_Fix0) == 0) - InterlockUtility.AddFloat3(contact.edgeParticleIndex0.x, _A0, cntPt, sumPt); - //nextPosArray[contact.edgeParticleIndex0.x] = nextPosA0 + _A0; - if ((contact.flagAndTeamId0 & Flag_Fix1) == 0) - InterlockUtility.AddFloat3(contact.edgeParticleIndex0.y, _A1, cntPt, sumPt); - //nextPosArray[contact.edgeParticleIndex0.y] = nextPosA1 + _A1; - if ((contact.flagAndTeamId1 & Flag_Fix0) == 0) - InterlockUtility.AddFloat3(contact.edgeParticleIndex1.x, _B0, cntPt, sumPt); - //nextPosArray[contact.edgeParticleIndex1.x] = nextPosB0 + _B0; - if ((contact.flagAndTeamId1 & Flag_Fix1) == 0) - InterlockUtility.AddFloat3(contact.edgeParticleIndex1.y, _B1, cntPt, sumPt); - //nextPosArray[contact.edgeParticleIndex1.y] = nextPosB1 + _B1; - } - } - - [BurstCompile] - unsafe struct SolverPointTriangleJob : IJobParallelForDefer - { - // particle - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - - // contact - [Unity.Collections.ReadOnly] - public NativeArray pointTriangleContactArray; - - // output - [NativeDisableParallelForRestriction] - public NativeArray countArray; - [NativeDisableParallelForRestriction] - public NativeArray sumArray; - - // コンタクトごと - public void Execute(int index) - { - //Debug.Log($"PointTriangleContactCount:{pointTriangleContactQueue.Count}"); - - var contact = pointTriangleContactArray[index]; - if ((contact.flagAndTeamId0 & Flag_Enable) == 0) - return; - - // 接触距離 - float thickness = contact.thickness; - - // トライアングル情報 - int3 tp = contact.triangleParticleIndex; - float3 nextPos0 = nextPosArray[tp.x]; - float3 nextPos1 = nextPosArray[tp.y]; - float3 nextPos2 = nextPosArray[tp.z]; - float invMass0 = contact.triangleInvMass.x; - float invMass1 = contact.triangleInvMass.y; - float invMass2 = contact.triangleInvMass.z; - - // 移動後トライアングル法線 - float3 tn = MathUtility.TriangleNormal(nextPos0, nextPos1, nextPos2); - - // 対象パーティクル情報 - int t_pindex = contact.pointParticleIndex; - float3 nextPos = nextPosArray[t_pindex]; - float invMass = contact.pointInvMass; - - //===================================================== - // 衝突の解決 - //===================================================== - // 移動後ポイントと移動後トライアングルへの最近接点 - float3 uvw; - MathUtility.ClosestPtPointTriangle(nextPos, nextPos0, nextPos1, nextPos2, out uvw); - - // 押し出し方向(移動後のトライアングル法線) - // 移動前に裏側ならば反転させる - float sign = contact.sign; - float3 n = tn * sign; - - // 押し出し法線方向に投影した距離 - float dist = math.dot(n, nextPos - nextPos0); - //Debug.Log($"dist:{dist}"); - if (dist >= thickness) - return; - - // 引き離す距離 - float restDist = thickness; - - // 押し出し - float C = dist - restDist; - - float3 grad = n; - float3 grad0 = -n * uvw[0]; - float3 grad1 = -n * uvw[1]; - float3 grad2 = -n * uvw[2]; - - float s = invMass + invMass0 * uvw.x * uvw.x + invMass1 * uvw.y * uvw.y + invMass2 * uvw.z * uvw.z; - if (s == 0.0f) - return; - s = C / s; - - float3 corr = -s * invMass * grad; - float3 corr0 = -s * invMass0 * grad0; - float3 corr1 = -s * invMass1 * grad1; - float3 corr2 = -s * invMass2 * grad2; - - //===================================================== - // 書き込み - //===================================================== - int* cntPt = (int*)countArray.GetUnsafePtr(); - int* sumPt = (int*)sumArray.GetUnsafePtr(); - if ((contact.flagAndTeamId0 & Flag_Fix0) == 0) - InterlockUtility.AddFloat3(t_pindex, corr, cntPt, sumPt); - //nextPosArray[t_pindex] = nextPos + corr; - if ((contact.flagAndTeamId1 & Flag_Fix0) == 0) - InterlockUtility.AddFloat3(tp.x, corr0, cntPt, sumPt); - //nextPosArray[tp.x] = nextPos0 + corr0; - if ((contact.flagAndTeamId1 & Flag_Fix1) == 0) - InterlockUtility.AddFloat3(tp.y, corr1, cntPt, sumPt); - //nextPosArray[tp.y] = nextPos1 + corr1; - if ((contact.flagAndTeamId1 & Flag_Fix2) == 0) - InterlockUtility.AddFloat3(tp.z, corr2, cntPt, sumPt); - //nextPosArray[tp.z] = nextPos2 + corr2; - - //Debug.Log($"Solve:{contact.ToString()}"); + // バッファクリア + int pindexB = tdata.particleChunk.startIndex; + for (int i = 0; i < tdata.particleChunk.dataLength; i++, pindexB++) + { + tempCountBuffer[pindexB] = 0; + tempVectorBufferA[pindexB] = 0; + } } } //========================================================================================= - /// - /// 交差(絡まり)の解決 - /// - /// - /// - unsafe JobHandle SolveIntersect(JobHandle jobHandle) - { - if (IntersectCount == 0) - return jobHandle; - - var tm = MagicaManager.Team; - var sm = MagicaManager.Simulation; - - // 交差フラグクリア - jobHandle = JobUtility.Fill(intersectFlagArray, intersectFlagArray.Length, 0, jobHandle); - - // EdgePrimitiveのnextPos更新 - var updateJob1 = new IntersectUpdatePrimitiveJob() - { - kind = KindEdge, - teamDataArray = tm.teamDataArray.GetNativeArray(), - nextPosArray = sm.nextPosArray.GetNativeArray(), - primitiveArray = primitiveArray.GetNativeArray(), - processingArray = sm.processingSelfEdgeEdge.Buffer, - }; - jobHandle = updateJob1.Schedule(sm.processingSelfEdgeEdge.GetJobSchedulePtr(), 16, jobHandle); - - // TrianglePrimitiveのnextPos更新 - var updateJob2 = new IntersectUpdatePrimitiveJob() - { - kind = KindTriangle, - teamDataArray = tm.teamDataArray.GetNativeArray(), - nextPosArray = sm.nextPosArray.GetNativeArray(), - primitiveArray = primitiveArray.GetNativeArray(), - processingArray = sm.processingSelfTrianglePoint.Buffer, - }; - jobHandle = updateJob2.Schedule(sm.processingSelfTrianglePoint.GetJobSchedulePtr(), 16, jobHandle); - - // EdgeTriangle交差判定 - // !重い処理なのでステップごとに分割して少しずつ実行する - int stepCount = sm.SimulationStepCount; - int execNumber = stepCount % Define.System.SelfCollisionIntersectDiv; - - // !正確にはここでは交差を実際には解決しない - // !交差しているEdgeTriangleのパーティクルにフラグを付け、次のステップのセルフ衝突判定から除外することで絡まりを解く - // !衝突判定を行わないことでパーティクルは自由になり復元制約の効果で元の姿勢に戻ろうとする(この時からまりが解ける) - // !この方法は論文にない独自のもので精度も高くないが安価なコストで交差をある程度解消することでできる(ランタイム向き) - - // Edgeベース - var intersectJob1 = new IntersectEdgeTriangleJob() - { - mainKind = KindEdge, - execNumber = execNumber, - div = Define.System.SelfCollisionIntersectDiv, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - primitiveArray = primitiveArray.GetNativeArray(), - sortAndSweepArray = sortAndSweepArray.GetNativeArray(), - processingEdgeEdgeArray = sm.processingSelfEdgeEdge.Buffer, - intersectFlagArray = intersectFlagArray, - }; - jobHandle = intersectJob1.Schedule(sm.processingSelfEdgeEdge.GetJobSchedulePtr(), 16, jobHandle); - - // Triangleベース - var intersectJob2 = new IntersectEdgeTriangleJob() - { - mainKind = KindTriangle, - execNumber = execNumber, - div = Define.System.SelfCollisionIntersectDiv, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - primitiveArray = primitiveArray.GetNativeArray(), - sortAndSweepArray = sortAndSweepArray.GetNativeArray(), - processingEdgeEdgeArray = sm.processingSelfTrianglePoint.Buffer, - intersectFlagArray = intersectFlagArray, - }; - jobHandle = intersectJob2.Schedule(sm.processingSelfTrianglePoint.GetJobSchedulePtr(), 16, jobHandle); - - return jobHandle; - } - + // Intersect + //========================================================================================= [BurstCompile] - struct IntersectUpdatePrimitiveJob : IJobParallelForDefer + unsafe internal struct SelfDetectionIntersectJob : IJobParallelFor { - // プリミティブ種類 - public uint kind; + public int updateIndex; + public int workerCount; + public int frameIndex; // 0 ~ (Define.System.SelfCollisionIntersectDiv-1) // team [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] public NativeArray teamDataArray; + // self collision + [Unity.Collections.ReadOnly] + public NativeArray primitiveArrayB; + [Unity.Collections.ReadOnly] + public NativeArray uniformGridStartCountBuffer; + + // buffer + [NativeDisableParallelForRestriction] + public NativeQueue.ParallelWriter intersectQueue; + + // 1チーム + public void Execute(int index) + { + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + // チームインデックス + int localIndex = index / workerCount; + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + if (updateIndex >= tdata.updateCount) + return; + if (tdata.updateCount == 0) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + int workerIndex = index % workerCount; + + // ■Edge-Triangle接触バッファ作成 + // セルフコリジョン + if (tdata.flag.IsSet(TeamManager.Flag_Self_EdgeTriangleIntersect)) + { + DetectionIntersect( + workerCount, + workerIndex, + frameIndex, + // edge + teamId, + ref tdata, + KindEdge, + // triangle + teamId, + ref tdata, + KindTriangle, + // self collision + ref primitiveArrayB, + ref uniformGridStartCountBuffer, + // intersect + ref intersectQueue + ); + } + + // 相互コリジョン + if (tdata.syncTeamId > 0) + { + ref var stdata = ref *(teamPt + tdata.syncTeamId); + if (tdata.flag.IsSet(TeamManager.Flag_Sync_EdgeTriangleIntersect)) + { + DetectionIntersect( + workerCount, + workerIndex, + frameIndex, + // edge + teamId, + ref tdata, + KindEdge, + // triangle + tdata.syncTeamId, + ref stdata, + KindTriangle, + // self collision + ref primitiveArrayB, + ref uniformGridStartCountBuffer, + // intersect + ref intersectQueue + ); + } + if (tdata.flag.IsSet(TeamManager.Flag_Sync_TriangleEdgeIntersect)) + { + DetectionIntersect( + workerCount, + workerIndex, + frameIndex, + // triangle + teamId, + ref tdata, + KindTriangle, + // edge + tdata.syncTeamId, + ref stdata, + KindEdge, + // self collision + ref primitiveArrayB, + ref uniformGridStartCountBuffer, + // intersect + ref intersectQueue + ); + } + } + //Debug.Log($"Detection intersect. team:{teamId}, Count:{writeCount}"); + } + } + + unsafe static void DetectionIntersect( + int workerCount, + int workerIndex, + // 0 ~ (Define.System.SelfCollisionIntersectDiv-1) + int frameIndex, + // my + int myTeamId, + ref TeamManager.TeamData myTeam, + uint myKind, + // target + int targetTeamId, + ref TeamManager.TeamData targetTeam, + uint targetKind, + // self collision + ref NativeArray primitiveArrayB, + ref NativeArray uniformGridStartCountBuffer, + // intersect buffer + ref NativeQueue.ParallelWriter intersectQueue + ) + { + Primitive* pt = (Primitive*)primitiveArrayB.GetUnsafeReadOnlyPtr(); + GridInfo* gt = (GridInfo*)uniformGridStartCountBuffer.GetUnsafeReadOnlyPtr(); + + // 参照元 + DataChunk myPriChunk = myKind == KindPoint ? myTeam.selfPointChunk : (myKind == KindEdge ? myTeam.selfEdgeChunk : myTeam.selfTriangleChunk); + if (myPriChunk.IsValid == false) + return; + + // 対象 + DataChunk tarPriChunk = targetKind == KindPoint ? targetTeam.selfPointChunk : (targetKind == KindEdge ? targetTeam.selfEdgeChunk : targetTeam.selfTriangleChunk); + if (tarPriChunk.IsValid == false) + return; + int gridBufferStart = tarPriChunk.startIndex; + int gridBufferIndex = gridBufferStart; + int gridBufferCount = 0; + switch (targetKind) + { + case KindPoint: + gridBufferCount = targetTeam.selfPointGridCount; + break; + case KindEdge: + gridBufferCount = targetTeam.selfEdgeGridCount; + break; + case KindTriangle: + gridBufferCount = targetTeam.selfTriangleGridCount; + break; + } + float maxPrimitiveSize = targetTeam.selfMaxPrimitiveSize; + float gridSize = targetTeam.selfGridSize; + + // 初回の交差判定はグリッドサイズ更新前に到達するので除外する + if (maxPrimitiveSize <= Define.System.Epsilon || gridSize <= Define.System.Epsilon) + return; + + //Debug.Log($"edgeTeamId:{edgeTeamId}, triangleTeamId:{triangleTeamId}, gridBufferStart:{gridBufferStart}, gridBufferIndex:{gridBufferIndex}, gridBufferCount:{gridBufferCount}"); + //Debug.Log($"edgeTeamId:{edgeTeamId}, maxPrimitiveSize:{maxPrimitiveSize}, gridSize:{gridSize}"); + + // プリミティブの接続判定 + bool connectionCheck = myTeamId == targetTeamId; + + // 格納自の入れ替え + bool primitiveFlip = myKind != KindEdge; + + // 検索範囲 + var chunk = MathUtility.GetWorkerChunk(myPriChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + // プリミティブごと + GridInfo searchGridInfo = new GridInfo(); + int priIndex = myPriChunk.startIndex + chunk.startIndex; + for (int i = 0; i < chunk.dataLength; i++, priIndex++) + { + if ((priIndex % Define.System.SelfCollisionIntersectDiv) != frameIndex) + continue; + + ref var p = ref *(pt + priIndex); + + // 無効判定 + if (p.IsIgnore()) + continue; + + bool pFix = (p.flag & Flag_AllFix) != 0; + + // このプリミティブの検索範囲 + float3 areaMin = p.aabb.Min - maxPrimitiveSize * 0.5f; + float3 areaMax = p.aabb.Max + maxPrimitiveSize * 0.5f; + + // グリッド範囲に変換する + int3 startGrid = GetGrid(areaMin, gridSize); + int3 endGrid = GetGrid(areaMax, gridSize); + + // グリッド範囲を調べる + int3 currentGrid = startGrid; + bool finish = false; + while (finish == false) + { + // グリッド情報検索(ハッシュ値による2分探索) + int currentHash = currentGrid.GetHashCode(); + searchGridInfo.hash = currentHash; + int infoIndex = NativeSortExtension.BinarySearch(gt + gridBufferStart, gridBufferCount, searchGridInfo); + if (infoIndex >= 0) + { + // このグリッドにはプリミティブが存在する + ref var gridInfo = ref *(gt + gridBufferStart + infoIndex); + int startPriIndex2 = gridInfo.start; + int endPriIndex2 = startPriIndex2 + gridInfo.count; + + for (int priIndex2 = startPriIndex2; priIndex2 < endPriIndex2; priIndex2++) + { + ref var p2 = ref *(pt + priIndex2); + + // AABB判定 + if (p.aabb.Overlaps(p2.aabb) == false) + continue; + + // 無効判定 + if (p2.IsIgnore()) + continue; + + // 両方のプリミティブが完全固定ならば無効 + if (pFix && ((p2.flag & Flag_AllFix) != 0)) + continue; + + // プリミティブ同士が接続している場合は無効 + if (connectionCheck && p.AnyParticle(ref p2)) + continue; + + // !衝突検出! + // インターセクトバッファ生成 + var intersect = new IntersectInfo() + { + edgeParticeIndices = primitiveFlip == false ? p.particleIndices.xy : p2.particleIndices.xy, + triangleParticleIndices = primitiveFlip == false ? p2.particleIndices : p.particleIndices, + }; + intersectQueue.Enqueue(intersect); + + //Debug.Log($"Intersect0! edge:{p.particleIndices.xyz}, tri:{p2.particleIndices.xyz}"); + } + } + + // next + currentGrid.x++; + if (currentGrid.x > endGrid.x) + { + currentGrid.x = startGrid.x; + currentGrid.y++; + if (currentGrid.y > endGrid.y) + { + currentGrid.y = startGrid.y; + currentGrid.z++; + if (currentGrid.z > endGrid.z) + { + finish = true; + } + } + } + } + } + } + + [BurstCompile] + unsafe internal struct SelfConvertIntersectListJob : IJob + { + [Unity.Collections.ReadOnly] + public NativeQueue intersectQueue; + + [NativeDisableParallelForRestriction] + public NativeList intersectList; + + public void Execute() + { + intersectList.Clear(); + if (intersectQueue.Count > 0) + intersectList.AddRange(intersectQueue.ToArray(Allocator.Temp)); + + //Debug.Log($"intersect count:{intersectList.Length}"); + } + } + + [BurstCompile] + unsafe internal struct SelfClearIntersectJob : IJobParallelFor + { + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + // buffer + [Unity.Collections.WriteOnly] + [NativeDisableParallelForRestriction] + public NativeArray intersectFlagArray; + + public void Execute(int index) + { + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + // チームインデックス + int teamId = batchSelfTeamList[index]; + ref var tdata = ref *(teamPt + teamId); + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + int pindex = tdata.particleChunk.startIndex; + for (int i = 0; i < tdata.particleChunk.dataLength; i++, pindex++) + { + intersectFlagArray[pindex] = 0; + } + } + } + + [BurstCompile] + unsafe internal struct SelfSolverIntersectJob : IJobParallelForDefer + { // particle [Unity.Collections.ReadOnly] public NativeArray nextPosArray; - // constraint - [NativeDisableParallelForRestriction] - public NativeArray primitiveArray; - - // processing + // self collision [Unity.Collections.ReadOnly] - public NativeArray processingArray; + public NativeList intersectList; - public void Execute(int index) - { - uint pack = processingArray[index]; - int teamId = DataUtility.Unpack32Hi(pack); - int l_index = DataUtility.Unpack32Low(pack); - - // チームはこのステップで有効であることが保証されている - var tdata = teamDataArray[teamId]; - if (kind == KindEdge && tdata.flag.TestAny(TeamManager.Flag_Self_EdgeTriangleIntersect, 3) == false) - return; - if (kind == KindTriangle && tdata.flag.TestAny(TeamManager.Flag_Self_TriangleEdgeIntersect, 3) == false) - return; - - // primitive - int pri_index = 0; - switch (kind) - { - case KindPoint: - pri_index = tdata.selfPointChunk.startIndex + l_index; - break; - case KindEdge: - pri_index = tdata.selfEdgeChunk.startIndex + l_index; - break; - case KindTriangle: - pri_index = tdata.selfTriangleChunk.startIndex + l_index; - break; - } - var primitive = primitiveArray[pri_index]; - - // プリミティブnextPos更新 - int ac = (int)kind + 1; // 軸の数 - for (int i = 0; i < ac; i++) - { - int pindex = primitive.particleIndices[i]; - primitive.nextPos[i] = nextPosArray[pindex]; - } - primitiveArray[pri_index] = primitive; - } - } - - [BurstCompile] - struct IntersectEdgeTriangleJob : IJobParallelForDefer - { - public uint mainKind; - public int execNumber; - public int div; - - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - - // constraint - [Unity.Collections.ReadOnly] - public NativeArray primitiveArray; - [Unity.Collections.ReadOnly] - public NativeArray sortAndSweepArray; - - // processing - [Unity.Collections.ReadOnly] - public NativeArray processingEdgeEdgeArray; - - // out + // buffer + [Unity.Collections.WriteOnly] [NativeDisableParallelForRestriction] public NativeArray intersectFlagArray; - // 解決Edge/Triangleごと + public void Execute(int index) { -#if true - // 分割実行判定 - if (index % div != execNumber) - return; -#endif + IntersectInfo* it = (IntersectInfo*)intersectList.GetUnsafeReadOnlyPtr(); - uint pack = processingEdgeEdgeArray[index]; - int teamId = DataUtility.Unpack32Hi(pack); - int l_index = DataUtility.Unpack32Low(pack); + ref var intersect = ref *(it + index); - // チームはこのステップで有効であることが保証されている - var tdata = teamDataArray[teamId]; - if (mainKind == KindEdge && tdata.flag.TestAny(TeamManager.Flag_Self_EdgeTriangleIntersect, 3) == false) - return; - if (mainKind == KindTriangle && tdata.flag.TestAny(TeamManager.Flag_Self_TriangleEdgeIntersect, 3) == false) - return; + // edge + float3 p = nextPosArray[intersect.edgeParticeIndices.x]; + float3 q = nextPosArray[intersect.edgeParticeIndices.y]; - // メインとサブのチャンク - bool isEdge = mainKind == KindEdge; - var mainChunk = isEdge ? tdata.selfEdgeChunk : tdata.selfTriangleChunk; - var subChunk = isEdge ? tdata.selfTriangleChunk : tdata.selfEdgeChunk; - - // メインプリミティブ情報 - int priIndex0 = mainChunk.startIndex + l_index; - var primitive0 = primitiveArray[priIndex0]; - var sd0 = sortAndSweepArray[primitive0.sortIndex]; - - //============================================================= - // Self - //============================================================= - if (tdata.flag.IsSet(isEdge ? TeamManager.Flag_Self_EdgeTriangleIntersect : TeamManager.Flag_Self_TriangleEdgeIntersect)) - { - SweepTest(ref primitive0, sd0, subChunk, true); - } - - //============================================================= - // Sync - //============================================================= - if (tdata.flag.IsSet(isEdge ? TeamManager.Flag_Sync_EdgeTriangleIntersect : TeamManager.Flag_Sync_TriangleEdgeIntersect)) - { - var stdata = teamDataArray[tdata.syncTeamId]; - SweepTest(ref primitive0, sd0, isEdge ? stdata.selfTriangleChunk : stdata.selfEdgeChunk, false); - } - - //============================================================= - // Parent Sync - //============================================================= - if (tdata.flag.IsSet(isEdge ? TeamManager.Flag_PSync_EdgeTriangleIntersect : TeamManager.Flag_PSync_TriangleEdgeIntersect)) - { - int cnt = tdata.syncParentTeamId.Length; - for (int j = 0; j < cnt; j++) - { - int parentTeamId = tdata.syncParentTeamId[j]; - var stdata = teamDataArray[parentTeamId]; - if (stdata.flag.IsSet(isEdge ? TeamManager.Flag_Sync_TriangleEdgeIntersect : TeamManager.Flag_Sync_EdgeTriangleIntersect)) - { - SweepTest(ref primitive0, sd0, isEdge ? stdata.selfTriangleChunk : stdata.selfEdgeChunk, false); - } - } - } - } - - void SweepTest(ref Primitive primitive0, in SortData sd0, in DataChunk subChunk, bool connectionCheck) - { - // スイープ - int sortIndex = BinarySearchSortAndlSweep(ref sortAndSweepArray, sd0, subChunk); - float end = sd0.firstMinMax.y; - int endIndex = subChunk.startIndex + subChunk.dataLength; - while (sortIndex < endIndex) - { - var sd1 = sortAndSweepArray[sortIndex]; - sortIndex++; - - // first - if (sd1.firstMinMax.x <= end) - { - // second - if (sd1.secondMinMax.y < sd0.secondMinMax.x || sd1.secondMinMax.x > sd0.secondMinMax.y) - continue; - - // third - if (sd1.thirdMinMax.y < sd0.thirdMinMax.x || sd1.thirdMinMax.x > sd0.thirdMinMax.y) - continue; - - // この時点で両方のAABBは衝突している - var primitive1 = primitiveArray[sd1.primitiveIndex]; - - // プリミティブ同士が接続している場合は無効 - if (connectionCheck && primitive0.AnyParticle(primitive1)) - continue; - - // 両方のプリミティブが完全固定ならば無効 - if ((primitive0.flagAndTeamId & Flag_AllFix) != 0 && (primitive1.flagAndTeamId & Flag_AllFix) != 0) - continue; - - // 交差判定 - if (mainKind == KindEdge) - { - IntersectTest(ref primitive0, ref primitive1); - } - else - { - IntersectTest(ref primitive1, ref primitive0); - } - } - else - break; - } - } - - void IntersectTest(ref Primitive epri, ref Primitive tpri) - { - //Debug.Log($"IntersectTest. edge:{epri.particleIndices.xy}, tri:{tpri.particleIndices.xyz}"); + // triangle + float3 a = nextPosArray[intersect.triangleParticleIndices.x]; + float3 b = nextPosArray[intersect.triangleParticleIndices.y]; + float3 c = nextPosArray[intersect.triangleParticleIndices.z]; + // Intersect test // 線分とトライアングルの交差判定 - var p = epri.nextPos.c0; - var q = epri.nextPos.c1; var qp = p - q; - float3 a = tpri.nextPos.c0; - float3 b = tpri.nextPos.c1; - float3 c = tpri.nextPos.c2; var ac = c - a; var ab = b - a; float3 n = math.cross(ab, ac); @@ -2529,7 +2282,8 @@ namespace MagicaCloth2 // 法線裏側からの侵入に対応 if (d < 0.0f) { - p = epri.nextPos.c1; + //p = epri.nextPos.c1; + p = q; qp = -qp; d = -d; } @@ -2549,15 +2303,14 @@ namespace MagicaCloth2 if (w < 0.0f || (v + w) > d) return; - // 交差 - // EdgeとTriangleにフラグを立てる - intersectFlagArray[epri.particleIndices.x] = 1; - intersectFlagArray[epri.particleIndices.y] = 1; - intersectFlagArray[tpri.particleIndices.x] = 1; - intersectFlagArray[tpri.particleIndices.y] = 1; - intersectFlagArray[tpri.particleIndices.z] = 1; + // !交差! + // Edgeにフラグを立てる + intersectFlagArray[intersect.edgeParticeIndices.x] = 1; + intersectFlagArray[intersect.edgeParticeIndices.y] = 1; - //Debug.Log($"Intersect.[{execNumber}] Edge:{epri.particleIndices.xy}, Tri:{tpri.particleIndices.xyz}"); + // Triangleにはフラグは立てない + + //Debug.Log($"Intersect! edge:{p0.particleIndices.xyz}, tri:{p1.particleIndices.xyz}"); } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SelfCollisionConstraint.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SelfCollisionConstraint.cs.meta index 6ba80d67..97fc4b52 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SelfCollisionConstraint.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SelfCollisionConstraint.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SelfCollisionConstraint.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SpringConstraint.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SpringConstraint.cs index 186e8eef..39968c8c 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SpringConstraint.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SpringConstraint.cs @@ -3,7 +3,6 @@ // https://magicasoft.jp using System; -using Unity.Jobs; using UnityEngine; namespace MagicaCloth2 @@ -127,11 +126,5 @@ namespace MagicaCloth2 public void Dispose() { } - - //========================================================================================= - unsafe internal JobHandle SolverConstraint(JobHandle jobHandle) - { - return jobHandle; - } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SpringConstraint.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SpringConstraint.cs.meta index 7a1ec06a..0c9a1ac1 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SpringConstraint.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SpringConstraint.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/SpringConstraint.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TetherConstraint.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TetherConstraint.cs index 6d20503d..46840a4a 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TetherConstraint.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TetherConstraint.cs @@ -2,9 +2,7 @@ // Copyright (c) 2023 MagicaSoft. // https://magicasoft.jp using System; -using Unity.Burst; using Unity.Collections; -using Unity.Jobs; using Unity.Mathematics; using UnityEngine; @@ -32,7 +30,7 @@ namespace MagicaCloth2 public SerializeData() { - distanceCompression = 0.9f; + distanceCompression = 0.4f; } public void DataValidate() @@ -85,102 +83,41 @@ namespace MagicaCloth2 } //========================================================================================= - /// - /// 制約の解決 - /// - /// - /// - /// - unsafe internal JobHandle SolverConstraint(JobHandle jobHandle) - { - var tm = MagicaManager.Team; - var sm = MagicaManager.Simulation; - var vm = MagicaManager.VMesh; - - var job = new TethreConstraintJob() - { - stepParticleIndexArray = sm.processingStepParticle.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - centerDataArray = tm.centerDataArray.GetNativeArray(), - - attributes = vm.attributes.GetNativeArray(), - vertexDepths = vm.vertexDepths.GetNativeArray(), - vertexRootIndices = vm.vertexRootIndices.GetNativeArray(), - - teamIdArray = sm.teamIdArray.GetNativeArray(), - nextPosArray = sm.nextPosArray.GetNativeArray(), - velocityPosArray = sm.velocityPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - - stepBasicPositionBuffer = sm.stepBasicPositionBuffer, - }; - jobHandle = job.Schedule(sm.processingStepParticle.GetJobSchedulePtr(), 32, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct TethreConstraintJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray stepParticleIndexArray; - + // Solver + //========================================================================================= + internal static void SolverConstraint( + DataChunk chunk, // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - [Unity.Collections.ReadOnly] - public NativeArray centerDataArray; - + ref TeamManager.TeamData tdata, + ref ClothParameters param, + ref InertiaConstraint.CenterData cdata, // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [Unity.Collections.ReadOnly] - public NativeArray vertexDepths; - [Unity.Collections.ReadOnly] - public NativeArray vertexRootIndices; - + ref NativeArray attributes, + ref NativeArray vertexDepths, + ref NativeArray vertexRootIndices, // particle - [Unity.Collections.ReadOnly] - public NativeArray teamIdArray; - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - [NativeDisableParallelForRestriction] - public NativeArray velocityPosArray; - [Unity.Collections.ReadOnly] - public NativeArray frictionArray; - + ref NativeArray nextPosArray, + ref NativeArray velocityPosArray, + ref NativeArray frictionArray, // buffer - [Unity.Collections.ReadOnly] - public NativeArray stepBasicPositionBuffer; - - // パーティクルごと - public void Execute(int index) + ref NativeArray stepBasicPositionBuffer + ) + { + int p_start = tdata.particleChunk.startIndex; + //int pindex = p_start; + int pindex = p_start + chunk.startIndex; + //int vindex = tdata.proxyCommonChunk.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++) { - // pindexのチームは有効であることが保証されている - int pindex = stepParticleIndexArray[index]; - - int teamId = teamIdArray[pindex]; - var tdata = teamDataArray[teamId]; - var param = parameterArray[teamId].tetherConstraint; - //if (param.stiffness < 1e-06f) - // return; - - int p_start = tdata.particleChunk.startIndex; - int l_index = pindex - p_start; - int v_start = tdata.proxyCommonChunk.startIndex; - int vindex = v_start + l_index; - var attr = attributes[vindex]; if (attr.IsMove() == false) - return; + continue; int rootIndex = vertexRootIndices[vindex]; if (rootIndex < 0) - return; + continue; //Debug.Log($"Tether [{pindex}] root:{rootIndex + p_start}"); @@ -198,7 +135,7 @@ namespace MagicaCloth2 // 距離がほぼ0ならば処理をスキップする(エラーの回避) if (distance < Define.System.Epsilon) - return; + continue; // 復元距離 // フラグにより初期姿勢かアニメーション後姿勢かを切り替える @@ -210,7 +147,7 @@ namespace MagicaCloth2 // 初期位置がまったく同じ状況を考慮 if (calcDistance == 0.0f) - return; + continue; // 現在の伸縮割合 //Develop.Assert(calcDistance > 0.0f); @@ -220,8 +157,8 @@ namespace MagicaCloth2 float dist = 0; float stiffness; float attn; - float compressionLimit = 1.0f - param.compressionLimit; - float stretchLimit = 1.0f + param.stretchLimit; + float compressionLimit = 1.0f - param.tetherConstraint.compressionLimit; + float stretchLimit = 1.0f + param.tetherConstraint.stretchLimit; //float widthRatio = math.max(param.stiffnessWidth, 0.001f); // 0.2? //float widthRatio = 0.1f; // 0.2? if (ratio < compressionLimit) @@ -243,7 +180,7 @@ namespace MagicaCloth2 attn = Define.System.TetherStretchVelocityAttenuation; } else - return; + continue; // 移動量 float3 add = (v / distance) * (dist * stiffness); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TetherConstraint.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TetherConstraint.cs.meta index 4e1dc9e2..72152c36 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TetherConstraint.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TetherConstraint.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TetherConstraint.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TriangleBendingConstraint.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TriangleBendingConstraint.cs index b7211c41..4a498f1b 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TriangleBendingConstraint.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TriangleBendingConstraint.cs @@ -4,9 +4,8 @@ using System; using System.Collections.Generic; using System.Text; -using Unity.Burst; using Unity.Collections; -using Unity.Jobs; +using Unity.Collections.LowLevel.Unsafe; using Unity.Mathematics; using UnityEngine; @@ -17,6 +16,11 @@ namespace MagicaCloth2 /// public class TriangleBendingConstraint : IDisposable { + /// + /// ボリュームとして処理する判定フラグ + /// + const sbyte VOLUME_SIGN = 100; + public enum Method { None = 0, @@ -29,7 +33,7 @@ namespace MagicaCloth2 /// /// 方向性ありの2面角曲げ制約 - /// 初期姿勢を保た持つように復元する + /// 初期姿勢を保つように復元する /// DirectionDihedralAngle = 2, } @@ -73,16 +77,17 @@ namespace MagicaCloth2 public void Convert(SerializeData sdata) { - //method = sdata.method; // モードはDirectionDihedralAngleに固定する method = sdata.stiffness > Define.System.Epsilon ? Method.DirectionDihedralAngle : Method.None; + //method = sdata.stiffness > Define.System.Epsilon ? Method.DihedralAngle : Method.None; stiffness = sdata.stiffness; } } //========================================================================================= - internal class ConstraintData : IValid + [System.Serializable] + public class ConstraintData : IValid { public ResultCode result; public ulong[] trianglePairArray; @@ -116,29 +121,16 @@ namespace MagicaCloth2 public ExNativeArray restAngleOrVolumeArray; /// - /// トライアングルペアごとの復元方向もしくはボリューム判定(100=このペアはボリュームである) + /// トライアングルペアごとの復元方向もしくはボリューム判定(VOLUME_SIGN(100)=このペアはボリュームである) /// public ExNativeArray signOrVolumeArray; - /// - /// トライアングルペアごとの結果書き込みローカルインデックス - /// 4つのbyteを1つのuintに結合したもの - /// - public ExNativeArray writeDataArray; + //public int DataCount => trianglePairArray?.Count ?? 0; /// - /// 頂点ごとの書き込みバッファの数と開始インデックス - /// (上位10bit = カウンタ, 下位22bit = 開始インデックス) + /// ボリューム計算の浮動小数点誤差を回避するための倍数 /// - public ExNativeArray writeIndexArray; - - /// - /// 頂点ごとの書き込みバッファ(集計用) - /// writeIndexArrayに従う - /// - public ExNativeArray writeBuffer; - - public int DataCount => trianglePairArray?.Count ?? 0; + const float VolumeScale = 1000.0f; //========================================================================================= public TriangleBendingConstraint() @@ -146,9 +138,6 @@ namespace MagicaCloth2 trianglePairArray = new ExNativeArray(0, true); restAngleOrVolumeArray = new ExNativeArray(0, true); signOrVolumeArray = new ExNativeArray(0, true); - writeDataArray = new ExNativeArray(0, true); - writeIndexArray = new ExNativeArray(0, true); - writeBuffer = new ExNativeArray(0, true); } public void Dispose() @@ -156,9 +145,6 @@ namespace MagicaCloth2 trianglePairArray?.Dispose(); restAngleOrVolumeArray?.Dispose(); signOrVolumeArray?.Dispose(); - writeDataArray?.Dispose(); - writeIndexArray?.Dispose(); - writeBuffer?.Dispose(); trianglePairArray = null; restAngleOrVolumeArray = null; @@ -172,9 +158,6 @@ namespace MagicaCloth2 sb.AppendLine($" -trianglePairArray:{trianglePairArray.ToSummary()}"); sb.AppendLine($" -restAngleOrVolumeArray:{restAngleOrVolumeArray.ToSummary()}"); sb.AppendLine($" -signOrVolumeArray:{signOrVolumeArray.ToSummary()}"); - sb.AppendLine($" -writeDataArray:{writeDataArray.ToSummary()}"); - sb.AppendLine($" -writeIndexArray:{writeIndexArray.ToSummary()}"); - sb.AppendLine($" -writeBuffer:{writeBuffer.ToSummary()}"); return sb.ToString(); } @@ -186,7 +169,7 @@ namespace MagicaCloth2 /// /// /// - internal static ConstraintData CreateData(VirtualMesh proxyMesh, in ClothParameters parameters) + public static ConstraintData CreateData(VirtualMesh proxyMesh, in ClothParameters parameters) { var constraintData = new ConstraintData(); @@ -223,7 +206,7 @@ namespace MagicaCloth2 if (proxyMesh.edgeToTriangles.ContainsKey(edge) == false) continue; - var triangles = proxyMesh.edgeToTriangles.ToFixedList128Bytes(edge); + var triangles = proxyMesh.edgeToTriangles.MC2ToFixedList128Bytes(edge); int tcnt = triangles.Length; // トライアングルの組み合わせ @@ -276,6 +259,7 @@ namespace MagicaCloth2 trianglePairList.Add(pair); restAngleOrVolumeList.Add(restData); signOrVolumeList.Add(signFlag); + //Debug.Log($"rest angle:{math.degrees(restData)}, signFlag:{signFlag}"); uint writeData = DataUtility.Pack32( multiBuilder.CountValuesForKey(vtx.x), @@ -320,7 +304,7 @@ namespace MagicaCloth2 volumeCount++; - //Develop.DebugLog($"Volume Pair. edge:{edge}, tri:({tri0},{tri1}) restAngle:{degAngle}"); + //Develop.DebugLog($"Volume Pair. edge:{edge}, tri:({tri0},{tri1}) restAngle:{degAngle}, restData:{restData}, signFlag:{signFlag}"); } } //if (math.all(tri0 - 243) == false || math.all(tri1 - 243) == false) @@ -357,13 +341,15 @@ namespace MagicaCloth2 static void InitVolume(VirtualMesh proxyMesh, int v0, int v1, int v2, int v3, out float volumeRest, out sbyte signFlag) { // 0/1が対角点,2/3が共通辺 - float3 pos0 = proxyMesh.localPositions[v0]; - float3 pos1 = proxyMesh.localPositions[v1]; - float3 pos2 = proxyMesh.localPositions[v2]; - float3 pos3 = proxyMesh.localPositions[v3]; + // ここは実行時とボリューム値を合わせるためワールド座標で計算する必要がある。 + float3 pos0 = MathUtility.TransformPoint(proxyMesh.localPositions[v0], proxyMesh.initLocalToWorld); + float3 pos1 = MathUtility.TransformPoint(proxyMesh.localPositions[v1], proxyMesh.initLocalToWorld); + float3 pos2 = MathUtility.TransformPoint(proxyMesh.localPositions[v2], proxyMesh.initLocalToWorld); + float3 pos3 = MathUtility.TransformPoint(proxyMesh.localPositions[v3], proxyMesh.initLocalToWorld); volumeRest = (1.0f / 6.0f) * math.dot(math.cross(pos1 - pos0, pos2 - pos0), pos3 - pos0); - signFlag = 100; // Volume + volumeRest *= VolumeScale; // 浮動小数点演算誤差回避 + signFlag = VOLUME_SIGN; // Volume } static void InitDihedralAngle(VirtualMesh proxyMesh, int v0, int v1, int v2, int v3, out float restAngle, out sbyte signFlag) @@ -409,11 +395,6 @@ namespace MagicaCloth2 tdata.bendingPairChunk = trianglePairArray.AddRange(cdata.trianglePairArray); restAngleOrVolumeArray.AddRange(cdata.restAngleOrVolumeArray); signOrVolumeArray.AddRange(cdata.signOrVolumeArray); - writeDataArray.AddRange(cdata.writeDataArray); - - // write buffer - tdata.bendingWriteIndexChunk = writeIndexArray.AddRange(cdata.writeIndexArray); - tdata.bendingBufferChunk = writeBuffer.AddRange(cdata.writeBufferCount); } } @@ -430,159 +411,78 @@ namespace MagicaCloth2 trianglePairArray.Remove(tdata.bendingPairChunk); restAngleOrVolumeArray.Remove(tdata.bendingPairChunk); signOrVolumeArray.Remove(tdata.bendingPairChunk); - writeDataArray.Remove(tdata.bendingPairChunk); - - // write buffer - writeIndexArray.Remove(tdata.bendingWriteIndexChunk); - writeBuffer.Remove(tdata.bendingBufferChunk); tdata.bendingPairChunk.Clear(); - tdata.bendingWriteIndexChunk.Clear(); - tdata.bendingBufferChunk.Clear(); } } //========================================================================================= - /// - /// 制約の解決 - /// - /// - /// - unsafe internal JobHandle SolverConstraint(JobHandle jobHandle) - { - var tm = MagicaManager.Team; - var sm = MagicaManager.Simulation; - var vm = MagicaManager.VMesh; - - if (DataCount > 0) - { - var triangleBendingJob = new TriangleBendingJob() - { - simulationPower = MagicaManager.Time.SimulationPower, - - stepTriangleBendIndexArray = sm.processingStepTriangleBending.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - - attributes = vm.attributes.GetNativeArray(), - depthArray = vm.vertexDepths.GetNativeArray(), - - nextPosArray = sm.nextPosArray.GetNativeArray(), - frictionArray = sm.frictionArray.GetNativeArray(), - - trianglePairArray = trianglePairArray.GetNativeArray(), - restAngleOrVolumeArray = restAngleOrVolumeArray.GetNativeArray(), - signOrVolumeArray = signOrVolumeArray.GetNativeArray(), - - writeDataArray = writeDataArray.GetNativeArray(), - writeIndexArray = writeIndexArray.GetNativeArray(), - writeBuffer = writeBuffer.GetNativeArray(), - }; - jobHandle = triangleBendingJob.Schedule(sm.processingStepTriangleBending.GetJobSchedulePtr(), 16, jobHandle); - - // 集計(速度影響はなし) - var aggregateJob = new SolveAggregateBufferJob() - { - stepParticleIndexArray = sm.processingStepParticle.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - - attributes = vm.attributes.GetNativeArray(), - - teamIdArray = sm.teamIdArray.GetNativeArray(), - nextPosArray = sm.nextPosArray.GetNativeArray(), - - writeIndexArray = writeIndexArray.GetNativeArray(), - writeBuffer = writeBuffer.GetNativeArray(), - }; - jobHandle = aggregateJob.Schedule(sm.processingStepParticle.GetJobSchedulePtr(), 16, jobHandle); - } - - return jobHandle; - } - - [BurstCompile] - struct TriangleBendingJob : IJobParallelForDefer - { - public float4 simulationPower; - - [Unity.Collections.ReadOnly] - public NativeArray stepTriangleBendIndexArray; - + // Solver + //========================================================================================= + internal unsafe static void SolverConstraint( + DataChunk chunk, + in float4 simulationPower, // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - + ref TeamManager.TeamData tdata, + ref ClothParameters param, // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [Unity.Collections.ReadOnly] - public NativeArray depthArray; - - + ref NativeArray attributes, + ref NativeArray depthArray, // particle - [Unity.Collections.ReadOnly] - public NativeArray nextPosArray; - [Unity.Collections.ReadOnly] - public NativeArray frictionArray; - + ref NativeArray nextPosArray, + ref NativeArray frictionArray, // constraints - [Unity.Collections.ReadOnly] - public NativeArray trianglePairArray; - [Unity.Collections.ReadOnly] - public NativeArray restAngleOrVolumeArray; - [Unity.Collections.ReadOnly] - public NativeArray signOrVolumeArray; - [Unity.Collections.ReadOnly] - public NativeArray writeDataArray; - [Unity.Collections.ReadOnly] - public NativeArray writeIndexArray; + ref NativeArray trianglePairArray, + ref NativeArray restAngleOrVolumeArray, + ref NativeArray signOrVolumeArray, + // buffer2 + ref NativeArray tempVectorBufferA, + ref NativeArray tempCountBuffer + ) + { + if (param.triangleBendingConstraint.method == Method.None) + return; - // output - [NativeDisableParallelForRestriction] - public NativeArray writeBuffer; + if (tdata.bendingPairChunk.IsValid == false) + return; - // ベンドトライアングルペアごと - public void Execute(int index) + // 剛性 + float stiffness = param.triangleBendingConstraint.stiffness; + if (stiffness < 1e-06f) + return; + stiffness = math.saturate(stiffness * simulationPower.y); + + int p_start = tdata.particleChunk.startIndex; + int v_start = tdata.proxyCommonChunk.startIndex; + int pindex; + int vindex; + + int* sumPt = (int*)tempVectorBufferA.GetUnsafePtr(); + int* cntPt = (int*)tempCountBuffer.GetUnsafePtr(); + + // ■計算 + // ベンドペアごと + //int pairIndex = tdata.bendingPairChunk.startIndex; + int pairIndex = tdata.bendingPairChunk.startIndex + chunk.startIndex; + //for (int k = 0; k < tdata.bendingPairChunk.dataLength; k++, pairIndex++) + for (int k = 0; k < chunk.dataLength; k++, pairIndex++) { - // インデックスのチームは有効であることが保証されている - //int pairIndex = stepTriangleBendIndexArray[index]; - //int teamId = trianglePairTeamIdArray[pairIndex]; - uint pack = (uint)stepTriangleBendIndexArray[index]; - int pairIndex = DataUtility.Unpack12_20Low(pack); - int teamId = DataUtility.Unpack12_20Hi(pack); - var tdata = teamDataArray[teamId]; - var parameter = parameterArray[teamId].triangleBendingConstraint; - if (parameter.method == Method.None) - return; - - // 剛性 - float stiffness = parameter.stiffness; - if (stiffness < 1e-06f) - return; - stiffness = math.saturate(stiffness * simulationPower.y); - - - int p_start = tdata.particleChunk.startIndex; - int v_start = tdata.proxyCommonChunk.startIndex; - // トライアングルペア var pairData = trianglePairArray[pairIndex]; int4 vertices = DataUtility.Unpack64(pairData); //Debug.Log(vertices); + int4 pindex4 = vertices + p_start; + int4 vindex4 = vertices + v_start; + // 状態 float3x4 nextPosBuffer = 0; float3x4 addPosBuffer = 0; float4 invMassBuffer = 1; - //int4 fixedBuffer = 0; for (int i = 0; i < 4; i++) { - int pindex = p_start + vertices[i]; - int vindex = v_start + vertices[i]; + pindex = pindex4[i]; + vindex = vindex4[i]; nextPosBuffer[i] = nextPosArray[pindex]; float friction = frictionArray[pindex]; float depth = depthArray[vindex]; @@ -598,220 +498,241 @@ namespace MagicaCloth2 // メソッドごとの解決 bool result = false; - if (signOrVolume == 100) + if (signOrVolume == VOLUME_SIGN) { // Volume - result = Volume(nextPosBuffer, invMassBuffer, restAngle, stiffness, ref addPosBuffer); + float volumeRest = restAngle * tdata.scaleRatio; // スケール倍率 + + // マイナススケール + volumeRest *= tdata.negativeScaleSign; + + result = CalcVolume(nextPosBuffer, invMassBuffer, volumeRest, stiffness, ref addPosBuffer); } else { // Triangle Bending - float sign = signOrVolume < 0 ? -1 : 1; - if (parameter.method == Method.DihedralAngle) + if (param.triangleBendingConstraint.method == Method.DihedralAngle) { - // 二面角 - result = DihedralAngle(0, nextPosBuffer, invMassBuffer, restAngle, stiffness, ref addPosBuffer); + // 方向性なし二面角 + result = CalcDihedralAngle(0, nextPosBuffer, invMassBuffer, restAngle, stiffness, ref addPosBuffer); } - else if (parameter.method == Method.DirectionDihedralAngle) + else if (param.triangleBendingConstraint.method == Method.DirectionDihedralAngle) { - // 方向性二面角 + // 方向性あり二面角 + float sign = signOrVolume < 0 ? -1 : 1; restAngle *= sign; - result = DihedralAngle(sign, nextPosBuffer, invMassBuffer, restAngle, stiffness, ref addPosBuffer); + + // マイナススケール + restAngle *= tdata.negativeScaleSign; + + result = CalcDihedralAngle(sign, nextPosBuffer, invMassBuffer, restAngle, stiffness, ref addPosBuffer); } } // 集計バッファへ格納 if (result) { - int4 writeData = DataUtility.Unpack32(writeDataArray[dataIndex]); - int indexStart = tdata.bendingWriteIndexChunk.startIndex; - int bufferStart = tdata.bendingBufferChunk.startIndex; for (int i = 0; i < 4; i++) { - int l_vindex = vertices[i]; - int start = DataUtility.Unpack12_20Low(writeIndexArray[indexStart + l_vindex]); - int bufferIndex = bufferStart + start + writeData[i]; - writeBuffer[bufferIndex] = addPosBuffer[i]; + pindex = pindex4[i]; + InterlockUtility.AddFloat3(pindex, addPosBuffer[i], cntPt, sumPt); } } } + } - bool Volume(in float3x4 nextPosBuffer, in float4 invMassBuffer, float volumeRest, float stiffness, ref float3x4 addPosBuffer) + internal unsafe static void SumConstraint( + DataChunk chunk, + // team + ref TeamManager.TeamData tdata, + ref ClothParameters param, + // vmesh + ref NativeArray attributes, + // particle + ref NativeArray nextPosArray, + // buffer2 + ref NativeArray tempVectorBufferA, + ref NativeArray tempCountBuffer + ) + { + if (param.triangleBendingConstraint.method == Method.None) + return; + + if (tdata.bendingPairChunk.IsValid == false) + return; + + // 剛性 + float stiffness = param.triangleBendingConstraint.stiffness; + if (stiffness < 1e-06f) + return; + + int p_start = tdata.particleChunk.startIndex; + int v_start = tdata.proxyCommonChunk.startIndex; + + int* sumPt = (int*)tempVectorBufferA.GetUnsafePtr(); + int* cntPt = (int*)tempCountBuffer.GetUnsafePtr(); + + // ■集計 + // パーティクルごと + int pindex = p_start + chunk.startIndex; + 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++) { - float3 nextPos0 = nextPosBuffer[0]; - float3 nextPos1 = nextPosBuffer[1]; - float3 nextPos2 = nextPosBuffer[2]; - float3 nextPos3 = nextPosBuffer[3]; - - float invMass0 = invMassBuffer[0]; - float invMass1 = invMassBuffer[1]; - float invMass2 = invMassBuffer[2]; - float invMass3 = invMassBuffer[3]; - - float volume = (1.0f / 6.0f) * math.dot(math.cross(nextPos1 - nextPos0, nextPos2 - nextPos0), nextPos3 - nextPos0); - - float3 grad0 = math.cross(nextPos1 - nextPos2, nextPos3 - nextPos2); - float3 grad1 = math.cross(nextPos2 - nextPos0, nextPos3 - nextPos0); - float3 grad2 = math.cross(nextPos0 - nextPos1, nextPos3 - nextPos1); - float3 grad3 = math.cross(nextPos1 - nextPos0, nextPos2 - nextPos0); - - float lambda = - invMass0 * math.lengthsq(grad0) + - invMass1 * math.lengthsq(grad1) + - invMass2 * math.lengthsq(grad2) + - invMass3 * math.lengthsq(grad3); - - if (math.abs(lambda) < 1e-06f) - return false; - - lambda = stiffness * (volume - volumeRest) / lambda; - - addPosBuffer[0] = -lambda * invMass0 * grad0; - addPosBuffer[1] = -lambda * invMass1 * grad1; - addPosBuffer[2] = -lambda * invMass2 * grad2; - addPosBuffer[3] = -lambda * invMass3 * grad3; - - return true; - } - - bool DihedralAngle(float sign, in float3x4 nextPosBuffer, in float4 invMassBuffer, float restAngle, float stiffness, ref float3x4 addPosBuffer) - { - float3 nextPos0 = nextPosBuffer[0]; - float3 nextPos1 = nextPosBuffer[1]; - float3 nextPos2 = nextPosBuffer[2]; - float3 nextPos3 = nextPosBuffer[3]; - - float invMass0 = invMassBuffer[0]; - float invMass1 = invMassBuffer[1]; - float invMass2 = invMassBuffer[2]; - float invMass3 = invMassBuffer[3]; - - float3 e = nextPos3 - nextPos2; - float elen = math.length(e); - if (elen < 1e-08f) - return false; - - float invElen = 1.0f / elen; - - float3 n1 = math.cross(nextPos2 - nextPos0, nextPos3 - nextPos0); - float3 n2 = math.cross(nextPos3 - nextPos1, nextPos2 - nextPos1); - float n1_lengsq = math.lengthsq(n1); - float n2_lengsq = math.lengthsq(n2); - - // 稀に発生する長さ0に対処 - if (n1_lengsq == 0.0f || n2_lengsq == 0.0f) - return false; - //Develop.Assert(n1_lengsq > 0.0f); - //Develop.Assert(n2_lengsq > 0.0f); - n1 /= n1_lengsq; - n2 /= n2_lengsq; - - float3 d0 = elen * n1; - float3 d1 = elen * n2; - float3 d2 = math.dot(nextPos0 - nextPos3, e) * invElen * n1 + math.dot(nextPos1 - nextPos3, e) * invElen * n2; - float3 d3 = math.dot(nextPos2 - nextPos0, e) * invElen * n1 + math.dot(nextPos2 - nextPos1, e) * invElen * n2; - - n1 = math.normalize(n1); - n2 = math.normalize(n2); - float dot = math.dot(n1, n2); - dot = MathUtility.Clamp1(dot); - float phi = math.acos(dot); - - // 方向性 - float dir = math.dot(math.cross(n1, n2), e); - if (sign != 0) + // 移動のみ + if (attributes[vindex].IsDontMove() == false) { - phi *= math.sign(dir); - dir = 1; // lambdaを反転させるため + int cnt = cntPt[pindex]; + if (cnt > 0) + { + int pindex2 = pindex * 3; + float3 add = new float3(sumPt[pindex2], sumPt[pindex2 + 1], sumPt[pindex2 + 2]); + add /= cnt; + // データは固定小数点なので戻す + add *= InterlockUtility.ToFloat; + + nextPosArray[pindex] = nextPosArray[pindex] + add; + } } - float lambda = - invMass0 * math.lengthsq(d0) + - invMass1 * math.lengthsq(d1) + - invMass2 * math.lengthsq(d2) + - invMass3 * math.lengthsq(d3); - - if (lambda == 0.0f) - return false; - - lambda = (phi - restAngle) / lambda * stiffness; - - if (dir > 0.0f) - lambda = -lambda; - - float3 corr0 = -invMass0 * lambda * d0; - float3 corr1 = -invMass1 * lambda * d1; - float3 corr2 = -invMass2 * lambda * d2; - float3 corr3 = -invMass3 * lambda * d3; - - addPosBuffer[0] = corr0; - addPosBuffer[1] = corr1; - addPosBuffer[2] = corr2; - addPosBuffer[3] = corr3; - - return true; + // バッファクリア + tempCountBuffer[pindex] = 0; + tempVectorBufferA[pindex] = 0; } } - [BurstCompile] - struct SolveAggregateBufferJob : IJobParallelForDefer + static bool CalcVolume( + in float3x4 nextPosBuffer, + in float4 invMassBuffer, + float volumeRest, + float stiffness, + ref float3x4 addPosBuffer + ) { - [Unity.Collections.ReadOnly] - public NativeArray stepParticleIndexArray; + float3 nextPos0 = nextPosBuffer[0]; + float3 nextPos1 = nextPosBuffer[1]; + float3 nextPos2 = nextPosBuffer[2]; + float3 nextPos3 = nextPosBuffer[3]; - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; + float invMass0 = invMassBuffer[0]; + float invMass1 = invMassBuffer[1]; + float invMass2 = invMassBuffer[2]; + float invMass3 = invMassBuffer[3]; - // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; + float volume = (1.0f / 6.0f) * math.dot(math.cross(nextPos1 - nextPos0, nextPos2 - nextPos0), nextPos3 - nextPos0); + volume *= VolumeScale; // 浮動小数点演算誤差回避 - // particle - [Unity.Collections.ReadOnly] - public NativeArray teamIdArray; - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; + float3 grad0 = math.cross(nextPos1 - nextPos2, nextPos3 - nextPos2); + float3 grad1 = math.cross(nextPos2 - nextPos0, nextPos3 - nextPos0); + float3 grad2 = math.cross(nextPos0 - nextPos1, nextPos3 - nextPos1); + float3 grad3 = math.cross(nextPos1 - nextPos0, nextPos2 - nextPos0); - // constraint - [Unity.Collections.ReadOnly] - public NativeArray writeIndexArray; - [Unity.Collections.ReadOnly] - public NativeArray writeBuffer; + float lambda = + invMass0 * math.lengthsq(grad0) + + invMass1 * math.lengthsq(grad1) + + invMass2 * math.lengthsq(grad2) + + invMass3 * math.lengthsq(grad3); + lambda *= VolumeScale; // 浮動小数点演算誤差回避 - // ステップパーティクルごと - public void Execute(int index) + if (math.abs(lambda) < 1e-06f) + return false; + + lambda = stiffness * (volumeRest - volume) / lambda; + + addPosBuffer[0] = lambda * invMass0 * grad0; + addPosBuffer[1] = lambda * invMass1 * grad1; + addPosBuffer[2] = lambda * invMass2 * grad2; + addPosBuffer[3] = lambda * invMass3 * grad3; + + return true; + } + + static bool CalcDihedralAngle( + float sign, + in float3x4 nextPosBuffer, + in float4 invMassBuffer, + float restAngle, + float stiffness, + ref float3x4 addPosBuffer + ) + { + float3 nextPos0 = nextPosBuffer[0]; + float3 nextPos1 = nextPosBuffer[1]; + float3 nextPos2 = nextPosBuffer[2]; + float3 nextPos3 = nextPosBuffer[3]; + + float invMass0 = invMassBuffer[0]; + float invMass1 = invMassBuffer[1]; + float invMass2 = invMassBuffer[2]; + float invMass3 = invMassBuffer[3]; + + float3 e = nextPos3 - nextPos2; + float elen = math.length(e); + if (elen < 1e-08f) + return false; + + float invElen = 1.0f / elen; + + float3 n1 = math.cross(nextPos2 - nextPos0, nextPos3 - nextPos0); + float3 n2 = math.cross(nextPos3 - nextPos1, nextPos2 - nextPos1); + + float n1_lengsq = math.lengthsq(n1); + float n2_lengsq = math.lengthsq(n2); + + // 稀に発生する長さ0に対処 + if (n1_lengsq == 0.0f || n2_lengsq == 0.0f) + return false; + //Develop.Assert(n1_lengsq > 0.0f); + //Develop.Assert(n2_lengsq > 0.0f); + n1 /= n1_lengsq; + n2 /= n2_lengsq; + + float3 d0 = elen * n1; + float3 d1 = elen * n2; + float3 d2 = math.dot(nextPos0 - nextPos3, e) * invElen * n1 + math.dot(nextPos1 - nextPos3, e) * invElen * n2; + float3 d3 = math.dot(nextPos2 - nextPos0, e) * invElen * n1 + math.dot(nextPos2 - nextPos1, e) * invElen * n2; + + n1 = math.normalize(n1); + n2 = math.normalize(n2); + float dot = math.dot(n1, n2); + dot = MathUtility.Clamp1(dot); + float phi = math.acos(dot); + + float lambda = + invMass0 * math.lengthsq(d0) + + invMass1 * math.lengthsq(d1) + + invMass2 * math.lengthsq(d2) + + invMass3 * math.lengthsq(d3); + + if (lambda == 0.0f) + return false; + + // 方向性 + float dirSign = math.sign(math.dot(math.cross(n1, n2), e)); + if (sign != 0) { - // pindexのチームは有効であることが保証されている - int pindex = stepParticleIndexArray[index]; - int teamId = teamIdArray[pindex]; - var tdata = teamDataArray[teamId]; - if (tdata.bendingPairChunk.IsValid == false) - return; - - int l_index = pindex - tdata.particleChunk.startIndex; - - // 固定なら無効 - int vindex = tdata.proxyCommonChunk.startIndex + l_index; - if (attributes[vindex].IsDontMove()) - return; - - // 書き込みバッファの値を平均化してnextPosに加算する - uint pack = writeIndexArray[tdata.bendingWriteIndexChunk.startIndex + l_index]; - int cnt = DataUtility.Unpack12_20Hi(pack); - int start = DataUtility.Unpack12_20Low(pack); - int bufferIndex = tdata.bendingBufferChunk.startIndex + start; - float3 add = 0; - for (int i = 0; i < cnt; i++) - { - add += writeBuffer[bufferIndex + i]; - } - if (cnt > 0) - { - add /= cnt; - nextPosArray[pindex] = nextPosArray[pindex] + add; - } + // 方向性あり(DirectionDihedralAngle) + phi *= dirSign; } + else + { + // 方向性なし(DihedralAngle) + lambda *= dirSign; + } + + lambda = (restAngle - phi) / lambda * stiffness; + + float3 corr0 = -invMass0 * lambda * d0; + float3 corr1 = -invMass1 * lambda * d1; + float3 corr2 = -invMass2 * lambda * d2; + float3 corr3 = -invMass3 * lambda * d3; + + addPosBuffer[0] = corr0; + addPosBuffer[1] = corr1; + addPosBuffer[2] = corr2; + addPosBuffer[3] = corr3; + + return true; } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TriangleBendingConstraint.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TriangleBendingConstraint.cs.meta index ec0bb69e..192ef7ea 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TriangleBendingConstraint.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TriangleBendingConstraint.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Constraints/TriangleBendingConstraint.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CullingSettings.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CullingSettings.cs index b8423828..831413c1 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CullingSettings.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CullingSettings.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Magica Cloth 2. +// Copyright (c) 2025 MagicaSoft. +// https://magicasoft.jp +using System.Collections.Generic; using UnityEngine; namespace MagicaCloth2 @@ -83,8 +86,57 @@ namespace MagicaCloth2 /// public List cameraCullingRenderers = new List(); + /// + /// 距離カリングの状態と距離 + /// Distance Culling State and Distance. + /// [OK] Runtime changes. + /// [NG] Export/Import with Presets + /// + public CheckSliderSerializeData distanceCullingLength; + + /// + /// 距離カリングのフェード割合(0.0 ~ 1.0) + /// Distance culling fade rate (0.0 to 1.0). + /// [OK] Runtime changes. + /// [NG] Export/Import with Presets + /// + [Range(0.0f, 1.0f)] + public float distanceCullingFadeRatio; + + /// + /// 距離カリングの測定対象(None=メインカメラ) + /// Distance culling measurement target (None = main camera). + /// [OK] Runtime changes. + /// [NG] Export/Import with Presets + /// + public GameObject distanceCullingReferenceObject; + + //========================================================================================= + public struct CullingParams + { + public bool useDistanceCulling; + public float distanceCullingLength; + public float distanceCullingFadeRatio; + + public void Convert(CullingSettings cullingSettings) + { + useDistanceCulling = cullingSettings.distanceCullingLength.use; + distanceCullingLength = cullingSettings.distanceCullingLength.value; + distanceCullingFadeRatio = cullingSettings.distanceCullingFadeRatio; + } + } + + //========================================================================================= + public CullingSettings() + { + distanceCullingLength = new CheckSliderSerializeData(false, 30.0f); + distanceCullingFadeRatio = 0.2f; + } + public void DataValidate() { + distanceCullingLength.DataValidate(0.0f, Define.System.DistanceCullingMaxLength); + distanceCullingFadeRatio = Mathf.Clamp01(distanceCullingFadeRatio); } public CullingSettings Clone() @@ -94,6 +146,9 @@ namespace MagicaCloth2 cameraCullingMode = cameraCullingMode, cameraCullingMethod = cameraCullingMethod, cameraCullingRenderers = new List(cameraCullingRenderers), + distanceCullingLength = distanceCullingLength.Clone(), + distanceCullingFadeRatio = distanceCullingFadeRatio, + distanceCullingReferenceObject = distanceCullingReferenceObject, }; } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CullingSettings.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CullingSettings.cs.meta index c1315ab2..02459dd6 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CullingSettings.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CullingSettings.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/CullingSettings.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CurveSerializeData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CurveSerializeData.cs.meta index f1498d3c..4c29e957 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CurveSerializeData.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CurveSerializeData.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/CurveSerializeData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CustomSkinningSettings.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CustomSkinningSettings.cs index 59a73f0a..347d00d3 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CustomSkinningSettings.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CustomSkinningSettings.cs @@ -19,10 +19,8 @@ namespace MagicaCloth2 public bool enable = false; /// - /// bones for skinning. - /// Calculated from the parent-child structure line of bones registered here. - /// スキニング用ボーン - /// ここに登録されたボーンの親子構造ラインから算出される + /// Bones for custom skinning. + /// カスタムスキニング用ボーン /// [NG] Runtime changes. /// [NG] Export/Import with Presets /// diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CustomSkinningSettings.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CustomSkinningSettings.cs.meta index aaea93b8..76a99c94 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CustomSkinningSettings.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/CustomSkinningSettings.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/CustomSkinningSettings.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/GizmoSerializeData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/GizmoSerializeData.cs.meta index bb0f0b0a..a2e95439 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/GizmoSerializeData.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/GizmoSerializeData.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/GizmoSerializeData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaCloth.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaCloth.cs index 7b6d414b..0d3d0f02 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaCloth.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaCloth.cs @@ -42,7 +42,14 @@ namespace MagicaCloth2 /// General processing. /// private ClothProcess process = new ClothProcess(); - public ClothProcess Process { get { process.cloth = this; return process; } } + public ClothProcess Process + { + get + { + process.cloth = this; + return process; + } + } /// /// Cloth component transform. @@ -53,7 +60,14 @@ namespace MagicaCloth2 /// /// Synchronization target. /// - public MagicaCloth SyncCloth => SerializeData.IsBoneSpring() ? null : SerializeData.selfCollisionConstraint.GetSyncPartner(); + public MagicaCloth SyncPartnerCloth + { + get + { + var syncCloth = SerializeData.IsBoneSpring() ? null : SerializeData.selfCollisionConstraint.GetSyncPartner(); + return syncCloth == this ? null : syncCloth; + } + } /// /// Check if the cloth component is in a valid state. @@ -66,6 +80,14 @@ namespace MagicaCloth2 } //========================================================================================= + private void Reset() + { +#if UNITY_EDITOR + // Automatically generate pre-build ID + serializeData2.preBuildData.buildId = PreBuildSerializeData.GenerateBuildID(); +#endif + } + private void OnValidate() { Process.DataUpdate(); @@ -73,10 +95,11 @@ namespace MagicaCloth2 private void Awake() { - Process.Init(); - - // If Awake() is called, OnDestroy() will also be called, so remove it from monitoring. - MagicaManager.Team.RemoveMonitoringProcess(Process); + if (MagicaManager.initializationLocation == MagicaManager.InitializationLocation.Awake) + { + Process.Init(); + MagicaManager.Team.RemoveMonitoringProcess(Process); + } } private void OnEnable() @@ -91,6 +114,12 @@ namespace MagicaCloth2 void Start() { + if (MagicaManager.initializationLocation == MagicaManager.InitializationLocation.Start) + { + Process.Init(); + MagicaManager.Team.RemoveMonitoringProcess(Process); + } + Process.AutoBuild(); } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaCloth.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaCloth.cs.meta index 792d34c9..c0c1e0d3 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaCloth.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaCloth.cs.meta @@ -4,8 +4,15 @@ MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] - executionOrder: 0 + executionOrder: 5 icon: {fileID: 2800000, guid: cf7e3400035e987478c3a19e57b4cf75, type: 3} userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaCloth.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAPI.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAPI.cs index 8cd0acbe..a633ba32 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAPI.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAPI.cs @@ -29,8 +29,14 @@ namespace MagicaCloth2 /// Event after completion of cloth data construction. /// (true = Success, false = Failure) /// - public Action OnBuildComplete; + public Action OnBuildComplete; + /// + /// レンダラーメッシュ変更後イベント + /// Renderer mesh change event. + /// (true = Change to custom mesh, false = Change to original mesh) + /// + public Action OnRendererMeshChange; /// /// 初期化を実行します @@ -67,41 +73,74 @@ namespace MagicaCloth2 /// true=start build. false=build failed. public bool BuildAndRun() { - if (Application.isPlaying == false) - return false; + bool ret = false; + bool buildComplate = true; - DisableAutoBuild(); - - if (Process.IsState(ClothProcess.State_Build)) + try { - Develop.LogError($"Already built.:{this.name}"); - return false; - } + if (Application.isPlaying == false) + throw new MagicaClothProcessingException(); - // initialize generated data. - if (Process.GenerateInitialization() == false) - return false; + DisableAutoBuild(); - // setting by type. - switch (serializeData.clothType) - { - case ClothProcess.ClothType.BoneCloth: - case ClothProcess.ClothType.BoneSpring: - // BoneCloth用のセレクションデータの作成 - // ただしセレクションデータが存在し、かつユーザー定義されている場合は作成しない - var nowSelection = serializeData2.selectionData; - if (nowSelection == null || nowSelection.IsValid() == false || nowSelection.IsUserEdit() == false) + if (Process.IsState(ClothProcess.State_Build)) + { + Develop.LogError($"Already built.:{this.name}"); + throw new MagicaClothProcessingException(); + } + + // initialize generated data. + if (Process.GenerateInitialization() == false) + throw new MagicaClothProcessingException(); + + // check Pre-Build + bool usePreBuildData = serializeData2.preBuildData.UsePreBuild(); + + if (usePreBuildData == false) + { + // Runtime Build. + // setting by type. + switch (serializeData.clothType) { - if (Process.GenerateBoneClothSelection() == false) - return false; + case ClothProcess.ClothType.BoneCloth: + case ClothProcess.ClothType.BoneSpring: + // BoneCloth用のセレクションデータの作成 + // ただしセレクションデータが存在し、かつユーザー定義されている場合は作成しない + var nowSelection = serializeData2.selectionData; + if (nowSelection == null || nowSelection.IsValid() == false || nowSelection.IsUserEdit() == false) + { + if (Process.GenerateBoneClothSelection() == false) + throw new MagicaClothProcessingException(); + } + break; } - break; + + // build and run. + ret = Process.StartRuntimeBuild(); + if (ret) + buildComplate = false; // OnBuildCompleteはランタイム構築後に呼ばれる + } + else + { + // pre-build + ret = Process.PreBuildDataConstruction(); + } + } + catch (MagicaClothProcessingException) + { + } + catch (Exception exception) + { + Debug.LogException(exception); + } + finally + { + // ビルド完了イベント + if (buildComplate) + OnBuildComplete?.Invoke(this, ret); } - // build and run. - Process.StartBuild(); - - return true; + return ret; } /// @@ -123,7 +162,7 @@ namespace MagicaCloth2 var replaceDict = new Dictionary(); foreach (var t in useTransformSet) { - if (targetTransformDict.ContainsKey(t.name)) + if (t && targetTransformDict.ContainsKey(t.name)) { replaceDict.Add(t.GetInstanceID(), targetTransformDict[t.name]); } @@ -133,6 +172,18 @@ namespace MagicaCloth2 Process.ReplaceTransform(replaceDict); } + /// + /// コンポーネントが保持するすべてのトランスフォームを取得します。 + /// Gets all the transforms held by the component. + /// + /// + public HashSet GetUsedTransform() + { + var useTransformSet = new HashSet(); + Process.GetUsedTransform(useTransformSet); + return useTransformSet; + } + /// /// パラメータの変更を通知 @@ -197,8 +248,8 @@ namespace MagicaCloth2 // Reset tdata.flag.SetBits(TeamManager.Flag_Reset, true); tdata.flag.SetBits(TeamManager.Flag_TimeReset, true); - tdata.flag.SetBits(TeamManager.Flag_CullingKeep, false); - Process.SetState(ClothProcess.State_CullingKeep, false); + tdata.flag.SetBits(TeamManager.Flag_CameraCullingKeep, false); + Process.SetState(ClothProcess.State_CameraCullingKeep, false); Process.UpdateRendererUse(); } } @@ -251,5 +302,50 @@ namespace MagicaCloth2 Process.SetSkipWriting(sw); } } + + private RenderData GetRenderData(Renderer ren) + { + if (IsValid() == false || ren == null) + return null; + int handle = ren.GetInstanceID(); + return MagicaManager.Render.GetRendererData(handle); + } + + /// + /// MeshClothのオリジナルメッシュを取得します + /// Get the original mesh of MeshCloth. + /// + /// + /// null if not found + public Mesh GetOriginalMesh(Renderer ren) + { + return GetRenderData(ren)?.originalMesh ?? null; + } + + /// + /// MeshClothのカスタムメッシュを取得します + /// Get the custom mesh for MeshCloth. + /// + /// + /// null if not found + public Mesh GetCustomMesh(Renderer ren) + { + return GetRenderData(ren)?.customMesh ?? null; + } + + /// + /// MeshClothのSkinnedMeshRendererに設定されているカスタムボーンリストを取得します + /// カスタムボーンリストはオリジナルのBonesからスキニングに不要なTransformをnullに設定し、 + /// また最後にレンダラーのTransformが追加されるなど加工されているので注意してください。 + /// Gets the custom bone list set for the SkinnedMeshRenderer of MeshCloth. + /// Please note that the custom bone list has been processed by setting Transforms + /// that are not necessary for skinning to null from the original Bones, and adding the renderer Transform at the end. + /// + /// + /// null if not found + public List GetCustomBones(Renderer ren) + { + return GetRenderData(ren)?.transformList ?? null; + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAPI.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAPI.cs.meta index a97c3184..14cb7890 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAPI.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAPI.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAPI.cs + uploadId: 756593 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 00000000..88e3882d --- /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 00000000..2990ea55 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAnimationProperty.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: fea7c53425d793a44b3d484072c68bde +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/MagicaClothAnimationProperty.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/NormalAlignmentSettings.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/NormalAlignmentSettings.cs.meta index 5bf54d51..1e3b2589 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/NormalAlignmentSettings.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/NormalAlignmentSettings.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/NormalAlignmentSettings.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/SelectionData.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/SelectionData.cs index 11284afa..1f4e1b65 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/SelectionData.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/SelectionData.cs @@ -212,13 +212,7 @@ namespace MagicaCloth2 public void Fill(VertexAttribute attr) { -#if UNITY_2020 - int cnt = Count; - for (int i = 0; i < cnt; i++) - attributes[i] = attr; -#else Array.Fill(attributes, attr); -#endif } //========================================================================================= diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/SelectionData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/SelectionData.cs.meta index c14fff5f..85b63b3e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/SelectionData.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/SelectionData.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/SelectionData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/MagicaWindZone.cs b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/MagicaWindZone.cs index c39eb9cd..fd046db0 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/MagicaWindZone.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/MagicaWindZone.cs @@ -127,12 +127,12 @@ namespace MagicaCloth2 public void OnDisable() { - MagicaManager.Wind.SetEnable(WindId, false); + MagicaManager.Wind?.SetEnable(WindId, false); } public void OnDestroy() { - MagicaManager.Wind.RemoveWind(WindId); + MagicaManager.Wind?.RemoveWind(WindId); WindId = -1; } @@ -200,8 +200,9 @@ namespace MagicaCloth2 public void SetWindDirection(Vector3 dir, bool localSpace = false) { Vector3 lv = localSpace ? dir : transform.InverseTransformDirection(dir); - directionAngleX = Mathf.Atan2(lv.z, lv.x) * Mathf.Rad2Deg; - directionAngleY = Mathf.Atan2(lv.z, lv.y) * Mathf.Rad2Deg; + var angles = Quaternion.FromToRotation(Vector3.forward, lv).eulerAngles; + directionAngleX = angles.x > 180 ? angles.x - 360 : angles.x; + directionAngleY = angles.y > 180 ? angles.y - 360 : angles.y; } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/MagicaWindZone.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/MagicaWindZone.cs.meta index dd632e1e..af8a80d6 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/MagicaWindZone.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/MagicaWindZone.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/MagicaWindZone.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/WindParams.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/WindParams.cs.meta index f65d419e..2e5bea7c 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/WindParams.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/WindParams.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/WindParams.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/WindSettings.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/WindSettings.cs.meta index 35cbcae2..3223aa51 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/WindSettings.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/WindSettings.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Cloth/Wind/WindSettings.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Define/ResultDefine.cs b/Assets/External/MagicaCloth2/Scripts/Core/Define/ResultDefine.cs index fd8f1771..b81b1a95 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Define/ResultDefine.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Define/ResultDefine.cs @@ -34,6 +34,8 @@ namespace MagicaCloth2 RenderMesh_UnknownWarning = 10100, RenderMesh_VertexWeightIs5BonesOrMore, + Init_NonUniformScale = 10200, + /////////////////////////////////////////////////////////////////// // Error(20000 - ) /////////////////////////////////////////////////////////////////// @@ -42,11 +44,15 @@ namespace MagicaCloth2 // Validating serialized data SerializeData_InvalidData = 20050, SerializeData_Over31Renderers, + SerializeData_DuplicateRootBone, + SerializeData_DuplicateRenderer, // init Init_InvalidData = 20100, Init_InvalidPaintMap, Init_PaintMapNotReadable, + Init_ScaleIsZero, + Init_NegativeScale, // RenderSetup RenderSetup_Exception = 20200, @@ -76,6 +82,11 @@ namespace MagicaCloth2 CreateCloth_InvalidPaintMap, CreateCloth_PaintMapNotReadable, CreateCloth_PaintMapCountMismatch, + CreateCloth_CanNotStart, + CreateCloth_VertexAttributeListCountMismatch, + CreateCloth_VertexAttributeListIsNull, + CreateCloth_VertexAttributeListDataMismatch, + CreateCloth_InvalidVertexAttributeData, // Reduction Reduction_Exception = 20500, @@ -131,6 +142,41 @@ namespace MagicaCloth2 MagicaMesh_Invalid, MagicaMesh_InvalidRenderer, MagicaMesh_InvalidMeshFilter, + + // PreBuildData + PreBuildData_UnknownError = 22600, + PreBuildData_MagicaClothException, + PreBuildData_VirtualMeshDeserializationException, + PreBuildData_VerificationResult, + PreBuildData_VersionMismatch, + PreBuildData_InvalidClothData, + PreBuildData_Empty, + PreBuildData_InvalidScale, + + // PreBuild + PreBuild_UnknownError = 22700, + PreBuild_Exception, + PreBuild_InvalidPreBuildData, + PreBuild_InvalidRenderSetupData, + PreBuild_SetupDeserializationError, + + // PreBuild Deserialization + Deserialization_UnknownError = 22800, + Deserialization_Exception, + + // Init SerializeData + InitSerializeData_UnknownError = 22900, + InitSerializeData_InvalidHash, + InitSerializeData_InvalidVersion, + InitSerializeData_InvalidSetupData, + InitSerializeData_ClothTypeMismatch, + InitSerializeData_SetupCountMismatch, + InitSerializeData_CustomSkinningBoneCountMismatch, + InitSerializeData_MeshClothSetupValidationError, + InitSerializeData_BoneClothSetupValidationError, + InitSerializeData_BoneSpringSetupValidationError, + InitSerializeData_DeserializationError, + InitSerializeData_InvalidCloneMesh, } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Define/ResultDefine.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Define/ResultDefine.cs.meta index 59eeb12b..0ecbba0b 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Define/ResultDefine.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Define/ResultDefine.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Define/ResultDefine.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Define/SystemDefine.cs b/Assets/External/MagicaCloth2/Scripts/Core/Define/SystemDefine.cs index 7af5cb07..36f45a2d 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Define/SystemDefine.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Define/SystemDefine.cs @@ -17,6 +17,11 @@ namespace MagicaCloth2 /// public const string DefineSymbol = "MAGICACLOTH2"; + /// + /// 現在有効なPreBuildの最新バージョン + /// + public const int LatestPreBuildVersion = 2; + /// /// 計算を省略する最小の浮動小数点数 /// @@ -72,6 +77,16 @@ namespace MagicaCloth2 /// public const float SameSurfaceAngle = 80.0f; + /// + /// 未来予測時のルートからの距離制限倍率 + /// + public const float MaxDistanceRatioFutuerPrediction = 1.3f; + + /// + /// 分割ジョブを適用するプロキシメッシュメッシュの頂点数 + /// + public const int SplitProxyMeshVertexCount = 300; + /// /// [Reduction] /// 有効フラグ。常にtrueとする。 @@ -319,7 +334,19 @@ namespace MagicaCloth2 /// [Self Collision] /// 反復回数 /// - public const int SelfCollisionSolverIteration = 4; + public const int SelfCollisionSolverIteration = 4; // 4 + + /// + /// [Self Collision] + /// 無効グリッド座標 + /// + public const int SelfCollisionIgnoreGrid = 1000000; + + /// + /// [Self Collision] + /// 交差判定の分割数 + /// + public const int SelfCollisionIntersectDiv = 2; // 8 /// /// [Self Collision] @@ -351,12 +378,6 @@ namespace MagicaCloth2 /// public static readonly float SelfCollisionPointTriangleAngleCos = math.cos(math.radians(60.0f)); - /// - /// [Self Collision] - /// 交差判定の分割数 - /// - public const int SelfCollisionIntersectDiv = 8; - /// /// [Self Collision] /// Thicknessの最小値(m) @@ -398,6 +419,12 @@ namespace MagicaCloth2 /// BoneSpring利用時のfriction値 /// public const float BoneSpringCollisionFriction = 0.5f; + + /// + /// [Culling] + /// 距離カリングの最大距離 + /// + public const float DistanceCullingMaxLength = 100.0f; } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Define/SystemDefine.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Define/SystemDefine.cs.meta index a4b675b2..c066e7dd 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Define/SystemDefine.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Define/SystemDefine.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Define/SystemDefine.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Interface/ICount.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Interface/ICount.cs.meta index c402a984..a83f39e2 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Interface/ICount.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Interface/ICount.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Interface/ICount.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Interface/IDataValidate.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Interface/IDataValidate.cs.meta index 1f38f5f0..5de1145f 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Interface/IDataValidate.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Interface/IDataValidate.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Interface/IDataValidate.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Interface/ITransform.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Interface/ITransform.cs.meta index b801f1d6..3933622e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Interface/ITransform.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Interface/ITransform.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Interface/ITransform.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Interface/IValid.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Interface/IValid.cs.meta index cf8369c6..a6fc7785 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Interface/IValid.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Interface/IValid.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Interface/IValid.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/ClothManager.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/ClothManager.cs index 9e3d6098..26856b2f 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/ClothManager.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/ClothManager.cs @@ -15,7 +15,7 @@ namespace MagicaCloth2 public class ClothManager : IManager, IValid { // すべて - internal HashSet clothSet = new HashSet(); + internal HashSet clothSet = new HashSet(256); // BoneCloth,BoneSpring internal HashSet boneClothSet = new HashSet(); @@ -50,6 +50,7 @@ namespace MagicaCloth2 // 更新処理 MagicaManager.afterEarlyUpdateDelegate -= OnEarlyClothUpdate; + MagicaManager.firstPreUpdateDelegate -= OnFirstPreUpdate; MagicaManager.afterLateUpdateDelegate -= OnAfterLateUpdate; MagicaManager.beforeLateUpdateDelegate -= OnBeforeLateUpdate; } @@ -69,6 +70,7 @@ namespace MagicaCloth2 // 更新処理 MagicaManager.afterEarlyUpdateDelegate += OnEarlyClothUpdate; + MagicaManager.firstPreUpdateDelegate += OnFirstPreUpdate; MagicaManager.afterLateUpdateDelegate += OnAfterLateUpdate; MagicaManager.beforeLateUpdateDelegate += OnBeforeLateUpdate; @@ -118,6 +120,9 @@ namespace MagicaCloth2 break; } + // チームマネージャの作業バッファへ登録 + MagicaManager.Team.comp2TeamIdMap.Add(cprocess.cloth.GetInstanceID(), teamId); + return teamId; } @@ -140,11 +145,15 @@ namespace MagicaCloth2 /// void OnEarlyClothUpdate() { - if (MagicaManager.Team.ActiveTeamCount > 0) + //Debug.Log($"OnEarlyClothUpdate. F:{Time.frameCount}"); + if (MagicaManager.Team.TrueTeamCount > 0) // カリング判定があるのでDisableチームもまわす必要がある { - //Debug.Log($"TransformRestoreUpdate. F:{Time.frameCount}"); - // チームカリング更新 - MagicaManager.Team.TeamCullingUpdate(); + // カメラカリング更新 + if (MagicaManager.Team.ActiveTeamCount > 0) + { + // この更新は次のTransform復元の前に行う必要がある + MagicaManager.Team.CameraCullingPostProcess(); + } // BoneClothのTransform復元更新 ClearMasterJob(); @@ -153,6 +162,25 @@ namespace MagicaCloth2 } } + /// + /// PreUpdate開始時に実行される更新処理 + /// + void OnFirstPreUpdate() + { + //Debug.Log($"OnFirstPreUpdate. F:{Time.frameCount}"); + if (MagicaManager.Team.TrueTeamCount > 0) // カリング判定があるのでDisableチームもまわす必要がある + { + //Debug.Log($"existFixedTeam:{MagicaManager.Bone.existFixedTeam.Value}"); + // FixedUpdateが0回かつFixedTeamが存在する場合のみ + if (MagicaManager.Time.FixedUpdateCount == 0 && MagicaManager.Bone.existFixedTeam.Value) + { + ClearMasterJob(); + masterJob = MagicaManager.Bone.RestoreBaseTransform(masterJob); + CompleteMasterJob(); + } + } + } + void OnBeforeLateUpdate() { if (MagicaManager.Time.updateLocation == TimeManager.UpdateLocation.BeforeLateUpdate) @@ -166,7 +194,9 @@ namespace MagicaCloth2 } //========================================================================================= - static readonly ProfilerMarker startClothUpdateMainProfiler = new ProfilerMarker("StartClothUpdate.Main"); + static readonly ProfilerMarker startClothUpdateTimeProfiler = new ProfilerMarker("StartClothUpdate.Time"); + static readonly ProfilerMarker startClothUpdateTeamProfiler = new ProfilerMarker("StartClothUpdate.Team"); + static readonly ProfilerMarker startClothUpdatePrePareProfiler = new ProfilerMarker("StartClothUpdate.Prepare"); static readonly ProfilerMarker startClothUpdateScheduleProfiler = new ProfilerMarker("StartClothUpdate.Schedule"); /// @@ -177,13 +207,16 @@ namespace MagicaCloth2 if (MagicaManager.IsPlaying() == false) return; + // ■コンポーネント0なら終了 + var tm = MagicaManager.Team; + if (tm.TrueTeamCount == 0) + return; + //----------------------------------------------------------------- // シミュレーション開始イベント MagicaManager.OnPreSimulation?.Invoke(); //----------------------------------------------------------------- - var tm = MagicaManager.Team; - var vm = MagicaManager.VMesh; var sm = MagicaManager.Simulation; var bm = MagicaManager.Bone; var wm = MagicaManager.Wind; @@ -192,22 +225,21 @@ namespace MagicaCloth2 //Develop.DebugLog($"StartClothUpdate. F:{Time.frameCount}, dtime:{Time.deltaTime}, stime:{Time.smoothDeltaTime}"); //----------------------------------------------------------------- - startClothUpdateMainProfiler.Begin(); // ■時間マネージャ更新 + startClothUpdateTimeProfiler.Begin(); MagicaManager.Time.FrameUpdate(); + startClothUpdateTimeProfiler.End(); // ■常に実行するチーム更新 + startClothUpdateTeamProfiler.Begin(); tm.AlwaysTeamUpdate(); + startClothUpdateTeamProfiler.End(); // ■ここで実行チーム数が0ならば終了 if (tm.ActiveTeamCount == 0) - { - startClothUpdateMainProfiler.End(); return; - } - int maxUpdateCount = tm.maxUpdateCount.Value; - //Debug.Log($"maxUpdateCount:{maxUpdateCount}"); + startClothUpdatePrePareProfiler.Begin(); // ■常に実行する風ゾーン更新 wm.AlwaysWindUpdate(); @@ -215,106 +247,32 @@ namespace MagicaCloth2 // ■作業バッファ更新 sm.WorkBufferUpdate(); - startClothUpdateMainProfiler.End(); + startClothUpdatePrePareProfiler.End(); //----------------------------------------------------------------- -#if true startClothUpdateScheduleProfiler.Begin(); + // マスタージョブ初期化 ClearMasterJob(); // ■トランスフォーム情報の読み込み - masterJob = bm.ReadTransform(masterJob); + masterJob = bm.ReadTransformSchedule(masterJob); - // ■プロキシメッシュをスキニングし基本姿勢を求める - masterJob = vm.PreProxyMeshUpdate(masterJob); - - //----------------------------------------------------------------- - // チームのセンター姿勢の決定と慣性用の移動量計算 - masterJob = tm.CalcCenterAndInertiaAndWind(masterJob); - - // パーティクルリセットの適用 - masterJob = sm.PreSimulationUpdate(masterJob); - - // ■コライダーのローカル姿勢を求める - masterJob = MagicaManager.Collider.PreSimulationUpdate(masterJob); - - //----------------------------------------------------------------- - // ■クロスシミュレーション実行 - // ステップ実行 - for (int i = 0; i < maxUpdateCount; i++) - { - masterJob = sm.SimulationStepUpdate(maxUpdateCount, i, masterJob); - } - - //----------------------------------------------------------------- - // 表示位置の決定 - masterJob = sm.CalcDisplayPosition(masterJob); - - //----------------------------------------------------------------- - // ■クロスシミュレーション後の頂点姿勢計算 - // プロキシメッシュの頂点から法線接線を求め姿勢を確定させる - // ラインがある場合はベースラインごとに姿勢を整える - // BoneClothの場合は頂点姿勢を連動するトランスフォームデータにコピーする - masterJob = vm.PostProxyMeshUpdate(masterJob); - - // マッピングメッシュ - int mappingCount = tm.MappingCount; - if (mappingCount > 0) - { - // マッピングメッシュ頂点姿勢をプロキシメッシュからスキニングし求める - // マッピングメッシュのローカル空間に座標変換する - masterJob = vm.PostMappingMeshUpdate(masterJob); - - // レンダーデータへ反映する - foreach (var cprocess in meshClothSet) - { - if (cprocess == null || cprocess.IsValid() == false || cprocess.IsEnable == false) - continue; - - // カリングによる非表示中ならば書き込まない - if (cprocess.IsCullingInvisible()) - continue; - - int cnt = cprocess.renderMeshInfoList.Count; - for (int i = 0; i < cnt; i++) - { - var info = cprocess.renderMeshInfoList[i]; - var renderData = MagicaManager.Render.GetRendererData(info.renderHandle); - - // Position/Normal書き込み - masterJob = renderData.UpdatePositionNormal(info.mappingChunk, masterJob); - - // BoneWeight書き込み - if (renderData.ChangeCustomMesh) - { - masterJob = renderData.UpdateBoneWeight(info.mappingChunk, masterJob); - } - } - } - } - - //----------------------------------------------------------------- - // ■BoneClothのTransformへの書き込み - masterJob = bm.WriteTransform(masterJob); - - //----------------------------------------------------------------- - // ■コライダー更新後処理 - masterJob = MagicaManager.Collider.PostSimulationUpdate(masterJob); - - // ■チーム更新後処理 - masterJob = tm.PostTeamUpdate(masterJob); + // ■シミュレーションジョブ + masterJob = sm.ClothSimulationSchedule(masterJob); startClothUpdateScheduleProfiler.End(); + //----------------------------------------------------------------- + //JobHandle.ScheduleBatchedJobs(); //----------------------------------------------------------------- - // ジョブを即実行 - //JobHandle.ScheduleBatchedJobs(); + // ■ジョブ完了待ちの間に行う処理 + // カメラカリングの準備 + tm.CameraCullingPreProcess(); //----------------------------------------------------------------- // ■現在は即時実行のためここでジョブの完了待ちを行う CompleteMasterJob(); -#endif //----------------------------------------------------------------- // シミュレーション終了イベント diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/ClothManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/ClothManager.cs.meta index e53b7b07..61ce8db9 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/ClothManager.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/ClothManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/ClothManager.cs + uploadId: 756593 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 00000000..a4436f7c --- /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 00000000..44f74b06 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/PreBuildManager.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 800b8846d5572fe438974d4af951c076 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Cloth/PreBuildManager.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/IManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/IManager.cs.meta index a05e7923..e6ee31d0 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/IManager.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/IManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/IManager.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManager.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManager.cs index 03130bd7..a10685fc 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManager.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManager.cs @@ -40,6 +40,7 @@ namespace MagicaCloth2 public static SimulationManager Simulation => managers?[6] as SimulationManager; public static ColliderManager Collider => managers?[7] as ColliderManager; public static WindManager Wind => managers?[8] as WindManager; + public static PreBuildManager PreBuild => managers?[9] as PreBuildManager; //========================================================================================= // player loop delegate @@ -55,6 +56,11 @@ namespace MagicaCloth2 /// public static UpdateMethod afterFixedUpdateDelegate; + /// + /// PreUpdate()の開始直後 + /// + public static UpdateMethod firstPreUpdateDelegate; + /// /// Update()の後 /// @@ -91,8 +97,6 @@ namespace MagicaCloth2 //========================================================================================= static volatile bool isPlaying = false; - //static bool isValid = false; - //========================================================================================= /// /// Reload Domain 対策 @@ -122,12 +126,16 @@ namespace MagicaCloth2 managers.Add(new SimulationManager()); // [6] managers.Add(new ColliderManager()); // [7] managers.Add(new WindManager()); // [8] + managers.Add(new PreBuildManager()); // [9] foreach (var manager in managers) manager.Initialize(); // カスタム更新ループ登録 InitCustomGameLoop(); + // アプリ終了イベント + Application.quitting += OnAppQuitting; + isPlaying = true; //isValid = true; } @@ -249,6 +257,14 @@ namespace MagicaCloth2 } #endif + /// + /// アプリ終了イベント + /// + static void OnAppQuitting() + { + Develop.DebugLog($"OnAppQuitting!"); + Dispose(); + } /// /// マネージャの破棄 @@ -267,6 +283,10 @@ namespace MagicaCloth2 // clear static member. OnPreSimulation = null; OnPostSimulation = null; + + Application.quitting -= OnAppQuitting; + + isPlaying = false; } public static bool IsPlaying() @@ -321,7 +341,7 @@ namespace MagicaCloth2 type = typeof(MagicaManager), updateDelegate = () => afterEarlyUpdateDelegate?.Invoke() }; - AddPlayerLoop(afterEarlyUpdate, ref playerLoop, "EarlyUpdate", string.Empty, last: true); + AddPlayerLoop(afterEarlyUpdate, ref playerLoop, "EarlyUpdate", string.Empty, firstLast: 1); // after fixed update // FixedUpdate()の後 @@ -335,6 +355,17 @@ namespace MagicaCloth2 }; AddPlayerLoop(afterFixedUpdate, ref playerLoop, "FixedUpdate", "ScriptRunBehaviourFixedUpdate"); + // first pre update + PlayerLoopSystem firstPreUpdate = new PlayerLoopSystem() + { + type = typeof(MagicaManager), + updateDelegate = () => + { + firstPreUpdateDelegate?.Invoke(); + } + }; + AddPlayerLoop(firstPreUpdate, ref playerLoop, "PreUpdate", string.Empty, firstLast: -1); + // after update // Update()の後 PlayerLoopSystem afterUpdate = new PlayerLoopSystem() @@ -403,13 +434,18 @@ namespace MagicaCloth2 /// /// /// - static void AddPlayerLoop(PlayerLoopSystem method, ref PlayerLoopSystem playerLoop, string categoryName, string systemName, bool last = false, bool before = false) + static void AddPlayerLoop(PlayerLoopSystem method, ref PlayerLoopSystem playerLoop, string categoryName, string systemName, int firstLast = 0, bool before = false) { int sysIndex = Array.FindIndex(playerLoop.subSystemList, (s) => s.type.Name == categoryName); PlayerLoopSystem category = playerLoop.subSystemList[sysIndex]; var systemList = new List(category.subSystemList); - if (last) + if (firstLast < 0) + { + // 最初に追加 + systemList.Insert(0, method); + } + else if (firstLast > 0) { // 最後に追加 systemList.Add(method); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManager.cs.meta index 59faaacc..3a72fe73 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManager.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManager.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManagerAPI.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManagerAPI.cs index e5fffb44..514ace74 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManagerAPI.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManagerAPI.cs @@ -33,7 +33,6 @@ namespace MagicaCloth2 { if (IsPlaying()) { - //Team.globalTimeScale = Mathf.Clamp01(timeScale); Time.GlobalTimeScale = Mathf.Clamp01(timeScale); } } @@ -47,7 +46,6 @@ namespace MagicaCloth2 { if (IsPlaying()) { - //return Team.globalTimeScale; return Time.GlobalTimeScale; } else @@ -153,5 +151,74 @@ namespace MagicaCloth2 return TimeManager.UpdateLocation.AfterLateUpdate; } } + + /// + /// 未使用のデータをすべて解放します + /// Free all unused data. + /// - Unused PreBuild data + /// + public static void UnloadUnusedData() + { + if (IsPlaying()) + { + PreBuild.UnloadUnusedData(); + } + } + + /// + /// MonoBehaviourでのMagicaClothの初期化場所 + /// MagicaCloth initialization location in MonoBehaviour. + /// + public enum InitializationLocation + { + /// + /// Initialize with MonoBehaviour.Start(). + /// (Default) + /// + Start = 0, + + /// + /// Initialize with MonoBehaviour.Awake(). + /// + Awake = 1, + } + internal static InitializationLocation initializationLocation = InitializationLocation.Start; + + /// + /// MonoBehaviourでのMagicaClothの初期化場所を設定する + /// Setting MagicaCloth initialization location in MonoBehaviour. + /// + /// + public static void SetInitializationLocation(InitializationLocation initLocation) + { + initializationLocation = initLocation; + } + + /// + /// 分割ジョブを適用するプロキシメッシュの頂点数を設定する + /// Sets the number of vertices for the proxy mesh to which the split job will be applied. + /// + /// + public static void SetSplitProxyMeshVertexCount(int vertexCount) + { + if (IsPlaying()) + Simulation.splitProxyMeshVertexCount = vertexCount; + } + + /// + /// 分割ジョブを適用するプロキシメッシュの頂点数を取得する + /// Gets the vertex count of the proxy mesh to which the split job is applied. + /// + /// + public static int GetSplitProxyMeshVertexCount() + { + if (IsPlaying()) + return Simulation.splitProxyMeshVertexCount; + else + { + Develop.LogError("MagicaManager is not starting!"); + return 0; + } + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManagerAPI.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManagerAPI.cs.meta index 5cca676a..196e722b 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManagerAPI.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManagerAPI.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaManagerAPI.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaSettings.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaSettings.cs index b99b8060..872f5b40 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaSettings.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaSettings.cs @@ -15,8 +15,8 @@ namespace MagicaCloth2 public enum RefreshMode { /// - /// コンポーネント生成時に1度だけ送信する - /// Send only once when the component is created. + /// コンポーネントのAwake()で1度だけ送信する + /// Send once at the component's Awake() /// OnAwake = 0, @@ -25,6 +25,18 @@ namespace MagicaCloth2 /// Send content every frame. /// EveryFrame = 1, + + /// + /// コンポーネントのStart()で一度だけ送信する + /// Send once at the component's Start(). + /// + OnStart = 2, + + /// + /// コンポーネントは何もしません。送信には手動でRefresh()を呼ぶ必要があります + /// The component does nothing. You must manually call Refresh() to submit. + /// + Manual = 3, } /// @@ -64,6 +76,12 @@ namespace MagicaCloth2 [Range(Define.System.MaxSimulationCountPerFrame_Low, Define.System.MaxSimulationCountPerFrame_Hi)] public int maxSimulationCountPerFrame = Define.System.DefaultMaxSimulationCountPerFrame; + /// + /// MonoBehaviourでのMagicaClothの初期化場所。 + /// MagicaCloth initialization location in MonoBehaviour. + /// + public MagicaManager.InitializationLocation initializationLocation = MagicaManager.InitializationLocation.Start; + /// /// シミュレーションの更新場所 /// BeforeLateUpdate : LateUpdate()の前に実行します。これはUnity 2D Animationで利用する場合に必要です。 @@ -75,6 +93,27 @@ namespace MagicaCloth2 /// public TimeManager.UpdateLocation updateLocation = TimeManager.UpdateLocation.AfterLateUpdate; + /// + /// PlayerLoopの監視 + /// MagicaClothのシステムはUnityのPlayerLoopに登録することで動作します + /// この登録が他の外部アセットにより上書きされてしまうと、MagicaClothのシステムが停止してしまいます + /// このフラグを有効にすると、PlayerLoopを監視して、上書きされていた場合は再度システムを登録するようになります + /// + /// PlayerLoop monitoring. + /// The MagicaCloth system works by registering it in Unity's PlayerLoop. + /// If this registration is overwritten by other external assets, the MagicaCloth system will stop working. + /// When this flag is enabled, the PlayerLoop will be monitored, and the system will be registered again if it has been overwritten. + /// + public bool monitorPlayerLoop = false; + + /// + /// ジョブ分割を適用するプロキシメッシュの頂点数 + /// + /// The number of proxy mesh vertices to apply job splitting to. + /// + [Min(0)] + public int splitProxyMeshVertexCount = Define.System.SplitProxyMeshVertexCount; + //========================================================================================= public void Awake() { @@ -82,6 +121,12 @@ namespace MagicaCloth2 Refresh(); } + public void Start() + { + if (refreshMode == RefreshMode.OnStart) + Refresh(); + } + public void Update() { if (refreshMode == RefreshMode.EveryFrame) @@ -108,7 +153,12 @@ namespace MagicaCloth2 MagicaManager.SetSimulationFrequency(simulationFrequency); MagicaManager.SetMaxSimulationCountPerFrame(maxSimulationCountPerFrame); + MagicaManager.SetInitializationLocation(initializationLocation); MagicaManager.SetUpdateLocation(updateLocation); + MagicaManager.SetSplitProxyMeshVertexCount(splitProxyMeshVertexCount); + + if (monitorPlayerLoop) + MagicaManager.InitCustomGameLoop(); } else { diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaSettings.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaSettings.cs.meta index 6c1894e7..09691237 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaSettings.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaSettings.cs.meta @@ -4,8 +4,15 @@ MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] - executionOrder: 0 + executionOrder: -50 icon: {fileID: 2800000, guid: 4b0d1adb21ff82e4e8e9ea02f486a85f, type: 3} userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/MagicaSettings.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderData.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderData.cs index d5dd0501..31f0de2e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderData.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderData.cs @@ -5,10 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; -using Unity.Burst; using Unity.Collections; -using Unity.Jobs; -using Unity.Mathematics; using UnityEngine; namespace MagicaCloth2 @@ -37,6 +34,7 @@ namespace MagicaCloth2 //========================================================================================= // セットアップデータ internal RenderSetupData setupData; + internal RenderSetupData.UniqueSerializationData preBuildUniqueSerializeData; internal string Name => setupData?.name ?? "(empty)"; @@ -44,40 +42,27 @@ namespace MagicaCloth2 internal bool HasBoneWeight => setupData?.hasBoneWeight ?? false; //========================================================================================= - // カスタムメッシュ情報 - Mesh customMesh; - NativeArray localPositions; - NativeArray localNormals; - NativeArray boneWeights; - BoneWeight centerBoneWeight; + // オリジナル情報 + internal Mesh originalMesh { get; private set; } + private Renderer renderer; + private SkinnedMeshRenderer skinnedMeshRendere; + private MeshFilter meshFilter; + internal List transformList { get; private set; } + internal Mesh customMesh { get; private set; } - /// - /// カスタムメッシュの使用フラグ - /// - public bool UseCustomMesh { get; private set; } - - /// - /// カスタムメッシュの変更フラグ - /// - public bool ChangeCustomMesh { get; private set; } - - public bool ChangePositionNormal { get; private set; } - public bool ChangeBoneWeight { get; private set; } + // RenderDataWorkバッファへのインデックス(RenderManagerが管理) + internal int renderDataWorkIndex { get; private set; } = -1; //========================================================================================= public void Dispose() { // オリジナルメッシュに戻す - SwapOriginalMesh(); + SwapOriginalMesh(null); setupData?.Dispose(); + preBuildUniqueSerializeData = null; - if (localPositions.IsCreated) - localPositions.Dispose(); - if (localNormals.IsCreated) - localNormals.Dispose(); - if (boneWeights.IsCreated) - boneWeights.Dispose(); + MagicaManager.Render.RemoveRenderDataWork(renderDataWorkIndex); if (customMesh) GameObject.Destroy(customMesh); @@ -98,17 +83,42 @@ namespace MagicaCloth2 /// この処理はスレッド化できないので少し負荷がかかるが即時実行する /// /// - internal void Initialize(Renderer ren) + internal void Initialize( + Renderer ren, + RenderSetupData referenceSetupData, + RenderSetupData.UniqueSerializationData referencePreBuildUniqueSetupData, + RenderSetupSerializeData referenceInitSetupData + ) { Debug.Assert(ren); // セットアップデータ作成 - setupData = new RenderSetupData(ren); + // PreBuildでは外部から受け渡される + if (referenceSetupData != null && referencePreBuildUniqueSetupData != null) + { + setupData = referenceSetupData; + preBuildUniqueSerializeData = referencePreBuildUniqueSetupData; - // センタートランスフォーム用ボーンウエイト - centerBoneWeight = new BoneWeight(); - centerBoneWeight.boneIndex0 = setupData.renderTransformIndex; - centerBoneWeight.weight0 = 1.0f; + originalMesh = preBuildUniqueSerializeData.originalMesh; + renderer = preBuildUniqueSerializeData.renderer; + skinnedMeshRendere = preBuildUniqueSerializeData.skinRenderer; + meshFilter = preBuildUniqueSerializeData.meshFilter; + transformList = preBuildUniqueSerializeData.transformList; + } + else + { + setupData = new RenderSetupData(referenceInitSetupData, ren); + preBuildUniqueSerializeData = null; + + originalMesh = setupData.originalMesh; + renderer = setupData.renderer; + skinnedMeshRendere = setupData.skinRenderer; + meshFilter = setupData.meshFilter; + transformList = setupData.transformList; + } + + // レンダーデータワークを確保 + renderDataWorkIndex = MagicaManager.Render.AddRenderDataWork(this); } internal ResultCode Result => setupData?.result ?? ResultCode.None; @@ -127,41 +137,39 @@ namespace MagicaCloth2 } //========================================================================================= - void SwapCustomMesh() + void SwapCustomMesh(ClothProcess process) { Debug.Assert(setupData != null); if (setupData.IsFaild()) return; - if (setupData.originalMesh == null) + if (originalMesh == null) + return; + if (MagicaManager.Render.IsSetRenderDataWorkFlag(renderDataWorkIndex, RenderManager.RenderDataFlag_UseCustomMesh)) return; // カスタムメッシュの作成 if (customMesh == null) { - Debug.Assert(setupData.originalMesh); - + //Debug.Assert(setupData.originalMesh); // クローン作成 - customMesh = GameObject.Instantiate(setupData.originalMesh); + customMesh = GameObject.Instantiate(originalMesh); customMesh.MarkDynamic(); - // 作業配列 - int vertexCount = setupData.vertexCount; - localPositions = new NativeArray(vertexCount, Allocator.Persistent); - localNormals = new NativeArray(vertexCount, Allocator.Persistent); - if (HasBoneWeight) - boneWeights = new NativeArray(vertexCount, Allocator.Persistent); - // bind pose if (HasBoneWeight) { - int transformCount = setupData.TransformCount; + int transformCount = preBuildUniqueSerializeData != null ? preBuildUniqueSerializeData.transformList.Count : setupData.TransformCount; var bindPoseList = new List(transformCount); bindPoseList.AddRange(setupData.bindPoseList); // rootBone/skinning bones while (bindPoseList.Count < transformCount) bindPoseList.Add(Matrix4x4.identity); customMesh.bindposes = bindPoseList.ToArray(); + + // スキニング用ボーンを書き換える + // このリストにはオリジナルのスキニングボーン+レンダラーのトランスフォームが含まれている + skinnedMeshRendere.bones = transformList.ToArray(); } } @@ -170,45 +178,76 @@ namespace MagicaCloth2 // カスタムメッシュに表示切り替え SetMesh(customMesh); + MagicaManager.Render.SetBitsRenderDataWorkFlag(renderDataWorkIndex, RenderManager.RenderDataFlag_UseCustomMesh, true); - // スキニング用ボーンを書き換える - if (HasBoneWeight) - { - // このリストにはオリジナルのスキニングボーン+レンダラーのトランスフォームが含まれている - setupData.skinRenderer.bones = setupData.transformList.ToArray(); - } - - UseCustomMesh = true; + // Event + if (process != null) + process.cloth?.OnRendererMeshChange?.Invoke(process.cloth, renderer, true); } void ResetCustomMeshWorkData() { + var rm = MagicaManager.Render; + ref var wdata = ref rm.GetRenderDataWorkRef(renderDataWorkIndex); + int vcnt = setupData.vertexCount; + // オリジナルデータをコピーする - var meshData = setupData.meshDataArray[0]; - meshData.GetVertices(localPositions); - meshData.GetNormals(localNormals); - if (HasBoneWeight) + if (setupData.HasMeshDataArray) { + var meshData = setupData.meshDataArray[0]; + using var localPositions = new NativeArray(vcnt, Allocator.TempJob); + using var localNormals = new NativeArray(vcnt, Allocator.TempJob); + meshData.GetVertices(localPositions); + meshData.GetNormals(localNormals); + rm.renderMeshPositions.CopyFrom(localPositions, wdata.renderMeshPositionAndNormalChunk.startIndex, vcnt); + rm.renderMeshNormals.CopyFrom(localNormals, wdata.renderMeshPositionAndNormalChunk.startIndex, vcnt); + if (wdata.HasMeshTangent) + { + using var localTangents = new NativeArray(vcnt, Allocator.TempJob); + meshData.GetTangents(localTangents); + rm.renderMeshTangents.CopyFrom(localTangents, wdata.renderMeshTangentChunk.startIndex, vcnt); + wdata.flag.SetBits(RenderManager.RenderDataFlag_HasTangent, true); // 最終的な接線あり + } + } + else + { + rm.renderMeshPositions.CopyFrom(setupData.localPositions, wdata.renderMeshPositionAndNormalChunk.startIndex, vcnt); + rm.renderMeshNormals.CopyFrom(setupData.localNormals, wdata.renderMeshPositionAndNormalChunk.startIndex, vcnt); + if (wdata.HasMeshTangent && setupData.HasTangent) + { + rm.renderMeshTangents.CopyFrom(setupData.localTangents, wdata.renderMeshTangentChunk.startIndex, vcnt); + wdata.flag.SetBits(RenderManager.RenderDataFlag_HasTangent, true); // 最終的な接線あり + } + } + if (HasBoneWeight && wdata.HasBoneWeight) + { + using var boneWeights = new NativeArray(vcnt, Allocator.TempJob); setupData.GetBoneWeightsRun(boneWeights); + rm.renderMeshBoneWeights.CopyFrom(boneWeights, wdata.renderMeshBoneWeightChunk.startIndex, vcnt); } } /// /// オリジナルメッシュに戻す /// - void SwapOriginalMesh() + void SwapOriginalMesh(ClothProcess process) { - if (UseCustomMesh && setupData != null) - { - SetMesh(setupData.originalMesh); + var rm = MagicaManager.Render; - if (setupData.skinRenderer != null) + if (rm.IsSetRenderDataWorkFlag(renderDataWorkIndex, RenderManager.RenderDataFlag_UseCustomMesh) && setupData != null) + { + SetMesh(originalMesh); + + if (skinnedMeshRendere != null) { - setupData.skinRenderer.bones = setupData.transformList.ToArray(); + skinnedMeshRendere.bones = transformList.ToArray(); } } + rm.SetBitsRenderDataWorkFlag(renderDataWorkIndex, RenderManager.RenderDataFlag_UseCustomMesh, false); - UseCustomMesh = false; + // Event + if (process != null) + process.cloth?.OnRendererMeshChange?.Invoke(process.cloth, renderer, false); } /// @@ -222,13 +261,13 @@ namespace MagicaCloth2 if (setupData != null) { - if (setupData.meshFilter != null) + if (meshFilter != null) { - setupData.meshFilter.mesh = mesh; + meshFilter.mesh = mesh; } - else if (setupData.skinRenderer != null) + else if (skinnedMeshRendere != null) { - setupData.skinRenderer.sharedMesh = mesh; + skinnedMeshRendere.sharedMesh = mesh; } } } @@ -251,7 +290,7 @@ namespace MagicaCloth2 /// public void EndUse(ClothProcess cprocess) { - Debug.Assert(useProcessSet.Count > 0); + //Debug.Assert(useProcessSet.Count > 0); UpdateUse(cprocess, -1); } @@ -263,36 +302,62 @@ namespace MagicaCloth2 } else if (add < 0) { - Debug.Assert(useProcessSet.Count > 0); - useProcessSet.Remove(cprocess); + //Debug.Assert(useProcessSet.Count > 0); + if (useProcessSet.Contains(cprocess)) + useProcessSet.Remove(cprocess); + else + return; } // Invisible状態 - bool invisible = useProcessSet.Any(x => x.IsCullingInvisible() && x.IsCullingKeep() == false); + bool invisible = useProcessSet.Any(x => (x.IsCameraCullingInvisible() && x.IsCameraCullingKeep() == false) || x.IsDistanceCullingInvisible()); // 状態変更 + bool modifyBoneWeight = false; if (invisible || useProcessSet.Count == 0) { // 利用停止 // オリジナルメッシュに切り替え - SwapOriginalMesh(); - ChangeCustomMesh = true; + SwapOriginalMesh(cprocess); } - else if (useProcessSet.Count == 1) + else if (add == 0 && useProcessSet.Count > 0) + { + // カリング復帰 + // カスタムメッシュに切り替え、および作業バッファ作成 + // すでにカスタムメッシュが存在する場合は作業バッファのみ再初期化する + SwapCustomMesh(cprocess); + modifyBoneWeight = true; + } + else if (add > 0 && useProcessSet.Count == 1) { // 利用開始 // カスタムメッシュに切り替え、および作業バッファ作成 - // すでにカスタムメッシュが存在する場合は作業バッファのみ最初期化する - SwapCustomMesh(); - ChangeCustomMesh = true; + // すでにカスタムメッシュが存在する場合は作業バッファのみ再初期化する + SwapCustomMesh(cprocess); + modifyBoneWeight = true; } else if (add != 0) { // 複数から利用されている状態で1つが停止した。 // バッファを最初期化する ResetCustomMeshWorkData(); - ChangeCustomMesh = true; + modifyBoneWeight = true; } + + // BoneWeight変更を連動するマッピングに指示する + if (modifyBoneWeight) + { + ref var wdata = ref MagicaManager.Render.GetRenderDataWorkRef(renderDataWorkIndex); + int mcnt = wdata.mappingDataIndexList.Length; + for (int i = 0; i < mcnt; i++) + { + int mindex = wdata.mappingDataIndexList[i]; + ref var mdata = ref MagicaManager.Team.GetMappingDataRef(mindex); + mdata.flag.SetBits(TeamManager.MappingDataFlag_ModifyBoneWeight, true); + } + } + + //Debug.Log($"add:{add}, invisible:{invisible}, useCount:{useProcessSet.Count}, ModifyBoneWeight = {flag.IsSet(Flag_ModifyBoneWeight)}"); } //========================================================================================= @@ -312,177 +377,39 @@ namespace MagicaCloth2 //========================================================================================= internal void WriteMesh() { - if (UseCustomMesh == false || useProcessSet.Count == 0) + var rm = MagicaManager.Render; + ref var wdata = ref rm.GetRenderDataWorkRef(renderDataWorkIndex); + + if (wdata.UseCustomMesh == false || useProcessSet.Count == 0) return; // 書き込み停止中ならスキップ if (isSkipWriting) return; + //Debug.Log($"WriteMesh [{Name}] ChangePositionNormal:{flag.IsSet(Flag_ChangePositionNormal)}, ChangeBoneWeight:{flag.IsSet(Flag_ChangeBoneWeight)}"); + // メッシュに反映 - if (ChangePositionNormal) + if (wdata.flag.IsSet(RenderManager.RenderDataFlag_WritePositionNormal)) { - customMesh.SetVertices(localPositions); - customMesh.SetNormals(localNormals); + customMesh.SetVertices(rm.renderMeshPositions.GetNativeArray(), wdata.renderMeshPositionAndNormalChunk.startIndex, wdata.renderMeshPositionAndNormalChunk.dataLength); + customMesh.SetNormals(rm.renderMeshNormals.GetNativeArray(), wdata.renderMeshPositionAndNormalChunk.startIndex, wdata.renderMeshPositionAndNormalChunk.dataLength); + wdata.flag.SetBits(RenderManager.RenderDataFlag_WritePositionNormal, false); + //Debug.Log($"[{customMesh.name}] Write Position+Normal"); } - if (ChangeBoneWeight && HasBoneWeight) + if (wdata.flag.IsSet(RenderManager.RenderDataFlag_WriteTangent)) { - customMesh.boneWeights = boneWeights.ToArray(); + customMesh.SetTangents(rm.renderMeshTangents.GetNativeArray(), wdata.renderMeshTangentChunk.startIndex, wdata.renderMeshTangentChunk.dataLength); + wdata.flag.SetBits(RenderManager.RenderDataFlag_WriteTangent, false); + //Debug.Log($"[{customMesh.name}] Write Tangent"); } - - // 完了 - ChangeCustomMesh = false; - ChangePositionNormal = false; - ChangeBoneWeight = false; - } - - //========================================================================================= - /// - /// メッシュの位置法線を更新 - /// - /// - /// - /// - internal JobHandle UpdatePositionNormal(DataChunk mappingChunk, JobHandle jobHandle = default) - { - if (UseCustomMesh == false) - return jobHandle; - - var vm = MagicaManager.VMesh; - - // 座標・法線の差分書き換え - var job = new UpdatePositionNormalJob2() + if (wdata.flag.IsSet(RenderManager.RenderDataFlag_WriteBoneWeight)) { - startIndex = mappingChunk.startIndex, - - meshLocalPositions = localPositions.Reinterpret(), - meshLocalNormals = localNormals.Reinterpret(), - - mappingReferenceIndices = vm.mappingReferenceIndices.GetNativeArray(), - mappingAttributes = vm.mappingAttributes.GetNativeArray(), - mappingPositions = vm.mappingPositions.GetNativeArray(), - mappingNormals = vm.mappingNormals.GetNativeArray(), - }; - jobHandle = job.Schedule(mappingChunk.dataLength, 32, jobHandle); - - ChangePositionNormal = true; - - return jobHandle; - } - - [BurstCompile] - struct UpdatePositionNormalJob2 : IJobParallelFor - { - public int startIndex; - - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray meshLocalPositions; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray meshLocalNormals; - - // mapping mesh - [Unity.Collections.ReadOnly] - public NativeArray mappingReferenceIndices; - [Unity.Collections.ReadOnly] - public NativeArray mappingAttributes; - [Unity.Collections.ReadOnly] - public NativeArray mappingPositions; - [Unity.Collections.ReadOnly] - public NativeArray mappingNormals; - - public void Execute(int index) - { - int vindex = index + startIndex; - - // 無効頂点なら書き込まない - var attr = mappingAttributes[vindex]; - if (attr.IsInvalid()) - return; - - // 固定も書き込まない(todo:一旦こうする) - if (attr.IsFixed()) - return; - - // 書き込む頂点インデックス - int windex = mappingReferenceIndices[vindex]; - - // 座標書き込み - meshLocalPositions[windex] = mappingPositions[vindex]; - - // 法線書き込み - meshLocalNormals[windex] = mappingNormals[vindex]; - } - } - - /// - /// メッシュのボーンウエイト書き込み - /// - /// - /// - /// - internal JobHandle UpdateBoneWeight(DataChunk mappingChunk, JobHandle jobHandle = default) - { - if (UseCustomMesh == false) - return jobHandle; - - // ボーンウエイトの差分書き換え - if (HasBoneWeight) - { - var vm = MagicaManager.VMesh; - - var job = new UpdateBoneWeightJob2() - { - startIndex = mappingChunk.startIndex, - centerBoneWeight = centerBoneWeight, - meshBoneWeights = boneWeights, - - mappingReferenceIndices = vm.mappingReferenceIndices.GetNativeArray(), - mappingAttributes = vm.mappingAttributes.GetNativeArray(), - }; - jobHandle = job.Schedule(mappingChunk.dataLength, 32, jobHandle); - - ChangeBoneWeight = true; - } - - return jobHandle; - } - - [BurstCompile] - struct UpdateBoneWeightJob2 : IJobParallelFor - { - public int startIndex; - public BoneWeight centerBoneWeight; - - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray meshBoneWeights; - - // mapping mesh - [Unity.Collections.ReadOnly] - public NativeArray mappingReferenceIndices; - [Unity.Collections.ReadOnly] - public NativeArray mappingAttributes; - - public void Execute(int index) - { - int vindex = index + startIndex; - - // 無効頂点なら書き込まない - var attr = mappingAttributes[vindex]; - if (attr.IsInvalid()) - return; - - // 固定も書き込まない(todo:一旦こうする) - if (attr.IsFixed()) - return; - - // 書き込む頂点インデックス - int windex = mappingReferenceIndices[vindex]; - - // 使用頂点のウエイトはcenterTransform100%で書き込む - meshBoneWeights[windex] = centerBoneWeight; + // BoneWeightはNativeArrayの区間指定ができない + var boneWeightsSlice = new NativeSlice(rm.renderMeshBoneWeights.GetNativeArray(), wdata.renderMeshBoneWeightChunk.startIndex, wdata.renderMeshBoneWeightChunk.dataLength); + customMesh.boneWeights = boneWeightsSlice.ToArray(); + wdata.flag.SetBits(RenderManager.RenderDataFlag_WriteBoneWeight, false); + //Debug.Log($"[{customMesh.name}] Write BoneWeight"); } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderData.cs.meta index ba4428ef..14eff1e6 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderData.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderData.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderManager.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderManager.cs index 0bfc9373..8572bffc 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderManager.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderManager.cs @@ -3,6 +3,9 @@ // https://magicasoft.jp using System.Collections.Generic; using System.Text; +using Unity.Collections; +using Unity.Mathematics; +using Unity.Profiling; using UnityEngine; namespace MagicaCloth2 @@ -17,6 +20,78 @@ namespace MagicaCloth2 /// Dictionary renderDataDict = new Dictionary(); + //========================================================================================= + // ■RenderData + //========================================================================================= + /// + /// RenderDataの状態フラグ(32bit) + /// + public const int RenderDataFlag_UseCustomMesh = 0; // カスタムメッシュの利用 + public const int RenderDataFlag_WritePositionNormal = 1; // 座標および法線の書き込み + public const int RenderDataFlag_WriteBoneWeight = 2; // ボーンウエイトの書き込み + //public const int RenderDataFlag_ModifyBoneWeight = 3; // ボーンウエイトの変更 + public const int RenderDataFlag_HasMeshTangent = 4; // オリジナルメッシュが接線を持っているかどうか + public const int RenderDataFlag_HasTangent = 5; // 最終的に接線情報を持っているかどうか + public const int RenderDataFlag_WriteTangent = 6; // 接線の書き込み + public const int RenderDataFlag_HasSkinnedMesh = 7; + public const int RenderDataFlag_HasBoneWeight = 8; + + public struct RenderDataWork : IValid + { + /// + /// RenderData状態フラグ + /// + public BitField32 flag; + + /// + /// バッファへの格納先情報 + /// + public DataChunk renderMeshPositionAndNormalChunk; + public DataChunk renderMeshTangentChunk; + public DataChunk renderMeshBoneWeightChunk; + + /// + /// 制御頂点に設定するボーンウエイト + /// + public BoneWeight centerBoneWeight; + + /// + /// 紐づけられているマッピングメッシュデータへのインデックスリスト + /// + public FixedList32Bytes mappingDataIndexList; + + public bool IsValid() + { + return renderMeshPositionAndNormalChunk.IsValid; + } + + public bool UseCustomMesh => flag.IsSet(RenderDataFlag_UseCustomMesh); + public bool HasMeshTangent => flag.IsSet(RenderDataFlag_HasMeshTangent); + public bool HasTangent => flag.IsSet(RenderDataFlag_HasTangent); + public bool HasBoneWeight => flag.IsSet(RenderDataFlag_HasBoneWeight); + + public void AddMappingIndex(int mindex) + { + mappingDataIndexList.Add((short)mindex); + } + + public void RemoveMappingIndex(int mindex) + { + mappingDataIndexList.MC2RemoveItemAtSwapBack((short)mindex); + } + } + public ExNativeArray renderDataWorkArray; + + public int RenderDataWorkCount => renderDataWorkArray?.Count ?? 0; + + //========================================================================================= + // ■RenderMesh + //========================================================================================= + public ExNativeArray renderMeshPositions; + public ExNativeArray renderMeshNormals; + public ExNativeArray renderMeshTangents; + public ExNativeArray renderMeshBoneWeights; + bool isValid = false; //========================================================================================= @@ -24,6 +99,15 @@ namespace MagicaCloth2 { Dispose(); + // 作業バッファ + const int capacity = 0; + const bool create = true; + renderDataWorkArray = new ExNativeArray(capacity, create); + renderMeshPositions = new ExNativeArray(capacity, create); + renderMeshNormals = new ExNativeArray(capacity, create); + renderMeshTangents = new ExNativeArray(capacity, create); + renderMeshBoneWeights = new ExNativeArray(capacity, create); + // 更新処理 MagicaManager.afterDelayedDelegate += PreRenderingUpdate; @@ -48,6 +132,18 @@ namespace MagicaCloth2 } renderDataDict.Clear(); + // 作業バッファ + renderDataWorkArray?.Dispose(); + renderMeshPositions?.Dispose(); + renderMeshNormals?.Dispose(); + renderMeshTangents?.Dispose(); + renderMeshBoneWeights?.Dispose(); + renderDataWorkArray = null; + renderMeshPositions = null; + renderMeshNormals = null; + renderMeshBoneWeights = null; + renderMeshTangents = null; + // 更新処理 MagicaManager.afterDelayedDelegate -= PreRenderingUpdate; } @@ -63,7 +159,12 @@ namespace MagicaCloth2 /// /// /// - public int AddRenderer(Renderer ren) + public int AddRenderer( + Renderer ren, + RenderSetupData referenceSetupData, + RenderSetupData.UniqueSerializationData referenceUniqueSetupData, + RenderSetupSerializeData referenceInitSetupData + ) { if (isValid == false) return 0; @@ -78,7 +179,7 @@ namespace MagicaCloth2 { // 新規 var rdata = new RenderData(); - rdata.Initialize(ren); + rdata.Initialize(ren, referenceSetupData, referenceUniqueSetupData, referenceInitSetupData); renderDataDict.Add(handle, rdata); } @@ -96,8 +197,6 @@ namespace MagicaCloth2 bool delete = false; - //if(renderDataDict.ContainsKey(handle) == ) - //Debug.Log($"RemoveRenderer:{handle}"); //Debug.Assert(ren); Debug.Assert(renderDataDict.ContainsKey(handle)); @@ -137,6 +236,92 @@ namespace MagicaCloth2 } } + //========================================================================================= + public int AddRenderDataWork(RenderData rdata) + { + if (isValid == false) + return -1; + + var wdata = new RenderDataWork(); + + // オリジナルメッシュの接線情報を確認 + wdata.flag.SetBits(RenderDataFlag_HasMeshTangent, rdata.originalMesh.HasVertexAttribute(UnityEngine.Rendering.VertexAttribute.Tangent)); + //Debug.Log($"OriginalMesh[{originalMesh.name}] hasTangent:{originalMesh.HasVertexAttribute(UnityEngine.Rendering.VertexAttribute.Tangent)}"); + + // Flag + wdata.flag.SetBits(RenderDataFlag_HasSkinnedMesh, rdata.HasSkinnedMesh); + wdata.flag.SetBits(RenderDataFlag_HasBoneWeight, rdata.HasBoneWeight); + + // センタートランスフォーム用ボーンウエイト + var centerBoneWeight = new BoneWeight(); + centerBoneWeight.boneIndex0 = rdata.setupData.renderTransformIndex; + centerBoneWeight.weight0 = 1.0f; + wdata.centerBoneWeight = centerBoneWeight; + + // レンダーメッシュ用バッファ確保 + int vcnt = rdata.originalMesh.vertexCount; + wdata.renderMeshPositionAndNormalChunk = renderMeshPositions.AddRange(vcnt); + renderMeshNormals.AddRange(vcnt); + if (wdata.HasMeshTangent) + wdata.renderMeshTangentChunk = renderMeshTangents.AddRange(vcnt); + if (wdata.HasBoneWeight) + { + wdata.renderMeshBoneWeightChunk = renderMeshBoneWeights.AddRange(vcnt); + } + + // 格納 + var c = renderDataWorkArray.Add(wdata); + return c.startIndex; + } + + public void RemoveRenderDataWork(int index) + { + if (isValid == false) + return; + if (index < 0) + return; + + // バッファ削除 + ref var wdata = ref GetRenderDataWorkRef(index); + if (wdata.renderMeshPositionAndNormalChunk.IsValid) + { + renderMeshPositions.Remove(wdata.renderMeshPositionAndNormalChunk); + renderMeshNormals.Remove(wdata.renderMeshPositionAndNormalChunk); + } + if (wdata.renderMeshTangentChunk.IsValid) + { + renderMeshTangents.Remove(wdata.renderMeshTangentChunk); + } + if (wdata.renderMeshBoneWeightChunk.IsValid) + { + renderMeshBoneWeights.Remove(wdata.renderMeshBoneWeightChunk); + } + wdata.renderMeshPositionAndNormalChunk.Clear(); + wdata.renderMeshTangentChunk.Clear(); + wdata.renderMeshBoneWeightChunk.Clear(); + wdata.flag.Clear(); + + // 削除 + renderDataWorkArray.RemoveAndFill(new DataChunk(index)); + } + + public ref RenderDataWork GetRenderDataWorkRef(int index) + { + return ref renderDataWorkArray.GetRef(index); + } + + public bool IsSetRenderDataWorkFlag(int index, int flag) + { + ref var wdata = ref GetRenderDataWorkRef(index); + return wdata.flag.IsSet(flag); + } + + public void SetBitsRenderDataWorkFlag(int index, int flag, bool sw) + { + ref var wdata = ref GetRenderDataWorkRef(index); + wdata.flag.SetBits(flag, sw); + } + //========================================================================================= /// /// 有効化 @@ -157,14 +342,21 @@ namespace MagicaCloth2 } //========================================================================================= + static readonly ProfilerMarker writeMeshTimeProfiler = new ProfilerMarker("WriteMesh"); + /// /// レンダリング前更新 /// void PreRenderingUpdate() { + if (renderDataDict.Count == 0) + return; + // メッシュへの反映 + writeMeshTimeProfiler.Begin(); foreach (var rdata in renderDataDict.Values) rdata?.WriteMesh(); + writeMeshTimeProfiler.End(); } //========================================================================================= @@ -179,7 +371,25 @@ namespace MagicaCloth2 else { sb.AppendLine($"Render Manager. Count({renderDataDict.Count})"); + sb.AppendLine($" [RenderMeshBuffer]"); + sb.AppendLine($" -renderMeshPositions:{renderMeshPositions.ToSummary()}"); + sb.AppendLine($" -renderMeshNormals:{renderMeshNormals.ToSummary()}"); + sb.AppendLine($" -renderMeshTangents:{renderMeshTangents.ToSummary()}"); + sb.AppendLine($" [RenderDataWork]"); + sb.AppendLine($" -Count:{renderDataWorkArray.Count}"); + if (renderDataWorkArray.Count > 0) + { + for (int j = 0; j < renderDataWorkArray.Count; j++) + { + var wdata = renderDataWorkArray[j]; + if (wdata.IsValid() == false) + continue; + sb.AppendLine($" [{j}] MappingListCount:{wdata.mappingDataIndexList.Length}"); + } + } + + sb.AppendLine($" [RenderData]"); foreach (var kv in renderDataDict) { sb.Append(kv.Value.ToString()); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderManager.cs.meta index f3368aa8..b40fe674 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderManager.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderManager.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupData.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupData.cs index 948d41c3..0a7821a1 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupData.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupData.cs @@ -7,6 +7,7 @@ using Unity.Burst; using Unity.Collections; using Unity.Jobs; using Unity.Mathematics; +using Unity.Profiling; using UnityEngine; using UnityEngine.Jobs; @@ -19,10 +20,11 @@ namespace MagicaCloth2 /// またこの情報はキャラクターが動き出す前に取得しておく必要がある /// そのためAwake()などで実行する /// - public class RenderSetupData : IDisposable, ITransform + public partial class RenderSetupData : IDisposable, ITransform { public ResultCode result; public string name = string.Empty; + public bool isManaged; // pre-build DeserializeManager管理 // タイプ public enum SetupType @@ -45,11 +47,17 @@ namespace MagicaCloth2 public Mesh.MeshDataArray meshDataArray; // Jobで利用するためのMeshData public int skinRootBoneIndex; public int skinBoneCount; + // MeshDataでは取得できないメッシュ情報 public List bindPoseList; public NativeArray bonesPerVertexArray; public NativeArray boneWeightArray; + // PreBuild時のみ保持する情報.逆にmeshDataArrayは持たない + public NativeArray localPositions; + public NativeArray localNormals; + public NativeArray localTangents; + // Bone --------------------------------------------------------------- public List rootTransformIdList; public enum BoneConnectionMode @@ -82,7 +90,7 @@ namespace MagicaCloth2 public List> transformChildIdList; // 子IDリスト public NativeArray transformPositions; public NativeArray transformRotations; - public NativeArray transformLocalPositins; + public NativeArray transformLocalPositions; public NativeArray transformLocalRotations; public NativeArray transformScales; public NativeArray transformInverseRotations; @@ -95,16 +103,21 @@ namespace MagicaCloth2 public bool IsSuccess() => result.IsSuccess(); public bool IsFaild() => result.IsFaild(); public int TransformCount => transformList?.Count ?? 0; + public bool HasMeshDataArray => meshDataArray.Length > 0; + public bool HasLocalPositions => localPositions.IsCreated; + public bool HasTangent => localTangents.IsCreated && localTangents.Length > 0; - //static readonly ProfilerMarker initProfiler = new ProfilerMarker("Render Setup"); + static readonly ProfilerMarker readTransformProfiler = new ProfilerMarker("readTransform"); //========================================================================================= + public RenderSetupData() { } + /// /// レンダラーから基本情報を作成する(メインスレッドのみ) /// タイプはMeshになる /// /// - public RenderSetupData(Renderer ren) + public RenderSetupData(RenderSetupSerializeData referenceInitSetupData, Renderer ren) { //using (initProfiler.Auto()) { @@ -119,6 +132,9 @@ namespace MagicaCloth2 return; } + // 初期化データの有無 + bool useInitData = referenceInitSetupData != null; + name = ren.name; var sren = ren as SkinnedMeshRenderer; @@ -133,7 +149,36 @@ namespace MagicaCloth2 // 描画の基準トランスフォーム var renderTransform = ren.transform; - if (sren) + if (useInitData) + { + // 初期化データがある場合はコピーして終わり + skinBoneCount = referenceInitSetupData.skinBoneCount; + skinRootBoneIndex = referenceInitSetupData.skinRootBoneIndex; + renderTransformIndex = referenceInitSetupData.renderTransformIndex; + hasBoneWeight = referenceInitSetupData.hasBoneWeight; + + // transformList復元 + transformList = new List(new Transform[referenceInitSetupData.transformCount]); + int ucnt = referenceInitSetupData.useTransformCount; + for (int i = 0; i < ucnt; i++) + { + int tindex = referenceInitSetupData.useTransformIndexArray[i]; + transformList[tindex] = referenceInitSetupData.transformArray[i]; + } + + // SkinnedMeshRendererかつオリジナルメッシュが存在する場合はSkinnedMeshRenererを復元する + // 実行時キャラクターコピーへの対応 + if (sren && referenceInitSetupData.originalMesh && sren.sharedMesh != referenceInitSetupData.originalMesh && skinBoneCount > 0) + { + sren.sharedMesh = referenceInitSetupData.originalMesh; + var newBones = new Transform[skinBoneCount]; + transformList.CopyTo(0, newBones, 0, skinBoneCount); + sren.bones = newBones; + sren.rootBone = transformList[skinRootBoneIndex]; + //Debug.Log($"★SkinnedMeshRenderer再構成"); + } + } + else if (sren) { // bones // このスキニングボーンの取得が特に重くメモリアロケーションも頻発する問題児 @@ -188,7 +233,7 @@ namespace MagicaCloth2 } // トランスフォーム情報の読み取り - ReadTransformInformation(includeChilds: false); + ReadTransformInformation(includeChilds: false, referenceInitSetupData, ren.transform); // bindpose / weights if (sren) @@ -207,12 +252,14 @@ namespace MagicaCloth2 // どうもコピーを作らないとダメらしい.. // ※具体的にはメッシュのクローンを作成したときに壊れる - var weightArray = mesh.GetAllBoneWeights(); - var perVertexArray = mesh.GetBonesPerVertex(); + using var weightArray = mesh.GetAllBoneWeights(); + using var perVertexArray = mesh.GetBonesPerVertex(); boneWeightArray = new NativeArray(weightArray, Allocator.Persistent); bonesPerVertexArray = new NativeArray(perVertexArray, Allocator.Persistent); +#if UNITY_EDITOR // 5ボーン以上を利用する頂点ウエイトは警告とする。一応無効となるだけで動くのでエラーにはしない。 + // なおこの検証はビルド環境では行わない int vcnt = mesh.vertexCount; using var bonesPerVertexResult = new NativeReference(Allocator.TempJob); var job = new VertexWeight5BoneCheckJob() @@ -223,6 +270,7 @@ namespace MagicaCloth2 }; job.Run(); result.SetWarning(bonesPerVertexResult.Value); +#endif } else { @@ -276,6 +324,10 @@ namespace MagicaCloth2 } } +#if UNITY_EDITOR + /// + /// 5ウエイト以上の検出 + /// [BurstCompile] struct VertexWeight5BoneCheckJob : IJob { @@ -301,6 +353,7 @@ namespace MagicaCloth2 } } } +#endif /// /// ルートボーンリストから基本情報を作成する(メインスレッドのみ) @@ -309,6 +362,7 @@ namespace MagicaCloth2 /// /// public RenderSetupData( + RenderSetupSerializeData referenceInitSetupData, SetupType setType, Transform renderTransform, List rootTransforms, @@ -322,6 +376,8 @@ namespace MagicaCloth2 //using (initProfiler.Auto()) try { + bool useInitData = referenceInitSetupData != null; + // Boneタイプに設定 setupType = setType; @@ -344,30 +400,47 @@ namespace MagicaCloth2 this.name = name; // 必要なトランスフォーム情報 - var indexDict = new Dictionary(256); - transformList = new List(256); - - // root以下をすべて登録する - var stack = new Stack(256); - foreach (var t in rootTransforms) - stack.Push(t); - while (stack.Count > 0) + if (useInitData) { - var t = stack.Pop(); - if (indexDict.ContainsKey(t)) - continue; + // 初期化データがある場合はコピーして終わり + transformList = new List(referenceInitSetupData.transformArray); + skinBoneCount = referenceInitSetupData.skinBoneCount; + renderTransformIndex = referenceInitSetupData.renderTransformIndex; + } + else + { + var indexDict = new Dictionary(256); + transformList = new List(256); - // 登録 - int index = transformList.Count; - transformList.Add(t); - indexDict.Add(t, index); - - // child - int cnt = t.childCount; - for (int i = 0; i < cnt; i++) + // root以下をすべて登録する + var stack = new Stack(256); + foreach (var t in rootTransforms) + stack.Push(t); + while (stack.Count > 0) { - stack.Push(t.GetChild(i)); + var t = stack.Pop(); + if (indexDict.ContainsKey(t)) + continue; + + // 登録 + int index = transformList.Count; + transformList.Add(t); + indexDict.Add(t, index); + + // child + int cnt = t.childCount; + for (int i = 0; i < cnt; i++) + { + stack.Push(t.GetChild(i)); + } } + + // スキニングボーン数 + skinBoneCount = transformList.Count; + + // レンダートランスフォームを最後に追加 + renderTransformIndex = transformList.Count; + transformList.Add(renderTransform); } // root transform id @@ -392,15 +465,8 @@ namespace MagicaCloth2 } } - // スキニングボーン数 - skinBoneCount = transformList.Count; - - // レンダートランスフォームを最後に追加 - renderTransformIndex = transformList.Count; - transformList.Add(renderTransform); - // トランスフォーム情報の読み取り - ReadTransformInformation(includeChilds: true); + ReadTransformInformation(includeChilds: true, referenceInitSetupData, renderTransform); // 完了 result.SetSuccess(); @@ -422,42 +488,117 @@ namespace MagicaCloth2 /// トランスフォーム情報の読み取り(メインスレッドのみ) /// この情報だけはキャラクターが動く前に取得する必要がある /// - void ReadTransformInformation(bool includeChilds) + void ReadTransformInformation(bool includeChilds, RenderSetupSerializeData referenceInitSetupData, Transform rendererTransform) { + readTransformProfiler.Begin(); + int tcnt = transformList.Count; - using var transformArray = new TransformAccessArray(transformList.ToArray()); + bool useInitData = referenceInitSetupData != null; + + // バッファ作成 transformPositions = new NativeArray(tcnt, Allocator.Persistent); transformRotations = new NativeArray(tcnt, Allocator.Persistent); - transformLocalPositins = new NativeArray(tcnt, Allocator.Persistent); + transformLocalPositions = new NativeArray(tcnt, Allocator.Persistent); transformLocalRotations = new NativeArray(tcnt, Allocator.Persistent); transformScales = new NativeArray(tcnt, Allocator.Persistent); transformInverseRotations = new NativeArray(tcnt, Allocator.Persistent); - var job = new ReadTransformJob() + + // 読み取り + if (useInitData) { - positions = transformPositions, - rotations = transformRotations, - scales = transformScales, - localPositions = transformLocalPositins, - localRotations = transformLocalRotations, - inverseRotations = transformInverseRotations, - }; - // シミュレーション以外でワーカーを消費したくないのでRun()版にしておく - job.RunReadOnly(transformArray); + Debug.Assert(tcnt == referenceInitSetupData.transformCount); - // 初期センタートランスフォームを別途コピーしておく - initRenderLocalToWorld = GetRendeerLocalToWorldMatrix(); - initRenderWorldtoLocal = math.inverse(initRenderLocalToWorld); - initRenderRotation = transformRotations[renderTransformIndex]; - initRenderScale = transformScales[renderTransformIndex]; + // 初期化データがある場合はコピーして終わり + int ucnt = referenceInitSetupData.useTransformCount; - // id + if (ucnt == tcnt) + { + // 全体コピー + NativeArray.Copy(referenceInitSetupData.transformPositions, 0, transformPositions, 0, ucnt); + NativeArray.Copy(referenceInitSetupData.transformRotations, 0, transformRotations, 0, ucnt); + NativeArray.Copy(referenceInitSetupData.transformLocalPositions, 0, transformLocalPositions, 0, ucnt); + NativeArray.Copy(referenceInitSetupData.transformLocalRotations, 0, transformLocalRotations, 0, ucnt); + NativeArray.Copy(referenceInitSetupData.transformScales, 0, transformScales, 0, ucnt); + } + else + { + // 差分 + for (int i = 0; i < ucnt; i++) + { + int tindex = referenceInitSetupData.useTransformIndexArray[i]; + transformPositions[tindex] = referenceInitSetupData.transformPositions[i]; + transformRotations[tindex] = referenceInitSetupData.transformRotations[i]; + transformLocalPositions[tindex] = referenceInitSetupData.transformLocalPositions[i]; + transformLocalRotations[tindex] = referenceInitSetupData.transformLocalRotations[i]; + transformScales[tindex] = referenceInitSetupData.transformScales[i]; + } + } + + // 逆回転のみ計算で求める + var job = new CalcInverseRotationJob() + { + rotations = transformRotations, + inverseRotations = transformInverseRotations, + }; + job.Run(tcnt); + + // 初期センタートランスフォームを別途コピーしておく + initRenderLocalToWorld = referenceInitSetupData.initRenderLocalToWorld; + initRenderWorldtoLocal = referenceInitSetupData.initRenderWorldtoLocal; + initRenderRotation = referenceInitSetupData.initRenderRotation; + initRenderScale = referenceInitSetupData.initRenderScale; + } + else + { + //using var transformArray = new TransformAccessArray(transformList.ToArray()); + // Unity6.1対応 + using var transformArray = new TransformAccessArray(transformList.Count); + int cnt = transformList.Count; + for (int i = 0; i < cnt; i++) + { + var t = transformList[i]; + if (t == null) + t = rendererTransform; + //transformArray[i] = t; + transformArray.Add(t); + } + + + var job = new ReadTransformJob() + { + positions = transformPositions, + rotations = transformRotations, + scales = transformScales, + localPositions = transformLocalPositions, + localRotations = transformLocalRotations, + inverseRotations = transformInverseRotations + }; + // シミュレーション以外でワーカーを消費したくないのでRun()版にしておく + job.RunReadOnly(transformArray); + + // 初期センタートランスフォームを別途コピーしておく + initRenderLocalToWorld = GetRendeerLocalToWorldMatrix(); + initRenderWorldtoLocal = math.inverse(initRenderLocalToWorld); + initRenderRotation = transformRotations[renderTransformIndex]; + initRenderScale = transformScales[renderTransformIndex]; + } + + // id / parent id transformIdList = new List(tcnt); transformParentIdList = new List(tcnt); for (int i = 0; i < tcnt; i++) { + int id = 0, pid = 0; + var t = transformList[i]; - transformIdList.Add(t?.GetInstanceID() ?? 0); - transformParentIdList.Add(t?.parent?.GetInstanceID() ?? 0); + if (t) + { + id = t.GetInstanceID(); + if (includeChilds && t.parent) + pid = t.parent.GetInstanceID(); + } + transformIdList.Add(id); + transformParentIdList.Add(pid); } // child id @@ -468,7 +609,7 @@ namespace MagicaCloth2 { var t = transformList[i]; var clist = new FixedList512Bytes(); - if (t?.childCount > 0) + if (t && t.childCount > 0) { for (int j = 0; j < t.childCount; j++) { @@ -479,6 +620,32 @@ namespace MagicaCloth2 transformChildIdList.Add(clist); } } + + readTransformProfiler.End(); + } + + /// + /// 逆回転を計算で求める + /// + [BurstCompile] + struct CalcInverseRotationJob : IJobParallelFor + { + [Unity.Collections.ReadOnly] + public NativeArray rotations; + [NativeDisableParallelForRestriction] + [Unity.Collections.WriteOnly] + public NativeArray inverseRotations; + + public void Execute(int index) + { + var rot = rotations[index]; + if (math.any(rot.value)) + { + // どれか1つでも != 0 なら実行する + var irot = math.inverse(rot); + inverseRotations[index] = irot; + } + } } /// @@ -487,16 +654,22 @@ namespace MagicaCloth2 [BurstCompile] struct ReadTransformJob : IJobParallelForTransform { + [NativeDisableParallelForRestriction] [Unity.Collections.WriteOnly] public NativeArray positions; + [NativeDisableParallelForRestriction] [Unity.Collections.WriteOnly] public NativeArray rotations; + [NativeDisableParallelForRestriction] [Unity.Collections.WriteOnly] public NativeArray scales; + [NativeDisableParallelForRestriction] [Unity.Collections.WriteOnly] public NativeArray localPositions; + [NativeDisableParallelForRestriction] [Unity.Collections.WriteOnly] public NativeArray localRotations; + [NativeDisableParallelForRestriction] [Unity.Collections.WriteOnly] public NativeArray inverseRotations; @@ -527,23 +700,22 @@ namespace MagicaCloth2 public void Dispose() { - if (bonesPerVertexArray.IsCreated) - bonesPerVertexArray.Dispose(); - if (boneWeightArray.IsCreated) - boneWeightArray.Dispose(); + // Pre-Build DeserializeManager管理中は破棄させない + if (isManaged) + return; - if (transformPositions.IsCreated) - transformPositions.Dispose(); - if (transformRotations.IsCreated) - transformRotations.Dispose(); - if (transformLocalPositins.IsCreated) - transformLocalPositins.Dispose(); - if (transformLocalRotations.IsCreated) - transformLocalRotations.Dispose(); - if (transformScales.IsCreated) - transformScales.Dispose(); - if (transformInverseRotations.IsCreated) - transformInverseRotations.Dispose(); + bonesPerVertexArray.MC2DisposeSafe(); + boneWeightArray.MC2DisposeSafe(); + localPositions.MC2DisposeSafe(); + localNormals.MC2DisposeSafe(); + localTangents.MC2DisposeSafe(); + + transformPositions.MC2DisposeSafe(); + transformRotations.MC2DisposeSafe(); + transformLocalPositions.MC2DisposeSafe(); + transformLocalRotations.MC2DisposeSafe(); + transformScales.MC2DisposeSafe(); + transformInverseRotations.MC2DisposeSafe(); // MeshDataArrayはメインスレッドのみDispose()可能 if (setupType == SetupType.MeshCloth) @@ -555,8 +727,12 @@ namespace MagicaCloth2 public void GetUsedTransform(HashSet transformSet) { - foreach (var t in transformList) - transformSet.Add(t); + if (transformList != null) + { + foreach (var t in transformList) + if (t) + transformSet.Add(t); + } } public void ReplaceTransform(Dictionary replaceDict) @@ -622,9 +798,10 @@ namespace MagicaCloth2 public float4x4 GetRendeerLocalToWorldMatrix() { - var pos = transformPositions[renderTransformIndex]; - var rot = transformRotations[renderTransformIndex]; - var scl = transformScales[renderTransformIndex]; + int index = renderTransformIndex; + var pos = transformPositions[index]; + var rot = transformRotations[index]; + var scl = transformScales[index]; return float4x4.TRS(pos, rot, scl); } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupData.cs.meta index dc6f58bc..206cef25 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupData.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupData.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupData.cs + uploadId: 756593 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 00000000..13e1cc18 --- /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 00000000..e8fa4084 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupDataSerialization.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 15097613d7348214ca528d3986504ece +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupDataSerialization.cs + uploadId: 756593 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 00000000..b725ea11 --- /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 00000000..162302cb --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupSerializeData.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 98f83594b09a8c5469b78d1d22047ecd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Render/RenderSetupSerializeData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/ColliderManager.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/ColliderManager.cs index e1cbd84e..be2dc640 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/ColliderManager.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/ColliderManager.cs @@ -2,10 +2,9 @@ // Copyright (c) 2023 MagicaSoft. // https://magicasoft.jp using System.Collections.Generic; +using System.Linq; using System.Text; -using Unity.Burst; using Unity.Collections; -using Unity.Jobs; using Unity.Mathematics; using UnityEngine; @@ -42,14 +41,31 @@ namespace MagicaCloth2 } /// - /// フラグ(8bit) - /// 下位4bitはコライダー種類 - /// 上位4bitはフラグ + /// シンメトリータイプ(最大15まで) /// - public const byte Flag_Valid = 0x10; // データの有無 - public const byte Flag_Enable = 0x20; // 有効状態 - public const byte Flag_Reset = 0x40; // 位置リセット - public ExNativeArray flagArray; + public enum SymmetryType : byte + { + None = 0, + X_Symmetry = 1, + Y_Symmetry = 2, + Z_Symmetry = 3, + XYZ_Symmetry = 4, + } + + /// + /// フラグ(16bit) + /// (0~3:4bit)コライダー種類 + /// (4~7:4bit)シンメトリータイプ + /// (8~15:8bit)フラグ + /// + public const ushort Flag_Valid = 0x0100; // データの有無 + public const ushort Flag_Enable = 0x0200; // 有効状態 + public const ushort Flag_Reset = 0x0400; // 位置リセット + public const ushort Flag_Reverse = 0x0800; // 方向逆転 + public const ushort Flag_Symmetry = 0x1000; // シンメトリー + public const ushort Flag_SymmetryReverse = 0x2000; // シンメトリーによる方向フリップ + public const ushort Flag_ScaleSuspend = 0x4000; // 極小スケールによる機能停止 + public ExNativeArray flagArray; /// /// トランスフォームからの中心ローカルオフセット位置 @@ -66,7 +82,7 @@ namespace MagicaCloth2 /// /// 現フレーム姿勢 - /// トランスフォームからスナップされたチームローカル姿勢 + /// トランスフォームからスナップされた姿勢(ワールド) /// センターオフセットも計算される /// public ExNativeArray framePositions; @@ -74,36 +90,33 @@ namespace MagicaCloth2 public ExNativeArray frameScales; /// - /// 1つ前のフレーム姿勢 + /// 1つ前のフレーム姿勢(ワールド) /// public ExNativeArray oldFramePositions; public ExNativeArray oldFrameRotations; - //public ExNativeArray oldFrameScales; /// - /// 現ステップでの姿勢 + /// 現ステップでの姿勢(ワールド) /// public ExNativeArray nowPositions; public ExNativeArray nowRotations; - //public ExNativeArray nowScales; + /// + /// 前ステップでの姿勢(ワールド) + /// public ExNativeArray oldPositions; public ExNativeArray oldRotations; /// - /// 有効なコライダーデータ数 + /// シンメトリー用のメインコライダーへのローカルインデックス配列 /// - public int DataCount => teamIdArray?.Count ?? 0; + public ExNativeArray mainColliderIndices; /// /// 登録コライダーコンポーネント + /// 現在はデバッグ用 /// - public HashSet colliderSet = new HashSet(); - - /// - /// 登録コライダー数 - /// - public int ColliderCount => colliderSet.Count; + HashSet colliderSet = new HashSet(); bool isValid = false; @@ -137,13 +150,12 @@ namespace MagicaCloth2 frameScales?.Dispose(); nowPositions?.Dispose(); nowRotations?.Dispose(); - //nowScales?.Dispose(); oldFramePositions?.Dispose(); oldFrameRotations?.Dispose(); - //oldFrameScales?.Dispose(); oldPositions?.Dispose(); oldRotations?.Dispose(); workDataArray?.Dispose(); + mainColliderIndices?.Dispose(); teamIdArray = null; flagArray = null; @@ -153,13 +165,12 @@ namespace MagicaCloth2 frameScales = null; nowPositions = null; nowRotations = null; - //nowScales = null; oldFramePositions = null; oldFrameRotations = null; - //oldFrameScales = null; oldPositions = null; oldRotations = null; workDataArray = null; + mainColliderIndices = null; colliderSet.Clear(); } @@ -175,7 +186,7 @@ namespace MagicaCloth2 const int capacity = 256; teamIdArray = new ExNativeArray(capacity); - flagArray = new ExNativeArray(capacity); + flagArray = new ExNativeArray(capacity); centerArray = new ExNativeArray(capacity); sizeArray = new ExNativeArray(capacity); framePositions = new ExNativeArray(capacity); @@ -183,13 +194,12 @@ namespace MagicaCloth2 frameScales = new ExNativeArray(capacity); nowPositions = new ExNativeArray(capacity); nowRotations = new ExNativeArray(capacity); - //nowScales = new ExNativeArray(capacity); oldFramePositions = new ExNativeArray(capacity); oldFrameRotations = new ExNativeArray(capacity); - //oldFrameScales = new ExNativeArray(capacity); oldPositions = new ExNativeArray(capacity); oldRotations = new ExNativeArray(capacity); workDataArray = new ExNativeArray(capacity); + mainColliderIndices = new ExNativeArray(capacity); isValid = true; } @@ -214,32 +224,45 @@ namespace MagicaCloth2 int cnt = cprocess.cloth.SerializeData.colliderCollisionConstraint.ColliderLength; if (cnt > 0) { + // シンメトリーも考慮した初期コライダーの数を算出する + var clist = cprocess.cloth.SerializeData.colliderCollisionConstraint.colliderList; + int activeCount = 0; + clist.ForEach(x => + { + if (x) + activeCount += x.symmetryMode != ColliderSymmetryMode.None ? 2 : 1; + }); + //Debug.Log($"[{cprocess.cloth.name}] ActiveColliderCount:{activeCount}"); + + // 初期コライダーの領域確保 int teamId = cprocess.TeamId; ref var tdata = ref MagicaManager.Team.GetTeamDataRef(teamId); - - // コライダー数で初期化 - tdata.colliderChunk = teamIdArray.AddRange(cnt, (short)teamId); - flagArray.AddRange(cnt, default); - centerArray.AddRange(cnt); - sizeArray.AddRange(cnt); - framePositions.AddRange(cnt); - frameRotations.AddRange(cnt); - frameScales.AddRange(cnt); - nowPositions.AddRange(cnt); - nowRotations.AddRange(cnt); - //nowScales.AddRange(cnt); - oldFramePositions.AddRange(cnt); - oldFrameRotations.AddRange(cnt); - //oldFrameScales.AddRange(cnt); - oldPositions.AddRange(cnt); - oldRotations.AddRange(cnt); - workDataArray.AddRange(cnt); - tdata.colliderTransformChunk = MagicaManager.Bone.AddTransform(cnt, teamId); // 領域のみ + tdata.colliderChunk = teamIdArray.AddRange(activeCount, (short)teamId); + flagArray.AddRange(activeCount, default); + centerArray.AddRange(activeCount); + sizeArray.AddRange(activeCount); + framePositions.AddRange(activeCount); + frameRotations.AddRange(activeCount); + frameScales.AddRange(activeCount); + nowPositions.AddRange(activeCount); + nowRotations.AddRange(activeCount); + oldFramePositions.AddRange(activeCount); + oldFrameRotations.AddRange(activeCount); + oldPositions.AddRange(activeCount); + oldRotations.AddRange(activeCount); + workDataArray.AddRange(activeCount); + mainColliderIndices.AddRange(activeCount); + Transform t = cprocess.cloth.ClothTransform; + tdata.colliderTransformChunk = MagicaManager.Bone.AddTransform(activeCount, teamId, t); // 領域のみ tdata.colliderCount = 0; - cprocess.colliderList.AddRange(new ColliderComponent[cnt]); // nullで領域確保 // 初期コライダー登録 - InitColliders(cprocess); + for (int i = 0; i < clist.Count; i++) + { + var col = clist[i]; + if (col && cprocess.colliderDict.ContainsKey(col) == false) + AddCollider(cprocess, col); + } } } @@ -255,15 +278,18 @@ namespace MagicaCloth2 int teamId = cprocess.TeamId; // コライダー解除 - foreach (var col in cprocess.colliderList) + foreach (var col in cprocess.colliderDict.Keys) { if (col) { - col.Exit(teamId); - colliderSet.Remove(col); + if (col.Exit(teamId)) + { + // 利用者0 + colliderSet.Remove(col); + } } } - cprocess.colliderList.Clear(); + cprocess.colliderDict.Clear(); ref var tdata = ref MagicaManager.Team.GetTeamDataRef(teamId); @@ -277,13 +303,12 @@ namespace MagicaCloth2 frameScales.Remove(c); nowPositions.Remove(c); nowRotations.Remove(c); - //nowScales.Remove(c); oldFramePositions.Remove(c); oldFrameRotations.Remove(c); - //oldFrameScales.Remove(c); oldPositions.Remove(c); oldRotations.Remove(c); workDataArray.Remove(c); + mainColliderIndices.Remove(c); tdata.colliderChunk.Clear(); tdata.colliderCount = 0; @@ -295,60 +320,36 @@ namespace MagicaCloth2 //========================================================================================= /// - /// 初期コライダーの登録 - /// - /// - internal void InitColliders(ClothProcess cprocess) - { - var clist = cprocess.cloth.SerializeData.colliderCollisionConstraint.colliderList; - if (clist.Count == 0) - return; - - ref var tdata = ref MagicaManager.Team.GetTeamDataRef(cprocess.TeamId); - int index = 0; - for (int i = 0; i < clist.Count; i++) - { - var col = clist[i]; - if (col && cprocess.colliderList.Contains(col) == false) - { - AddColliderInternal(cprocess, col, index, tdata.colliderChunk.startIndex + index, tdata.colliderTransformChunk.startIndex + index); - tdata.colliderCount++; - index++; - } - } - } - - /// - /// コライダーの内容を更新する + /// コライダーのリスト内容を更新する + /// これはMagicaClothコンポーネント側のコライダーリストが変更された場合 + /// つまりパラメータの変更ではない /// /// internal void UpdateColliders(ClothProcess cprocess) { if (isValid == false) return; + + // ここではコライダーリストへのコンポーネント追加削除だけで、シンメトリーなどの切り替えは考慮しなくていい var clist = cprocess.cloth.SerializeData.colliderCollisionConstraint.colliderList; - // 現在の登録コライダーと比較し削除と追加を行う - // 既存削除 - for (int i = 0, cnt = cprocess.ColliderCapacity; i < cnt;) + // 現在の登録コライダーと比較し不要なコライダーを削除する + var keys = cprocess.colliderDict.Keys.ToList(); + foreach (ColliderComponent col in keys) { - var col = cprocess.colliderList[i]; if (col && clist.Contains(col) == false) { - // コライダー消滅 + // コライダー削除 RemoveCollider(col, cprocess.TeamId); } - else - i++; } - // 新規追加 + // 現在の登録コライダーと比較し必要なコライダーを追加する foreach (var col in clist) { - if (col && cprocess.GetColliderIndex(col) < 0) + if (col && cprocess.colliderDict.ContainsKey(col) == false) { AddCollider(cprocess, col); - //Debug.Log($"コライダー追加:{col.name}"); } } } @@ -364,12 +365,38 @@ namespace MagicaCloth2 return; if (col == null) return; - if (cprocess.GetColliderIndex(col) >= 0) + if (cprocess.colliderDict.ContainsKey(col)) return; // すでに追加済み ref var tdata = ref MagicaManager.Team.GetTeamDataRef(cprocess.TeamId); Debug.Assert(tdata.IsValid); + // Main + AddColliderInternal(ref tdata, cprocess, col, false); + colliderSet.Add(col); + + // Symmetry + col.SetActiveSymmetryMode(firstOnly: true); // シンメトリー情報更新 + AddColliderInternal(ref tdata, cprocess, col, true); + + // コライダーコンポーネント側にも登録する(紐づけ) + col.Register(cprocess.TeamId); + } + + void AddColliderInternal(ref TeamManager.TeamData tdata, ClothProcess cprocess, ColliderComponent col, bool isSymmetry) + { + // シンメトリーの有効性 + if (isSymmetry) + { + if (col.ActiveSymmetryMode == ColliderSymmetryMode.None) + return; + if (col.ActiveSymmetryTarget == null) + return; + } + + int teamId = cprocess.TeamId; + + // 領域拡張 if (tdata.colliderChunk.IsValid == false) { // 新規確保 @@ -388,11 +415,12 @@ namespace MagicaCloth2 oldPositions.AddRange(newCount); oldRotations.AddRange(newCount); workDataArray.AddRange(newCount); - tdata.colliderTransformChunk = MagicaManager.Bone.AddTransform(newCount, cprocess.TeamId); // 領域のみ + mainColliderIndices.AddRange(newCount); + Transform t = cprocess.cloth.ClothTransform; + tdata.colliderTransformChunk = MagicaManager.Bone.AddTransform(newCount, cprocess.TeamId, t); // 領域のみ tdata.colliderCount = 0; - cprocess.colliderList.AddRange(new ColliderComponent[newCount]); // nullで領域確保 } - else if (tdata.ColliderCount == tdata.colliderChunk.dataLength) + else if (tdata.UseColliderCount == tdata.colliderChunk.dataLength) { // コライダー配列のキャパシティ上限なら拡張する // 拡張 @@ -412,28 +440,140 @@ namespace MagicaCloth2 oldPositions.Expand(oldColliderChunk, newCount); oldRotations.Expand(oldColliderChunk, newCount); workDataArray.Expand(oldColliderChunk, newCount); + mainColliderIndices.Expand(oldColliderChunk, newCount); // コライダートランスフォーム拡張 var oldColliderTransformChunk = tdata.colliderTransformChunk; tdata.colliderTransformChunk = MagicaManager.Bone.Expand(oldColliderTransformChunk, newCount); - - // コライダー配列拡張 - cprocess.colliderList.AddRange(new ColliderComponent[Define.System.ExpandedColliderCount]); } - // 最後に追加する - int index = tdata.colliderCount; - int arrayIndex = tdata.colliderChunk.startIndex + index; - int transformIndex = tdata.colliderTransformChunk.startIndex + index; - AddColliderInternal(cprocess, col, index, arrayIndex, transformIndex); + // 追加インデックス + int localIndex = tdata.UseColliderCount; + int arrayIndex = tdata.colliderChunk.startIndex + localIndex; + int transformIndex = tdata.colliderTransformChunk.startIndex + localIndex; + + // フラグ + var flag = new ExBitFlag16(); + flag = DataUtility.SetColliderType(flag, col.GetColliderType()); + flag.SetFlag(Flag_Valid, true); + flag.SetFlag(Flag_Enable, col.isActiveAndEnabled); + flag.SetFlag(Flag_Reset, true); + flag.SetFlag(Flag_Reverse, col.IsReverseDirection()); + // ワールド姿勢 + var ct = col.transform; + float3 pos = float3.zero; + quaternion rot = quaternion.identity; + float3 scl = 1; + float3 center = col.center; + // 登録トランスフォーム + Transform target = ct; + if (isSymmetry) + { + // シンメトリー + // ここでは姿勢計算は不要。方向性のみでよい。 + SymmetryType symType; + switch (col.ActiveSymmetryMode) + { + case ColliderSymmetryMode.X_Symmetry: + symType = SymmetryType.X_Symmetry; + break; + case ColliderSymmetryMode.Y_Symmetry: + symType = SymmetryType.Y_Symmetry; + break; + case ColliderSymmetryMode.Z_Symmetry: + symType = SymmetryType.Z_Symmetry; + break; + case ColliderSymmetryMode.XYZ_Symmetry: + symType = SymmetryType.XYZ_Symmetry; + break; + default: + Develop.LogError("Unknown active symmetry mode."); + return; + } + flag = DataUtility.SetSymmetryType(flag, symType); + + // 方向性 + float direction = 1.0f; + if (col is MagicaCapsuleCollider) + { + var ccol = col as MagicaCapsuleCollider; + if (col.ActiveSymmetryMode == ColliderSymmetryMode.X_Symmetry && ccol.direction == MagicaCapsuleCollider.Direction.X) + direction = -1.0f; + else if (col.ActiveSymmetryMode == ColliderSymmetryMode.Y_Symmetry && ccol.direction == MagicaCapsuleCollider.Direction.Y) + direction = -1.0f; + else if (col.ActiveSymmetryMode == ColliderSymmetryMode.Z_Symmetry && ccol.direction == MagicaCapsuleCollider.Direction.Z) + direction = -1.0f; + else if (col.ActiveSymmetryMode == ColliderSymmetryMode.XYZ_Symmetry) + direction = -1.0f; + } + else if (col is MagicaPlaneCollider) + { + switch (col.ActiveSymmetryMode) + { + case ColliderSymmetryMode.Y_Symmetry: + case ColliderSymmetryMode.XYZ_Symmetry: + direction = -1.0f; + break; + } + } + + // フラグ + flag.SetFlag(Flag_Symmetry, true); + flag.SetFlag(Flag_SymmetryReverse, direction < 0.0f); + + // 登録トランスフォーム + target = col.ActiveSymmetryTarget; + } + + // マネージャへ登録 + teamIdArray[arrayIndex] = (short)teamId; + flagArray[arrayIndex] = flag; + centerArray[arrayIndex] = center; + sizeArray[arrayIndex] = math.max(col.GetSize(), 0.0001f); // 念のため + framePositions[arrayIndex] = pos; + frameRotations[arrayIndex] = rot; + frameScales[arrayIndex] = scl; + nowPositions[arrayIndex] = pos; + nowRotations[arrayIndex] = rot; + oldFramePositions[arrayIndex] = pos; + oldFrameRotations[arrayIndex] = rot; + oldPositions[arrayIndex] = pos; + oldRotations[arrayIndex] = rot; + mainColliderIndices[arrayIndex] = 0; + + // ClothProcessにコライダーコンポーネントを登録 + if (cprocess.colliderDict.ContainsKey(col)) + { + int2 data = cprocess.colliderDict[col]; + if (isSymmetry) + { + data.y = localIndex; + // メインコライダーローカルインデックスを記録 + mainColliderIndices[arrayIndex] = data.x; + } + else + data.x = localIndex; + cprocess.colliderDict[col] = data; + } + else + { + Debug.Assert(isSymmetry == false); + cprocess.colliderDict.Add(col, new int2(localIndex, 0)); + } + + // トランスフォーム登録 + bool t_enable = cprocess.IsEnable && flag.IsSet(Flag_Enable); + var tflag = new ExBitFlag8(TransformManager.Flag_Read); + tflag.SetFlag(TransformManager.Flag_Enable, t_enable); + MagicaManager.Bone.SetTransform(target, tflag, transformIndex, teamId); tdata.colliderCount++; } + /// /// コライダーを削除する - /// ここでは領域は削除せずにデータのみを無効化させる - /// 領域は生存する最後尾のデータと入れ替えられる(SwapBack) + /// 削除領域は生存する最後尾のデータと入れ替えられる(SwapBack) /// /// /// @@ -441,6 +581,29 @@ namespace MagicaCloth2 { if (isValid == false) return; + if (col == null || teamId == 0) + return; + + // Symmetry + RemoveColliderInternal(col, teamId, true); + + // Main + RemoveColliderInternal(col, teamId, false); + + // コライダーコンポーネント側からも削除登録する(紐づけ解除) + if (col.Exit(teamId)) + { + // 利用者0 + colliderSet.Remove(col); + } + } + + void RemoveColliderInternal(ColliderComponent col, int teamId, bool isSymmetry) + { + if (isValid == false) + return; + if (col == null || teamId == 0) + return; ref var tdata = ref MagicaManager.Team.GetTeamDataRef(teamId); int ccnt = tdata.colliderCount; if (ccnt == 0) @@ -448,16 +611,23 @@ namespace MagicaCloth2 var cprocess = MagicaManager.Team.GetClothProcess(teamId); if (cprocess == null) return; - int index = cprocess.GetColliderIndex(col); - if (index < 0) + if (cprocess.colliderDict.ContainsKey(col) == false) return; + int2 data = cprocess.colliderDict[col]; + int localIndex = data.x; + if (isSymmetry) + { + if (data.y == 0) + return; // シンメトリーコライダーなし + localIndex = data.y; + } - int arrayIndex = tdata.colliderChunk.startIndex + index; - int transformIndex = tdata.colliderTransformChunk.startIndex + index; + int arrayIndex = tdata.colliderChunk.startIndex + localIndex; + int transformIndex = tdata.colliderTransformChunk.startIndex + localIndex; - int swapIndex = ccnt - 1; - int swapArrayIndex = tdata.colliderChunk.startIndex + swapIndex; - int swapTransformIndex = tdata.colliderTransformChunk.startIndex + swapIndex; + int swapLocalIndex = ccnt - 1; + int swapArrayIndex = tdata.colliderChunk.startIndex + swapLocalIndex; + int swapTransformIndex = tdata.colliderTransformChunk.startIndex + swapLocalIndex; if (arrayIndex < swapArrayIndex) { @@ -471,12 +641,11 @@ namespace MagicaCloth2 frameScales[arrayIndex] = frameScales[swapArrayIndex]; nowPositions[arrayIndex] = nowPositions[swapArrayIndex]; nowRotations[arrayIndex] = nowRotations[swapArrayIndex]; - //nowScales[arrayIndex] = nowScales[swapArrayIndex]; oldFramePositions[arrayIndex] = oldFramePositions[swapArrayIndex]; oldFrameRotations[arrayIndex] = oldFrameRotations[swapArrayIndex]; - //oldFrameScales[arrayIndex] = oldFrameScales[swapArrayIndex]; oldPositions[arrayIndex] = oldPositions[swapArrayIndex]; oldRotations[arrayIndex] = oldRotations[swapArrayIndex]; + mainColliderIndices[arrayIndex] = mainColliderIndices[swapArrayIndex]; flagArray[swapArrayIndex] = default; teamIdArray[swapArrayIndex] = 0; @@ -486,8 +655,24 @@ namespace MagicaCloth2 MagicaManager.Bone.SetTransform(null, default, swapTransformIndex, 0); // cprocess - cprocess.colliderList[index] = cprocess.colliderList[swapIndex]; - cprocess.colliderList[swapIndex] = null; + var ckeys = cprocess.colliderDict.Keys.ToList(); + foreach (ColliderComponent kcol in ckeys) + { + Debug.Assert(cprocess.colliderDict.ContainsKey(kcol)); + int2 data2 = cprocess.colliderDict[kcol]; + if (data2.x == swapLocalIndex) + { + data2.x = localIndex; + cprocess.colliderDict[kcol] = data2; + break; + } + if (data2.y == swapLocalIndex) + { + data2.y = localIndex; + cprocess.colliderDict[kcol] = data2; + break; + } + } } else { @@ -497,58 +682,16 @@ namespace MagicaCloth2 // transform MagicaManager.Bone.SetTransform(null, default, transformIndex, 0); - - // cprocess - cprocess.colliderList[index] = null; } + if (isSymmetry) + data.y = 0; + else + data.x = 0; + cprocess.colliderDict[col] = data; + if (data.x == 0 && data.y == 0 && isSymmetry == false) + cprocess.colliderDict.Remove(col); // コライダー削除 tdata.colliderCount--; - - colliderSet.Remove(col); - } - - void AddColliderInternal(ClothProcess cprocess, ColliderComponent col, int index, int arrayIndex, int transformIndex) - { - int teamId = cprocess.TeamId; - - // マネージャへ登録 - teamIdArray[arrayIndex] = (short)teamId; - var flag = new ExBitFlag8(); - flag = DataUtility.SetColliderType(flag, col.GetColliderType()); - flag.SetFlag(Flag_Valid, true); - flag.SetFlag(Flag_Enable, col.isActiveAndEnabled); - flag.SetFlag(Flag_Reset, true); - flagArray[arrayIndex] = flag; - centerArray[arrayIndex] = col.center; - sizeArray[arrayIndex] = col.GetSize(); - var pos = col.transform.position; - var rot = col.transform.rotation; - var scl = col.transform.localScale; - framePositions[arrayIndex] = pos; - frameRotations[arrayIndex] = rot; - frameScales[arrayIndex] = scl; - nowPositions[arrayIndex] = pos; - nowRotations[arrayIndex] = rot; - //nowScales[arrayIndex] = scl; - oldFramePositions[arrayIndex] = pos; - oldFrameRotations[arrayIndex] = rot; - //oldFrameScales[arrayIndex] = scl; - oldPositions[arrayIndex] = pos; - oldRotations[arrayIndex] = rot; - - // チームにコライダーコンポーネントを登録 - cprocess.colliderList[index] = col; - - // コライダーコンポーネント側にも登録する - col.Register(teamId); - - // トランスフォーム登録 - bool t_enable = cprocess.IsEnable && flag.IsSet(Flag_Enable); - var tflag = new ExBitFlag8(TransformManager.Flag_Read); - tflag.SetFlag(TransformManager.Flag_Enable, t_enable); - MagicaManager.Bone.SetTransform(col.transform, tflag, transformIndex, teamId); - - colliderSet.Add(col); } /// @@ -565,19 +708,29 @@ namespace MagicaCloth2 if (tdata.IsValid == false) return; var cprocess = MagicaManager.Team.GetClothProcess(teamId); - int index = cprocess.GetColliderIndex(col); - if (index < 0) - return; - int arrayIndex = tdata.colliderChunk.startIndex + index; - var flag = flagArray[arrayIndex]; - flag.SetFlag(Flag_Enable, sw); - flag.SetFlag(Flag_Reset, true); // Enable/Disableどちらでもリセット - flagArray[arrayIndex] = flag; - // トランスフォーム有効状態 - int transformIndex = tdata.colliderTransformChunk.startIndex + index; - bool t_enable = cprocess.IsEnable && flag.IsSet(Flag_Enable); - MagicaManager.Bone.EnableTransform(transformIndex, t_enable); + if (cprocess.colliderDict.ContainsKey(col) == false) + return; + + // メイン、シンメトリーの2つをチェック + int2 data = cprocess.colliderDict[col]; + for (int i = 0; i < 2; i++) + { + int localIndex = data[i]; + if (i == 1 && localIndex == 0) + continue; // シンメトリーのindex0はデータなし + + int arrayIndex = tdata.colliderChunk.startIndex + localIndex; + var flag = flagArray[arrayIndex]; + flag.SetFlag(Flag_Enable, sw); + flag.SetFlag(Flag_Reset, true); // Enable/Disableどちらでもリセット + flagArray[arrayIndex] = flag; + + // トランスフォーム有効状態 + int transformIndex = tdata.colliderTransformChunk.startIndex + localIndex; + bool t_enable = cprocess.IsEnable && flag.IsSet(Flag_Enable); + MagicaManager.Bone.EnableTransform(transformIndex, t_enable); + } } /// @@ -585,14 +738,14 @@ namespace MagicaCloth2 /// /// /// - internal void EnableTeamCollider(int teamId, bool sw) + internal void EnableTeamCollider(int teamId) { if (IsValid() == false) return; ref var tdata = ref MagicaManager.Team.GetTeamDataRef(teamId); if (tdata.IsValid == false) return; - if (tdata.ColliderCount == 0) + if (tdata.UseColliderCount == 0) return; bool teamEnable = tdata.IsEnable; @@ -604,7 +757,7 @@ namespace MagicaCloth2 // フラグ var flag = flagArray[arrayIndex]; - flag.SetFlag(Flag_Enable, sw); + //flag.SetFlag(Flag_Enable, sw); // コライダーのEnableフラグはコライダー固有のものなので変更する必要はない flag.SetFlag(Flag_Reset, true); // Enable/Disableどちらでもリセット flagArray[arrayIndex] = flag; @@ -616,10 +769,11 @@ namespace MagicaCloth2 /// /// コライダーコンポーネントのパラメータ変更を反映する + /// シンメトリーの変更なども反映させる /// /// /// - internal void UpdateParameters(ColliderComponent col, int teamId) + internal void UpdateParameters(ColliderComponent col, int teamId, bool changeSymmetry) { if (IsValid() == false) return; @@ -628,119 +782,193 @@ namespace MagicaCloth2 if (tdata.IsValid == false) return; var cprocess = MagicaManager.Team.GetClothProcess(teamId); - int index = cprocess.GetColliderIndex(col); - if (index < 0) + if (cprocess.colliderDict.ContainsKey(col) == false) return; - int arrayIndex = tdata.colliderChunk.startIndex + index; + int2 data = cprocess.colliderDict[col]; + // Main + // メインコライダーは変更のみ考える + // メインは削除されることはない。Transformの変更もない。 + int localIndex = data.x; + int arrayIndex = tdata.colliderChunk.startIndex + localIndex; var flag = flagArray[arrayIndex]; flag = DataUtility.SetColliderType(flag, col.GetColliderType()); + flag.SetFlag(Flag_Reverse, col.IsReverseDirection()); flagArray[arrayIndex] = flag; centerArray[arrayIndex] = col.center; sizeArray[arrayIndex] = math.max(col.GetSize(), 0.0001f); // 念のため + + // Symmetry + if (col.ActiveSymmetryMode != ColliderSymmetryMode.None && col.ActiveSymmetryTarget != null) + { + // シンメトリーあり + if (changeSymmetry) + { + // シンメトリーのモードまたはターゲットの変更 + // 一旦削除して再度追加する + RemoveColliderInternal(col, teamId, true); + AddColliderInternal(ref tdata, cprocess, col, true); + //Debug.Log($"remove and add symmetry."); + } + else if (data.y > 0) + { + // シンメトリーのモードおよびターゲットは変更されていない + // パラメータの変更のみ + localIndex = data.y; + arrayIndex = tdata.colliderChunk.startIndex + localIndex; + flag = flagArray[arrayIndex]; + flag = DataUtility.SetColliderType(flag, col.GetColliderType()); + flag.SetFlag(Flag_Reverse, col.IsReverseDirection()); + flagArray[arrayIndex] = flag; + centerArray[arrayIndex] = col.center; + sizeArray[arrayIndex] = math.max(col.GetSize(), 0.0001f); // 念のため + //Debug.Log($"modify symmetry parameter only."); + } + } + else + { + // シンメトリーなし + // 既存のシンメトリーコライダーが存在する場合は削除する + RemoveColliderInternal(col, teamId, true); + //Debug.Log($"remove symmetry."); + } } + //========================================================================================= + // Simulation //========================================================================================= /// /// シミュレーション更新前処理 /// コライダー姿勢の読み取り /// - /// - /// - internal JobHandle PreSimulationUpdate(JobHandle jobHandle) - { - if (DataCount == 0) - return jobHandle; - - var job = new PreSimulationUpdateJob() - { - teamDataArray = MagicaManager.Team.teamDataArray.GetNativeArray(), - centerDataArray = MagicaManager.Team.centerDataArray.GetNativeArray(), - - teamIdArray = teamIdArray.GetNativeArray(), - flagArray = flagArray.GetNativeArray(), - centerArray = centerArray.GetNativeArray(), - framePositions = framePositions.GetNativeArray(), - frameRotations = frameRotations.GetNativeArray(), - frameScales = frameScales.GetNativeArray(), - oldFramePositions = oldFramePositions.GetNativeArray(), - oldFrameRotations = oldFrameRotations.GetNativeArray(), - //oldFrameScales = oldFrameScales.GetNativeArray(), - nowPositions = nowPositions.GetNativeArray(), - nowRotations = nowRotations.GetNativeArray(), - oldPositions = oldPositions.GetNativeArray(), - oldRotations = oldRotations.GetNativeArray(), - - transformPositionArray = MagicaManager.Bone.positionArray.GetNativeArray(), - transformRotationArray = MagicaManager.Bone.rotationArray.GetNativeArray(), - transformScaleArray = MagicaManager.Bone.scaleArray.GetNativeArray(), - }; - jobHandle = job.Schedule(DataCount, 8, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct PreSimulationUpdateJob : IJobParallelFor - { + internal static void SimulationPreUpdate( + DataChunk chunk, // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray centerDataArray; - + ref TeamManager.TeamData tdata, + ref InertiaConstraint.CenterData cdata, // collider - [Unity.Collections.ReadOnly] - public NativeArray teamIdArray; - //[Unity.Collections.ReadOnly] - public NativeArray flagArray; - [Unity.Collections.ReadOnly] - public NativeArray centerArray; - [Unity.Collections.WriteOnly] - public NativeArray framePositions; - [Unity.Collections.WriteOnly] - public NativeArray frameRotations; - [Unity.Collections.WriteOnly] - public NativeArray frameScales; - public NativeArray oldFramePositions; - public NativeArray oldFrameRotations; - //[Unity.Collections.WriteOnly] - //public NativeArray oldFrameScales; - public NativeArray nowPositions; - public NativeArray nowRotations; - public NativeArray oldPositions; - public NativeArray oldRotations; - - // transform (ワールド姿勢) - [Unity.Collections.ReadOnly] - public NativeArray transformPositionArray; - [Unity.Collections.ReadOnly] - public NativeArray transformRotationArray; - [Unity.Collections.ReadOnly] - public NativeArray transformScaleArray; - - public void Execute(int index) + ref NativeArray flagArray, + ref NativeArray centerArray, + ref NativeArray framePositions, + ref NativeArray frameRotations, + ref NativeArray frameScales, + ref NativeArray oldFramePositions, + ref NativeArray oldFrameRotations, + ref NativeArray nowPositions, + ref NativeArray nowRotations, + ref NativeArray oldPositions, + ref NativeArray oldRotations, + ref NativeArray mainColliderIndices, + // transform + ref NativeArray transformPositionArray, + ref NativeArray transformRotationArray, + ref NativeArray transformScaleArray, + ref NativeArray transformLocalPositionArray, + ref NativeArray transformLocalRotationArray, + ref NativeArray transformLocalScaleArray + ) + { + // コライダーごと + //int index = tdata.colliderChunk.startIndex; + int index = tdata.colliderChunk.startIndex + chunk.startIndex; + //for (int i = 0; i < tdata.colliderChunk.dataLength; i++, index++) + for (int i = 0; i < chunk.dataLength; i++, index++) { var flag = flagArray[index]; if (flag.IsSet(Flag_Valid) == false || flag.IsSet(Flag_Enable) == false) - return; - - int teamId = teamIdArray[index]; - var tdata = teamDataArray[teamId]; - if (tdata.IsProcess == false) - return; + continue; var center = centerArray[index]; int l_index = index - tdata.colliderChunk.startIndex; int t_index = tdata.colliderTransformChunk.startIndex + l_index; - // transform姿勢(ワールド) - var wpos = transformPositionArray[t_index]; - var wrot = transformRotationArray[t_index]; - var wscl = transformScaleArray[t_index]; + // ほぼ0スケールは極小スケールに変換し無効化させる + bool isZeroScale = false; + float3 pscl = transformScaleArray[t_index]; + for (int j = 0; j < 3; j++) + { + float s = pscl[j]; + if (s < 1e-06f && s > -1e-06f) + { + pscl[j] = 1e-06f; + isZeroScale = true; + } + } + flag.SetFlag(Flag_ScaleSuspend, isZeroScale); - // オフセット - wpos += math.mul(wrot, center) * wscl; + // コライダー姿勢(ワールド) + float3 wpos; + quaternion wrot; + float3 wscl; + if (flag.IsSet(Flag_Symmetry)) + { + // Symmetry + int mainLocalIndex = mainColliderIndices[index]; + int mainTransformIndex = tdata.colliderTransformChunk.startIndex + mainLocalIndex; + float3 lpos = transformLocalPositionArray[mainTransformIndex]; + float3 lerot = MathUtility.ToEuler(transformLocalRotationArray[mainTransformIndex]); + float3 lscl = transformLocalScaleArray[mainTransformIndex]; + + var symmetryType = DataUtility.GetSymmetryType(flag); + switch (symmetryType) + { + case SymmetryType.X_Symmetry: + lpos.x = -lpos.x; + center.x = -center.x; + lerot.y = -lerot.y; + lerot.z = -lerot.z; + break; + case SymmetryType.Y_Symmetry: + lpos.y = -lpos.y; + center.y = -center.y; + lerot.x = -lerot.x; + lerot.z = -lerot.z; + break; + case SymmetryType.Z_Symmetry: + lpos.z = -lpos.z; + center.z = -center.z; + lerot.x = -lerot.x; + lerot.y = -lerot.y; + break; + case SymmetryType.XYZ_Symmetry: + lpos = -lpos; + center = -center; + break; + } + + // シンメトリー先の親 + float3 ppos = transformPositionArray[t_index]; + quaternion prot = transformRotationArray[t_index]; + //float3 pscl = transformScaleArray[t_index]; + + // マイナススケール + float3 sclSign = math.sign(pscl); + float3 sclEulerSign = 1; + if (pscl.x < 0 || pscl.y < 0 || pscl.z < 0) + sclEulerSign = sclSign * -1; + + // シンメトリーコライダーの姿勢 + wpos = MathUtility.TransformPoint(lpos, ppos, prot, pscl); + wrot = math.mul(prot, quaternion.Euler(math.radians(lerot * sclEulerSign))); + wscl = pscl * lscl; + + // オフセット + wpos += math.mul(wrot, center * sclSign) * wscl * sclSign; + } + else + { + // Main + wpos = transformPositionArray[t_index]; + wrot = transformRotationArray[t_index]; + //wscl = transformScaleArray[t_index]; + wscl = pscl; + + // マイナススケール + float3 sclSign = math.sign(wscl); + + // オフセット + wpos += math.mul(wrot, center * sclSign) * wscl * sclSign; + } // 格納 framePositions[index] = wpos; @@ -748,195 +976,104 @@ namespace MagicaCloth2 frameScales[index] = wscl; // リセット処理 - if (tdata.IsReset || flag.IsSet(Flag_Reset)) + if (tdata.IsReset || flag.IsSet(Flag_Reset) || isZeroScale) { oldFramePositions[index] = wpos; oldFrameRotations[index] = wrot; - //oldFrameScales[index] = lscl; nowPositions[index] = wpos; nowRotations[index] = wrot; oldPositions[index] = wpos; oldRotations[index] = wrot; flag.SetFlag(Flag_Reset, false); - flagArray[index] = flag; } - else if (tdata.IsInertiaShift) + else if (tdata.IsInertiaShift || tdata.IsNegativeScaleTeleport) { // 慣性全体シフト - var cdata = centerDataArray[teamId]; + var oldFramePosition = oldFramePositions[index]; + var oldFrameRotation = oldFrameRotations[index]; + var nowPosition = nowPositions[index]; + var nowRotation = nowRotations[index]; + var oldPosition = oldPositions[index]; + var oldRotation = oldRotations[index]; - // cdata.frameComponentShiftVector : 全体シフトベクトル - // cdata.frameComponentShiftRotation : 全体シフト回転 - // cdata.oldComponentWorldPosition : フレーム移動前のコンポーネント中心位置 - - float3 prevFrameWorldPosition = cdata.oldComponentWorldPosition; - - oldFramePositions[index] = MathUtility.ShiftPosition(oldFramePositions[index], prevFrameWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); - oldFrameRotations[index] = math.mul(cdata.frameComponentShiftRotation, oldFrameRotations[index]); - - nowPositions[index] = MathUtility.ShiftPosition(nowPositions[index], prevFrameWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); - nowRotations[index] = math.mul(cdata.frameComponentShiftRotation, nowRotations[index]); - - oldPositions[index] = MathUtility.ShiftPosition(oldPositions[index], prevFrameWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); - oldRotations[index] = math.mul(cdata.frameComponentShiftRotation, oldRotations[index]); - } - } - } - - - /// - /// 今回のシミュレーションステップで計算が必要なコライダーリストを作成する - /// - /// - /// - /// - internal JobHandle CreateUpdateColliderList(int updateIndex, JobHandle jobHandle) - { - var sm = MagicaManager.Simulation; - var tm = MagicaManager.Team; - - var job = new CreateUpdatecolliderListJob() - { - updateIndex = updateIndex, - teamDataArray = tm.teamDataArray.GetNativeArray(), - - jobColliderCounter = sm.processingStepCollider.Counter, - jobColliderIndexList = sm.processingStepCollider.Buffer, - }; - jobHandle = job.Schedule(tm.TeamCount, 1, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct CreateUpdatecolliderListJob : IJobParallelFor - { - public int updateIndex; - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference jobColliderCounter; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray jobColliderIndexList; - - public void Execute(int teamId) - { - var tdata = teamDataArray[teamId]; - if (tdata.IsProcess == false) - return; - - // このステップでの更新があるか判定する - if (updateIndex >= tdata.updateCount) - return; - - // このチームが参照するコライダーを登録する - if (tdata.ColliderCount > 0) - { - int start = jobColliderCounter.InterlockedStartIndex(tdata.ColliderCount); - for (int j = 0; j < tdata.ColliderCount; j++) + // マイナススケール + if (tdata.IsNegativeScaleTeleport) { - int index = tdata.colliderChunk.startIndex + j; - jobColliderIndexList[start + j] = index; + // 本体のスケール反転に合わせてシミュレーションに影響が出ないように必要な座標系を同様に軸反転させる + // コライダーはセンター空間で反転させる + // 回転に関してはパーティクルとは異なり法線接線をスケール方向により反転させて組み直す + + // センター空間軸反転用マトリックス + float4x4 negativeM = cdata.negativeScaleMatrix; + + oldFramePosition = MathUtility.TransformPoint(oldFramePosition, negativeM); + oldFrameRotation = MathUtility.TransformRotation(oldFrameRotation, negativeM, tdata.negativeScaleChange); + + nowPosition = MathUtility.TransformPoint(nowPosition, negativeM); + nowRotation = MathUtility.TransformRotation(nowRotation, negativeM, tdata.negativeScaleChange); + + oldPosition = MathUtility.TransformPoint(oldPosition, negativeM); + oldRotation = MathUtility.TransformRotation(oldRotation, negativeM, tdata.negativeScaleChange); } + + if (tdata.IsInertiaShift) + { + // cdata.frameComponentShiftVector : 全体シフトベクトル + // cdata.frameComponentShiftRotation : 全体シフト回転 + // cdata.oldComponentWorldPosition : フレーム移動前のコンポーネント中心位置 + + float3 prevFrameWorldPosition = cdata.oldComponentWorldPosition; + + oldFramePosition = MathUtility.ShiftPosition(oldFramePosition, prevFrameWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); + oldFrameRotation = math.mul(cdata.frameComponentShiftRotation, oldFrameRotation); + + nowPosition = MathUtility.ShiftPosition(nowPosition, prevFrameWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); + nowRotation = math.mul(cdata.frameComponentShiftRotation, nowRotation); + + oldPosition = MathUtility.ShiftPosition(oldPosition, prevFrameWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); + oldRotation = math.mul(cdata.frameComponentShiftRotation, oldRotation); + } + + oldFramePositions[index] = oldFramePosition; + oldFrameRotations[index] = oldFrameRotation; + nowPositions[index] = nowPosition; + nowRotations[index] = nowRotation; + oldPositions[index] = oldPosition; + oldRotations[index] = oldRotation; } + + // フラグ書き戻し + flagArray[index] = flag; } } - /// - /// シミュレーションステップ前処理 - /// コライダーの更新および作業データ作成 - /// - /// - /// - internal unsafe JobHandle StartSimulationStep(JobHandle jobHandle) - { - var tm = MagicaManager.Team; - var sm = MagicaManager.Simulation; - - var job = new StartSimulationStepJob() - { - jobColliderIndexList = sm.processingStepCollider.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - centerDataArray = tm.centerDataArray.GetNativeArray(), - - teamIdArray = teamIdArray.GetNativeArray(), - flagArray = flagArray.GetNativeArray(), - sizeArray = sizeArray.GetNativeArray(), - framePositions = framePositions.GetNativeArray(), - frameRotations = frameRotations.GetNativeArray(), - frameScales = frameScales.GetNativeArray(), - oldFramePositions = oldFramePositions.GetNativeArray(), - oldFrameRotations = oldFrameRotations.GetNativeArray(), - nowPositions = nowPositions.GetNativeArray(), - nowRotations = nowRotations.GetNativeArray(), - oldPositions = oldPositions.GetNativeArray(), - oldRotations = oldRotations.GetNativeArray(), - workDataArray = workDataArray.GetNativeArray(), - }; - jobHandle = job.Schedule(sm.processingStepCollider.GetJobSchedulePtr(), 8, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct StartSimulationStepJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray jobColliderIndexList; - + internal static void SimulationStartStep( // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray centerDataArray; - + ref TeamManager.TeamData tdata, + ref InertiaConstraint.CenterData cdata, // collider - [Unity.Collections.ReadOnly] - public NativeArray teamIdArray; - [Unity.Collections.ReadOnly] - public NativeArray flagArray; - [Unity.Collections.ReadOnly] - public NativeArray sizeArray; - [Unity.Collections.ReadOnly] - public NativeArray framePositions; - [Unity.Collections.ReadOnly] - public NativeArray frameRotations; - [Unity.Collections.ReadOnly] - public NativeArray frameScales; - [Unity.Collections.ReadOnly] - public NativeArray oldFramePositions; - [Unity.Collections.ReadOnly] - public NativeArray oldFrameRotations; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray nowPositions; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray nowRotations; - [NativeDisableParallelForRestriction] - //[Unity.Collections.ReadOnly] - public NativeArray oldPositions; - [NativeDisableParallelForRestriction] - //[Unity.Collections.ReadOnly] - public NativeArray oldRotations; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray workDataArray; - - public void Execute(int index) + ref NativeArray flagArray, + ref NativeArray sizeArray, + ref NativeArray framePositions, + ref NativeArray frameRotations, + ref NativeArray frameScales, + ref NativeArray oldFramePositions, + ref NativeArray oldFrameRotations, + ref NativeArray nowPositions, + ref NativeArray nowRotations, + ref NativeArray oldPositions, + ref NativeArray oldRotations, + ref NativeArray workDataArray + ) + { + // コライダーごと + int cindex = tdata.colliderChunk.startIndex; + for (int i = 0; i < tdata.colliderChunk.dataLength; i++, cindex++) { - // ここでのコライダーは有効であることが保証されている - int cindex = jobColliderIndexList[index]; var flag = flagArray[cindex]; - if (flag.IsSet(Flag_Valid) == false || flag.IsSet(Flag_Enable) == false) - return; - int teamId = teamIdArray[cindex]; - var tdata = teamDataArray[teamId]; + if (flag.IsSet(Flag_Valid) == false || flag.IsSet(Flag_Enable) == false || flag.IsSet(Flag_ScaleSuspend)) + continue; // 今回のシミュレーションステップでの姿勢を求める float3 pos = math.lerp(oldFramePositions[cindex], framePositions[cindex], tdata.frameInterpolation); @@ -952,7 +1089,6 @@ namespace MagicaCloth2 var oldrot = oldRotations[cindex]; // ローカル慣性シフト - var cdata = centerDataArray[teamId]; oldpos = math.lerp(oldpos, pos, cdata.stepMoveInertiaRatio); oldrot = math.slerp(oldrot, rot, cdata.stepRotationInertiaRatio); oldPositions[cindex] = oldpos; @@ -993,7 +1129,20 @@ namespace MagicaCloth2 : math.forward(); // スケール - float scl = math.dot(math.abs(cscl), dir); // dirの軸のスケールを使用する + //float scl = math.dot(math.abs(cscl), dir); // dirの軸のスケールを使用する + + // マイナススケール + float scl0 = math.dot(cscl, dir); // dirの軸のスケールを使用する + dir *= math.sign(scl0); // 方向反転 + float scl = math.abs(scl0); + + // 逆方向 + if (flag.IsSet(Flag_Reverse)) + dir = -dir; + + // シンメトリーによる方向性 + if (flag.IsSet(Flag_Symmetry) && flag.IsSet(Flag_SymmetryReverse)) + dir = -dir; // x = 始点半径 // y = 終点半径 @@ -1002,9 +1151,9 @@ namespace MagicaCloth2 float sr = csize.x; float er = csize.y; + float length = csize.z; // 長さ - float length = csize.z; float slen = alignedCenter ? length * 0.5f : 0.0f; float elen = alignedCenter ? length * 0.5f : (length - sr); slen = math.max(slen - sr, 0.0f); @@ -1032,7 +1181,15 @@ namespace MagicaCloth2 else if (type == ColliderType.Plane) { // 押し出し法線方向をoldposに格納する - float3 n = math.mul(rot, math.up()); + // マイナススケール + float3 dir = math.up(); + dir *= math.sign(cscl.y); // Y反転時は逆にする + + // シンメトリーによる方向性 + if (flag.IsSet(Flag_Symmetry) && flag.IsSet(Flag_SymmetryReverse)) + dir = -dir; + + float3 n = math.mul(rot, dir); work.oldPos.c0 = n; work.nextPos.c0 = pos; } @@ -1045,120 +1202,52 @@ namespace MagicaCloth2 /// シミュレーションステップ後処理 /// old姿勢の格納 /// - /// - /// - internal unsafe JobHandle EndSimulationStep(JobHandle jobHandle) - { - var sm = MagicaManager.Simulation; - - var job = new EndSimulationStepJob() - { - jobColliderIndexList = sm.processingStepCollider.Buffer, - - nowPositions = nowPositions.GetNativeArray(), - nowRotations = nowRotations.GetNativeArray(), - oldPositions = oldPositions.GetNativeArray(), - oldRotations = oldRotations.GetNativeArray(), - }; - jobHandle = job.Schedule(sm.processingStepCollider.GetJobSchedulePtr(), 8, jobHandle); - - return jobHandle; - } - - - [BurstCompile] - struct EndSimulationStepJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray jobColliderIndexList; - + internal static void SimulationEndStep( + DataChunk chunk, + // team + ref TeamManager.TeamData tdata, // collider - [Unity.Collections.ReadOnly] - public NativeArray nowPositions; - [Unity.Collections.ReadOnly] - public NativeArray nowRotations; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray oldPositions; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray oldRotations; - - public void Execute(int index) + ref NativeArray nowPositions, + ref NativeArray nowRotations, + ref NativeArray oldPositions, + ref NativeArray oldRotations + ) + { + //int cindex = tdata.colliderChunk.startIndex; + int cindex = tdata.colliderChunk.startIndex + chunk.startIndex; + //for (int i = 0; i < tdata.colliderChunk.dataLength; i++, cindex++) + for (int i = 0; i < chunk.dataLength; i++, cindex++) { - // ここでのコライダーは有効であることが保証されている - int cindex = jobColliderIndexList[index]; - oldPositions[cindex] = nowPositions[cindex]; oldRotations[cindex] = nowRotations[cindex]; } } - /// /// シミュレーション更新後処理 /// - /// - /// - internal JobHandle PostSimulationUpdate(JobHandle jobHandle) - { - if (DataCount == 0) - return jobHandle; - - var job = new PostSimulationUpdateJob() - { - teamDataArray = MagicaManager.Team.teamDataArray.GetNativeArray(), - - teamIdArray = teamIdArray.GetNativeArray(), - framePositions = framePositions.GetNativeArray(), - frameRotations = frameRotations.GetNativeArray(), - //frameScales = frameScales.GetNativeArray(), - oldFramePositions = oldFramePositions.GetNativeArray(), - oldFrameRotations = oldFrameRotations.GetNativeArray(), - //oldFrameScales = oldFrameScales.GetNativeArray(), - }; - jobHandle = job.Schedule(DataCount, 8, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct PostSimulationUpdateJob : IJobParallelFor - { + internal static void SimulationPostUpdate( // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - + ref TeamManager.TeamData tdata, // collider - [Unity.Collections.ReadOnly] - public NativeArray teamIdArray; - [Unity.Collections.ReadOnly] - public NativeArray framePositions; - [Unity.Collections.ReadOnly] - public NativeArray frameRotations; - //[Unity.Collections.ReadOnly] - //public NativeArray frameScales; - [Unity.Collections.WriteOnly] - public NativeArray oldFramePositions; - [Unity.Collections.WriteOnly] - public NativeArray oldFrameRotations; - //[Unity.Collections.WriteOnly] - //public NativeArray oldFrameScales; + ref NativeArray framePositions, + ref NativeArray frameRotations, + ref NativeArray oldFramePositions, + ref NativeArray oldFrameRotations + ) + { + if (tdata.colliderCount == 0) + return; + if (tdata.IsRunning == false) + return; - public void Execute(int index) + int cindex = tdata.colliderChunk.startIndex; + for (int k = 0; k < tdata.colliderChunk.dataLength; k++, cindex++) { - int teamId = teamIdArray[index]; - var tdata = teamDataArray[teamId]; - if (tdata.IsProcess == false) - return; + // コライダー履歴更新 + oldFramePositions[cindex] = framePositions[cindex]; + oldFrameRotations[cindex] = frameRotations[cindex]; - if (tdata.IsRunning) - { - // コライダー履歴更新 - oldFramePositions[index] = framePositions[index]; - oldFrameRotations[index] = frameRotations[index]; - //oldFrameScales[index] = frameScales[index]; - } } } @@ -1173,7 +1262,9 @@ namespace MagicaCloth2 } else { - sb.AppendLine($"Collider Manager. Collider:{colliderSet.Count}"); + int cnt = teamIdArray?.Count ?? 0; + + sb.AppendLine($"Use:{cnt}"); sb.AppendLine($" -flagArray:{flagArray.ToSummary()}"); sb.AppendLine($" -centerArray:{centerArray.ToSummary()}"); sb.AppendLine($" -sizeArray:{sizeArray.ToSummary()}"); @@ -1186,23 +1277,36 @@ namespace MagicaCloth2 sb.AppendLine($" -nowRotations:{nowRotations.ToSummary()}"); sb.AppendLine($" -oldPositions:{oldPositions.ToSummary()}"); sb.AppendLine($" -oldRotations:{oldRotations.ToSummary()}"); + sb.AppendLine($" -mainColliderIndices:{mainColliderIndices.ToSummary()}"); sb.AppendLine($"[Colliders]"); - int cnt = teamIdArray?.Count ?? 0; + int useCnt = 0; for (int i = 0; i < cnt; i++) { var flag = flagArray[i]; if (flag.IsSet(Flag_Valid) == false) continue; + useCnt++; var ctype = DataUtility.GetColliderType(flag); - sb.AppendLine($" [{i}] tid:{teamIdArray[i]}, flag:0x{flag.Value:X}, type:{ctype}, size:{sizeArray[i]}, cen:{centerArray[i]}"); + string sym = flag.IsSet(Flag_Symmetry) ? "Symmetry" : ""; + sb.AppendLine($" [{i}] tid:{teamIdArray[i]}, flag:0x{flag.Value:X}, type:{ctype}, size:{sizeArray[i]}, cen:{centerArray[i]}, {sym}"); } + sb.AppendLine($" ActiveCount:{useCnt}"); - sb.AppendLine($"[Collider Names]"); + sb.AppendLine($"[Collider Components:{colliderSet.Count}]"); foreach (var col in colliderSet) { - var name = col?.name ?? "(null)"; - sb.AppendLine($" {name}"); + if (col) + { + sb.Append($"({col.UseTeamCount}) {col.name}"); + if (col.ActiveSymmetryMode != ColliderSymmetryMode.None) + { + sb.Append($" Symmetry:{col.ActiveSymmetryMode}"); + } + sb.AppendLine(); + } + else + sb.AppendLine($" (null!)"); } } sb.AppendLine(); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/ColliderManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/ColliderManager.cs.meta index e6b939d9..a0779118 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/ColliderManager.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/ColliderManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/ColliderManager.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManager.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManager.cs index bfa46330..fae77a9f 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManager.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManager.cs @@ -2,16 +2,14 @@ // Copyright (c) 2023 MagicaSoft. // https://magicasoft.jp using System.Text; -using Unity.Burst; using Unity.Collections; -using Unity.Collections.LowLevel.Unsafe; using Unity.Jobs; using Unity.Mathematics; using UnityEngine; namespace MagicaCloth2 { - public class SimulationManager : IManager, IValid + public partial class SimulationManager : IManager, IValid { /// /// チームID @@ -90,13 +88,6 @@ namespace MagicaCloth2 /// public ExNativeArray collisionNormalArray; - /// - /// 接触中コライダーID - /// 接触コライダーID+1が格納されているので注意!(0=なし) - /// todo:現在未使用! - /// - //public ExNativeArray colliderIdArray; - public int ParticleCount => nextPosArray?.Count ?? 0; //========================================================================================= @@ -113,38 +104,6 @@ namespace MagicaCloth2 public SelfCollisionConstraint selfCollisionConstraint; //========================================================================================= - /// - /// フレームもしくはステップごとに変動するリストを管理するための汎用バッファ。用途は様々 - /// - internal ExProcessingList processingStepParticle; - internal ExProcessingList processingStepTriangleBending; - internal ExProcessingList processingStepEdgeCollision; - internal ExProcessingList processingStepCollider; - internal ExProcessingList processingStepBaseLine; - //internal ExProcessingList processingIntList5; - internal ExProcessingList processingStepMotionParticle; - - internal ExProcessingList processingSelfParticle; - internal ExProcessingList processingSelfPointTriangle; - internal ExProcessingList processingSelfEdgeEdge; - internal ExProcessingList processingSelfTrianglePoint; - - //--------------------------------------------------------------------- - /// - /// 汎用float3作業バッファ - /// - internal NativeArray tempFloat3Buffer; - - /// - /// パーティクルごとのfloat3集計カウンタ(排他制御用) - /// - internal NativeArray countArray; - - /// - /// パーティクルごとのfloat3蓄積リスト、内部は固定小数点。パーティクル数x3。(排他制御用) - /// - internal NativeArray sumArray; - /// /// ステップごとのシミュレーションの基準となる姿勢座標 /// 初期姿勢とアニメーション姿勢をAnimatinBlendRatioで補間したもの @@ -157,6 +116,16 @@ namespace MagicaCloth2 /// public NativeArray stepBasicRotationBuffer; + /// + /// 作業用バッファ + /// + internal NativeArray tempVectorBufferA; + internal NativeArray tempVectorBufferB; + internal NativeArray tempCountBuffer; + internal NativeArray tempFloatBufferA; + internal NativeArray tempRotationBufferA; + internal NativeArray tempRotationBufferB; + /// /// ステップ実行カウンター /// @@ -167,6 +136,11 @@ namespace MagicaCloth2 /// internal int WorkerCount => Unity.Jobs.LowLevel.Unsafe.JobsUtility.JobWorkerCount; + /// + /// 分割ジョブを適用するプロキシメッシュの頂点数 + /// + internal int splitProxyMeshVertexCount = Define.System.SplitProxyMeshVertexCount; + bool isValid = false; //========================================================================================= @@ -189,7 +163,6 @@ namespace MagicaCloth2 frictionArray?.Dispose(); staticFrictionArray?.Dispose(); collisionNormalArray?.Dispose(); - //colliderIdArray?.Dispose(); teamIdArray = null; nextPosArray = null; @@ -206,30 +179,23 @@ namespace MagicaCloth2 frictionArray = null; staticFrictionArray = null; collisionNormalArray = null; - //colliderIdArray = null; - processingStepParticle?.Dispose(); - processingStepTriangleBending?.Dispose(); - processingStepEdgeCollision?.Dispose(); - processingStepCollider?.Dispose(); - processingStepBaseLine?.Dispose(); - //processingIntList5?.Dispose(); - processingStepMotionParticle?.Dispose(); - processingSelfParticle?.Dispose(); - processingSelfPointTriangle?.Dispose(); - processingSelfEdgeEdge?.Dispose(); - processingSelfTrianglePoint?.Dispose(); - - if (tempFloat3Buffer.IsCreated) - tempFloat3Buffer.Dispose(); - if (countArray.IsCreated) - countArray.Dispose(); - if (sumArray.IsCreated) - sumArray.Dispose(); if (stepBasicPositionBuffer.IsCreated) stepBasicPositionBuffer.Dispose(); if (stepBasicRotationBuffer.IsCreated) stepBasicRotationBuffer.Dispose(); + if (tempVectorBufferA.IsCreated) + tempVectorBufferA.Dispose(); + if (tempVectorBufferB.IsCreated) + tempVectorBufferB.Dispose(); + if (tempCountBuffer.IsCreated) + tempCountBuffer.Dispose(); + if (tempFloatBufferA.IsCreated) + tempFloatBufferA.Dispose(); + if (tempRotationBufferA.IsCreated) + tempRotationBufferA.Dispose(); + if (tempRotationBufferB.IsCreated) + tempRotationBufferB.Dispose(); distanceConstraint?.Dispose(); bendingConstraint?.Dispose(); @@ -274,21 +240,6 @@ namespace MagicaCloth2 frictionArray = new ExNativeArray(capacity); staticFrictionArray = new ExNativeArray(capacity); collisionNormalArray = new ExNativeArray(capacity); - //colliderIdArray = new ExNativeArray(capacity); - - processingStepParticle = new ExProcessingList(); - processingStepTriangleBending = new ExProcessingList(); - processingStepEdgeCollision = new ExProcessingList(); - processingStepCollider = new ExProcessingList(); - processingStepBaseLine = new ExProcessingList(); - //processingIntList5 = new ExProcessingList(); - processingStepMotionParticle = new ExProcessingList(); - processingSelfParticle = new ExProcessingList(); - processingSelfPointTriangle = new ExProcessingList(); - processingSelfEdgeEdge = new ExProcessingList(); - processingSelfTrianglePoint = new ExProcessingList(); - - tempFloat3Buffer = new NativeArray(capacity, Allocator.Persistent); // 制約 distanceConstraint = new DistanceConstraint(); @@ -323,7 +274,7 @@ namespace MagicaCloth2 return; int teamId = cprocess.TeamId; - var proxyMesh = cprocess.ProxyMesh; + var proxyMesh = cprocess.ProxyMeshContainer.shareVirtualMesh; ref var tdata = ref MagicaManager.Team.GetTeamDataRef(teamId); int pcnt = proxyMesh.VertexCount; @@ -342,7 +293,6 @@ namespace MagicaCloth2 frictionArray.AddRange(pcnt); staticFrictionArray.AddRange(pcnt); collisionNormalArray.AddRange(pcnt); - //colliderIdArray.AddRange(pcnt); } /// @@ -395,7 +345,6 @@ namespace MagicaCloth2 frictionArray.Remove(c); staticFrictionArray.Remove(c); collisionNormalArray.Remove(c); - //colliderIdArray.Remove(c); tdata.particleChunk.Clear(); @@ -413,1576 +362,1050 @@ namespace MagicaCloth2 internal void WorkBufferUpdate() { int pcnt = ParticleCount; - //int ecnt = MagicaManager.VMesh.EdgeCount; - //int tcnt = MagicaManager.VMesh.TriangleCount; - int bcnt = MagicaManager.VMesh.BaseLineCount; - int ccnt = MagicaManager.Collider.DataCount; - int bendCnt = bendingConstraint.DataCount; - - // ステップ処理パーティクル全般 - processingStepParticle.UpdateBuffer(pcnt); - - // ステップ処理トライアングルベンド - processingStepTriangleBending.UpdateBuffer(bendCnt); - - // ステップ処理コリジョン用エッジ - int edgeColliderCount = MagicaManager.Team.edgeColliderCollisionCount; - processingStepEdgeCollision.UpdateBuffer(edgeColliderCount); - - // 処理コライダー - processingStepCollider.UpdateBuffer(ccnt); - - // ステップ処理ベースライン - processingStepBaseLine.UpdateBuffer(bcnt); - - // ステップ処理セルフコリジョンパーティクル - //processingIntList5.UpdateBuffer(pcnt); - - // ステップ実行モーション制約パーティクル - processingStepMotionParticle.UpdateBuffer(pcnt); - - // セルフコリジョン - processingSelfParticle.UpdateBuffer(pcnt); - processingSelfPointTriangle.UpdateBuffer(selfCollisionConstraint.PointPrimitiveCount); - processingSelfEdgeEdge.UpdateBuffer(selfCollisionConstraint.EdgePrimitiveCount); - processingSelfTrianglePoint.UpdateBuffer(selfCollisionConstraint.TrianglePrimitiveCount); // 汎用作業バッファ - tempFloat3Buffer.Resize(pcnt); - stepBasicPositionBuffer.Resize(pcnt); - stepBasicRotationBuffer.Resize(pcnt); + // 拡張時には0クリアされる + stepBasicPositionBuffer.MC2Resize(pcnt); + stepBasicRotationBuffer.MC2Resize(pcnt); - // 加算バッファ - countArray.Resize(pcnt); - sumArray.Resize(pcnt * 3); + // 汎用バッファ + // 拡張時には0クリアされる + tempVectorBufferA.MC2Resize(pcnt); + tempVectorBufferB.MC2Resize(pcnt); + tempCountBuffer.MC2Resize(pcnt); + tempFloatBufferA.MC2Resize(pcnt); + tempRotationBufferA.MC2Resize(pcnt); + tempRotationBufferB.MC2Resize(pcnt); // 制約 - angleConstraint.WorkBufferUpdate(); - colliderCollisionConstraint.WorkBufferUpdate(); selfCollisionConstraint.WorkBufferUpdate(); } //========================================================================================= - /// - /// シミュレーション実行前処理 - /// -リセット - /// -移動影響 - /// - /// - /// - internal JobHandle PreSimulationUpdate(JobHandle jobHandle) - { - // パーティクルのリセットおよび慣性の適用 - var job = new PreSimulationUpdateJob() - { - teamDataArray = MagicaManager.Team.teamDataArray.GetNativeArray(), - parameterArray = MagicaManager.Team.parameterArray.GetNativeArray(), - centerDataArray = MagicaManager.Team.centerDataArray.GetNativeArray(), - - positions = MagicaManager.VMesh.positions.GetNativeArray(), - rotations = MagicaManager.VMesh.rotations.GetNativeArray(), - vertexDepths = MagicaManager.VMesh.vertexDepths.GetNativeArray(), - - teamIdArray = teamIdArray.GetNativeArray(), - nextPosArray = nextPosArray.GetNativeArray(), - oldPosArray = oldPosArray.GetNativeArray(), - oldRotArray = oldRotArray.GetNativeArray(), - basePosArray = basePosArray.GetNativeArray(), - baseRotArray = baseRotArray.GetNativeArray(), - oldPositionArray = oldPositionArray.GetNativeArray(), - oldRotationArray = oldRotationArray.GetNativeArray(), - velocityPosArray = velocityPosArray.GetNativeArray(), - dispPosArray = dispPosArray.GetNativeArray(), - velocityArray = velocityArray.GetNativeArray(), - realVelocityArray = realVelocityArray.GetNativeArray(), - frictionArray = frictionArray.GetNativeArray(), - staticFrictionArray = staticFrictionArray.GetNativeArray(), - collisionNormalArray = collisionNormalArray.GetNativeArray(), - //colliderIdArray = colliderIdArray.GetNativeArray(), - }; - jobHandle = job.Schedule(ParticleCount, 32, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct PreSimulationUpdateJob : IJobParallelFor - { - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - [Unity.Collections.ReadOnly] - public NativeArray centerDataArray; - - // vmesh - [Unity.Collections.ReadOnly] - public NativeArray positions; - [Unity.Collections.ReadOnly] - public NativeArray rotations; - [Unity.Collections.ReadOnly] - public NativeArray vertexDepths; - - // particle - [Unity.Collections.ReadOnly] - public NativeArray teamIdArray; - [Unity.Collections.WriteOnly] - public NativeArray nextPosArray; - public NativeArray oldPosArray; - public NativeArray oldRotArray; - [Unity.Collections.WriteOnly] - public NativeArray basePosArray; - [Unity.Collections.WriteOnly] - public NativeArray baseRotArray; - public NativeArray oldPositionArray; - public NativeArray oldRotationArray; - [Unity.Collections.WriteOnly] - public NativeArray velocityPosArray; - public NativeArray dispPosArray; - [Unity.Collections.WriteOnly] - public NativeArray velocityArray; - public NativeArray realVelocityArray; - [Unity.Collections.WriteOnly] - public NativeArray frictionArray; - [Unity.Collections.WriteOnly] - public NativeArray staticFrictionArray; - [Unity.Collections.WriteOnly] - public NativeArray collisionNormalArray; - //[Unity.Collections.WriteOnly] - //public NativeArray colliderIdArray; - - // パーティクルごと - public void Execute(int pindex) - { - int teamId = teamIdArray[pindex]; - if (teamId == 0) - return; - - var tdata = teamDataArray[teamId]; - if (tdata.IsProcess == false) - return; - - int l_index = pindex - tdata.particleChunk.startIndex; - int vindex = tdata.proxyCommonChunk.startIndex + l_index; - - if (tdata.IsReset) - { - // リセット - 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; - //colliderIdArray[pindex] = 0; - } - else if (tdata.IsInertiaShift) - { - // 慣性全体シフト - var cdata = centerDataArray[teamId]; - - // cdata.frameComponentShiftVector : 全体シフトベクトル - // cdata.frameComponentShiftRotation : 全体シフト回転 - // cdata.oldComponentWorldPosition : フレーム移動前のコンポーネント中心位置 - - float3 prevFrameWorldPosition = cdata.oldComponentWorldPosition; - - oldPosArray[pindex] = MathUtility.ShiftPosition(oldPosArray[pindex], prevFrameWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); - oldRotArray[pindex] = math.mul(cdata.frameComponentShiftRotation, oldRotArray[pindex]); - - oldPositionArray[pindex] = MathUtility.ShiftPosition(oldPositionArray[pindex], prevFrameWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); - oldRotationArray[pindex] = math.mul(cdata.frameComponentShiftRotation, oldRotationArray[pindex]); - - dispPosArray[pindex] = MathUtility.ShiftPosition(dispPosArray[pindex], prevFrameWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); - - realVelocityArray[pindex] = math.mul(cdata.frameComponentShiftRotation, realVelocityArray[pindex]); - } - } - } - + // Simulation //========================================================================================= /// - /// クロスシミュレーションの1ステップ実行 + /// シミュレーションメインスケジュール /// - /// - /// - /// /// /// - unsafe internal JobHandle SimulationStepUpdate(int updateCount, int updateIndex, JobHandle jobHandle) + internal JobHandle ClothSimulationSchedule(JobHandle jobHandle) { - //Debug.Log($"Step:{updateIndex}/{updateCount}"); - var tm = MagicaManager.Team; + var bm = MagicaManager.Bone; var vm = MagicaManager.VMesh; var wm = MagicaManager.Wind; + var cm = MagicaManager.Collider; + var tim = MagicaManager.Time; - // シミュレーションステップカウンター - SimulationStepCount++; + int normalClothTeamCount = tm.batchNormalClothTeamList.Length; + int splitClothTeamCount = tm.batchSplitClothTeamList.Length; + bool useNormalClothJob = normalClothTeamCount > 0; + bool useSplitClothJob = splitClothTeamCount > 0; - // ステップごとのチーム更新 - jobHandle = tm.SimulationStepTeamUpdate(updateIndex, jobHandle); + if (useNormalClothJob == false && useSplitClothJob == false) + return jobHandle; - // 今回のステップで計算が必要な作業リストを作成する - var clearStepCounterJob = new ClearStepCounter() + // 最大更新回数 + int maxUpdateCount = tm.TeamMaxUpdateCount; + //Debug.Log($"TeamMaxUpdateCount:{tm.TeamMaxUpdateCount}, UseSelfPointCollision:{tm.UseSelfPointCollision}, UseSelfEdgeCollision:{tm.UseSelfEdgeCollision}"); + + // 利用できるワーカースレッド数 + int workerCount = math.max(WorkerCount, 1); + workerCount *= 5; // 更に分割:テスト結果より + //Debug.Log($"workerCount:{workerCount}"); + + // ジョブ連結用 + JobHandle normalClothJobHandle = new JobHandle(); + JobHandle splitClothJobHandle = new JobHandle(); + JobHandle selfIntersectJobHandle = new JobHandle(); + JobHandle solverIntersectJobHandle = new JobHandle(); + + // ■分割シミュレーションジョブ + // セルフコリジョンあり、もしくはプロキシメッシュの頂点数が一定値以上のジョブ + // オリジナルと同様にジョブを分割し同期しながら実行する + // ただし最適化を行いオリジナルより軽量化している + if (useSplitClothJob) { - processingStepParticle = processingStepParticle.Counter, // ステップ実行パーティクル - processingStepTriangleBending = processingStepTriangleBending.Counter, // ステップ実行トライアングルベンド - processingStepEdgeCollision = processingStepEdgeCollision.Counter, // ステップ実行エッジコリジョン - processingStepCollider = processingStepCollider.Counter, // ステップ実行コライダーリスト - processingStepBaseLine = processingStepBaseLine.Counter, // ステップ実行ベースライン - //processingCounter5 = processingIntList5.Counter, // (reserve) - processingStepMotionParticle = processingStepMotionParticle.Counter, // ステップ実行モーション制約パーティクル + // コンタクトキューとリスト + selfCollisionConstraint.contactQueue.Clear(); + selfCollisionConstraint.contactList.Clear(); + selfCollisionConstraint.intersectQueue.Clear(); + selfCollisionConstraint.intersectList.Clear(); - processingSelfParticle = processingSelfParticle.Counter, - processingSelfPointTriangle = processingSelfPointTriangle.Counter, - processingSelfEdgeEdge = processingSelfEdgeEdge.Counter, - processingSelfTrianglePoint = processingSelfTrianglePoint.Counter, - }; - jobHandle = clearStepCounterJob.Schedule(jobHandle); + // 分割ジョブ内での各種コリジョンの有無 + bool useEdgeCollision = tm.teamStatus.Value.z > 0; + bool useSelfCollision = tm.teamStatus.Value.w > 0; - var createUpdateParticleJob = new CreateUpdateParticleList() - { - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), + // セルフコリジョンのインターセクト解決 + bool useIntersect = selfCollisionConstraint.IntersectCount > 0; - stepParticleIndexCounter = processingStepParticle.Counter, - stepParticleIndexArray = processingStepParticle.Buffer, - - stepBaseLineIndexCounter = processingStepBaseLine.Counter, - stepBaseLineIndexArray = processingStepBaseLine.Buffer, - - stepTriangleBendIndexCounter = processingStepTriangleBending.Counter, - stepTriangleBendIndexArray = processingStepTriangleBending.Buffer, - - stepEdgeCollisionIndexCounter = processingStepEdgeCollision.Counter, - stepEdgeCollisionIndexArray = processingStepEdgeCollision.Buffer, - - motionParticleIndexCounter = processingStepMotionParticle.Counter, - motionParticleIndexArray = processingStepMotionParticle.Buffer, - - selfParticleCounter = processingSelfParticle.Counter, - selfParticleIndexArray = processingSelfParticle.Buffer, - selfPointTriangleCounter = processingSelfPointTriangle.Counter, - selfPointTriangleIndexArray = processingSelfPointTriangle.Buffer, - selfEdgeEdgeCounter = processingSelfEdgeEdge.Counter, - selfEdgeEdgeIndexArray = processingSelfEdgeEdge.Buffer, - selfTrianglePointCounter = processingSelfTrianglePoint.Counter, - selfTrianglePointIndexArray = processingSelfTrianglePoint.Buffer, - }; - jobHandle = createUpdateParticleJob.Schedule(tm.TeamCount, 1, jobHandle); - - // 今回のステップで計算が必要なコライダーリストを作成する - jobHandle = MagicaManager.Collider.CreateUpdateColliderList(updateIndex, jobHandle); - - // コライダーの更新 - jobHandle = MagicaManager.Collider.StartSimulationStep(jobHandle); - - // 速度更新、外力の影響、慣性シフト - var startStepJob = new StartSimulationStepJob() - { - simulationPower = MagicaManager.Time.SimulationPower, - simulationDeltaTime = MagicaManager.Time.SimulationDeltaTime, - - stepParticleIndexArray = processingStepParticle.Buffer, - - attributes = vm.attributes.GetNativeArray(), - depthArray = vm.vertexDepths.GetNativeArray(), - positions = vm.positions.GetNativeArray(), - rotations = vm.rotations.GetNativeArray(), - vertexRootIndices = vm.vertexRootIndices.GetNativeArray(), - - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - centerDataArray = tm.centerDataArray.GetNativeArray(), - teamWindArray = tm.teamWindArray.GetNativeArray(), - - windDataArray = wm.windDataArray.GetNativeArray(), - - teamIdArray = teamIdArray.GetNativeArray(), - oldPosArray = oldPosArray.GetNativeArray(), - velocityArray = velocityArray.GetNativeArray(), - nextPosArray = nextPosArray.GetNativeArray(), - basePosArray = basePosArray.GetNativeArray(), - baseRotArray = baseRotArray.GetNativeArray(), - oldPositionArray = oldPositionArray.GetNativeArray(), - oldRotationArray = oldRotationArray.GetNativeArray(), - velocityPosArray = velocityPosArray.GetNativeArray(), - frictionArray = frictionArray.GetNativeArray(), - - stepBasicPositionArray = stepBasicPositionBuffer, - stepBasicRotationArray = stepBasicRotationBuffer, - }; - jobHandle = startStepJob.Schedule(processingStepParticle.GetJobSchedulePtr(), 32, jobHandle); - - // 制約解決のためのステップごとの基準姿勢を計算(ベースラインから) - var updateStepBasicPotureJob = new UpdateStepBasicPotureJob() - { - stepBaseLineIndexArray = processingStepBaseLine.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - - attributes = MagicaManager.VMesh.attributes.GetNativeArray(), - vertexParentIndices = vm.vertexParentIndices.GetNativeArray(), - vertexLocalPositions = vm.vertexLocalPositions.GetNativeArray(), - vertexLocalRotations = vm.vertexLocalRotations.GetNativeArray(), - baseLineStartDataIndices = vm.baseLineStartDataIndices.GetNativeArray(), - baseLineDataCounts = vm.baseLineDataCounts.GetNativeArray(), - baseLineData = vm.baseLineData.GetNativeArray(), - //vertexToTransformRotations = vm.vertexToTransformRotations.GetNativeArray(), - - basePosArray = basePosArray.GetNativeArray(), - baseRotArray = baseRotArray.GetNativeArray(), - - stepBasicPositionArray = stepBasicPositionBuffer, - stepBasicRotationArray = stepBasicRotationBuffer, - }; - jobHandle = updateStepBasicPotureJob.Schedule(processingStepBaseLine.GetJobSchedulePtr(), 2, jobHandle); - - // 制約の解決 - //for (int i = 0; i < 2; i++) - { - // 一般制約 - jobHandle = tetherConstraint.SolverConstraint(jobHandle); - jobHandle = distanceConstraint.SolverConstraint(jobHandle); - jobHandle = angleConstraint.SolverConstraint(jobHandle); - jobHandle = bendingConstraint.SolverConstraint(jobHandle); - // コライダーコリジョン - jobHandle = colliderCollisionConstraint.SolverConstraint(jobHandle); - // コライダー衝突後はパーティクルが乱れる可能性があるためもう一度距離制約で整える。 - // これは裏返り防止などに効果大。 - jobHandle = distanceConstraint.SolverConstraint(jobHandle); - // モーション制約はコライダーより優先 - jobHandle = motionConstraint.SolverConstraint(jobHandle); - // セルフコリジョンは最後 - jobHandle = selfCollisionConstraint.SolverConstraint(updateIndex, jobHandle); - } - - // 座標確定 - var endStepJob = new EndSimulationStepJob() - { - simulationDeltaTime = MagicaManager.Time.SimulationDeltaTime, - - stepParticleIndexArray = processingStepParticle.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - centerDataArray = tm.centerDataArray.GetNativeArray(), - - attributes = vm.attributes.GetNativeArray(), - vertexDepths = vm.vertexDepths.GetNativeArray(), - - teamIdArray = teamIdArray.GetNativeArray(), - nextPosArray = nextPosArray.GetNativeArray(), - oldPosArray = oldPosArray.GetNativeArray(), - velocityArray = velocityArray.GetNativeArray(), - realVelocityArray = realVelocityArray.GetNativeArray(), - velocityPosArray = velocityPosArray.GetNativeArray(), - frictionArray = frictionArray.GetNativeArray(), - staticFrictionArray = staticFrictionArray.GetNativeArray(), - collisionNormalArray = collisionNormalArray.GetNativeArray(), - }; - jobHandle = endStepJob.Schedule(processingStepParticle.GetJobSchedulePtr(), 32, jobHandle); - - // コライダーの後更新 - jobHandle = MagicaManager.Collider.EndSimulationStep(jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct ClearStepCounter : IJob - { - [Unity.Collections.WriteOnly] - public NativeReference processingStepParticle; - [Unity.Collections.WriteOnly] - public NativeReference processingStepTriangleBending; - [Unity.Collections.WriteOnly] - public NativeReference processingStepEdgeCollision; - [Unity.Collections.WriteOnly] - public NativeReference processingStepCollider; - [Unity.Collections.WriteOnly] - public NativeReference processingStepBaseLine; - //[Unity.Collections.WriteOnly] - //public NativeReference processingCounter5; - [Unity.Collections.WriteOnly] - public NativeReference processingStepMotionParticle; - - [Unity.Collections.WriteOnly] - public NativeReference processingSelfParticle; - [Unity.Collections.WriteOnly] - public NativeReference processingSelfPointTriangle; - [Unity.Collections.WriteOnly] - public NativeReference processingSelfEdgeEdge; - [Unity.Collections.WriteOnly] - public NativeReference processingSelfTrianglePoint; - - public void Execute() - { - processingStepParticle.Value = 0; - processingStepTriangleBending.Value = 0; - processingStepEdgeCollision.Value = 0; - processingStepCollider.Value = 0; - processingStepBaseLine.Value = 0; - //processingCounter5.Value = 0; - processingStepMotionParticle.Value = 0; - - processingSelfParticle.Value = 0; - processingSelfPointTriangle.Value = 0; - processingSelfEdgeEdge.Value = 0; - processingSelfTrianglePoint.Value = 0; - } - } - - [BurstCompile] - struct CreateUpdateParticleList : IJobParallelFor - { - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - - // buffer - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference stepParticleIndexCounter; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray stepParticleIndexArray; - - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference stepBaseLineIndexCounter; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray stepBaseLineIndexArray; - - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference stepTriangleBendIndexCounter; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray stepTriangleBendIndexArray; - - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference stepEdgeCollisionIndexCounter; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray stepEdgeCollisionIndexArray; - - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference motionParticleIndexCounter; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray motionParticleIndexArray; - - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference selfParticleCounter; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray selfParticleIndexArray; - - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference selfPointTriangleCounter; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray selfPointTriangleIndexArray; - - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference selfEdgeEdgeCounter; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray selfEdgeEdgeIndexArray; - - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference selfTrianglePointCounter; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray selfTrianglePointIndexArray; - - // チームごと - public void Execute(int teamId) - { - if (teamId == 0) - return; - - var tdata = teamDataArray[teamId]; - if (tdata.IsProcess == false || tdata.IsRunning == false) - return; - - // このステップでの更新があるか判定する - if (tdata.IsStepRunning == false) - return; - - var parameter = parameterArray[teamId]; - - // パーティクルリスト - int pcnt = tdata.particleChunk.dataLength; - int pstart = tdata.particleChunk.startIndex; - int start = stepParticleIndexCounter.InterlockedStartIndex(pcnt); - for (int i = 0; i < pcnt; i++) + // プロキシメッシュをスキニングし基本姿勢を求める + var splitPre_A_Job = new SplitPre_A_Job() { - stepParticleIndexArray[start + i] = pstart + i; - } + workerCount = workerCount, - // ベースライン - int bcnt = tdata.BaseLineCount; - int bstart = tdata.baseLineChunk.startIndex; - start = stepBaseLineIndexCounter.InterlockedStartIndex(bcnt); - for (int i = 0; i < bcnt; i++) - { - // 上位16bit:チームID, 下位16bit:ベースラインインデックス - uint pack = DataUtility.Pack32(teamId, bstart + i); - stepBaseLineIndexArray[start + i] = (int)pack; - } + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), - // トライアングルベンド - if (parameter.triangleBendingConstraint.method != TriangleBendingConstraint.Method.None) + // transform + transformLocalToWorldMatrixArray = bm.localToWorldMatrixArray.GetNativeArray(), + + // vmesh + attributes = vm.attributes.GetNativeArray(), + localPositions = vm.localPositions.GetNativeArray(), + localNormals = vm.localNormals.GetNativeArray(), + localTangents = vm.localTangents.GetNativeArray(), + boneWeights = vm.boneWeights.GetNativeArray(), + skinBoneTransformIndices = vm.skinBoneTransformIndices.GetNativeArray(), + skinBoneBindPoses = vm.skinBoneBindPoses.GetNativeArray(), + positions = vm.positions.GetNativeArray(), + rotations = vm.rotations.GetNativeArray(), + }; + splitClothJobHandle = splitPre_A_Job.Schedule(splitClothTeamCount * workerCount, 1, jobHandle); + + // チームのセンター姿勢の決定と慣性用の移動量計算 + var splitPre_B_Job = new SplitPre_B_Job() { - int bendCnt = tdata.bendingPairChunk.dataLength; - int bendIndex = tdata.bendingPairChunk.startIndex; - start = stepTriangleBendIndexCounter.InterlockedStartIndex(bendCnt); - for (int i = 0; i < bendCnt; i++, bendIndex++) + simulationDeltaTime = MagicaManager.Time.SimulationDeltaTime, + + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + centerDataArray = tm.centerDataArray.GetNativeArray(), + teamWindArray = tm.teamWindArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + + // wind + windZoneCount = wm.WindCount, + windDataArray = wm.windDataArray.GetNativeArray(), + + // transform + transformPositionArray = bm.positionArray.GetNativeArray(), + transformRotationArray = bm.rotationArray.GetNativeArray(), + transformScaleArray = bm.scaleArray.GetNativeArray(), + + // vmesh + positions = vm.positions.GetNativeArray(), + rotations = vm.rotations.GetNativeArray(), + vertexBindPoseRotations = vm.vertexBindPoseRotations.GetNativeArray(), + + // inertia + fixedArray = inertiaConstraint.fixedArray.GetNativeArray(), + }; + splitClothJobHandle = splitPre_B_Job.Schedule(splitClothTeamCount, 1, splitClothJobHandle); + + // パーティクルの全体慣性およびリセットの適用 + // コライダーのローカル姿勢を求める、および全体慣性とリセットの適用 + var splitPre_C_Job = new SplitPre_C_Job() + { + workerCount = workerCount, + + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + centerDataArray = tm.centerDataArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + + // transform + transformPositionArray = bm.positionArray.GetNativeArray(), + transformRotationArray = bm.rotationArray.GetNativeArray(), + transformScaleArray = bm.scaleArray.GetNativeArray(), + transformLocalPositionArray = bm.localPositionArray.GetNativeArray(), + transformLocalRotationArray = bm.localRotationArray.GetNativeArray(), + transformLocalScaleArray = bm.localScaleArray.GetNativeArray(), + + // vmesh + positions = vm.positions.GetNativeArray(), + rotations = vm.rotations.GetNativeArray(), + vertexDepths = vm.vertexDepths.GetNativeArray(), + + // particle + nextPosArray = nextPosArray.GetNativeArray(), + oldPosArray = oldPosArray.GetNativeArray(), + oldRotArray = oldRotArray.GetNativeArray(), + basePosArray = basePosArray.GetNativeArray(), + baseRotArray = baseRotArray.GetNativeArray(), + oldPositionArray = oldPositionArray.GetNativeArray(), + oldRotationArray = oldRotationArray.GetNativeArray(), + velocityPosArray = velocityPosArray.GetNativeArray(), + dispPosArray = dispPosArray.GetNativeArray(), + velocityArray = velocityArray.GetNativeArray(), + realVelocityArray = realVelocityArray.GetNativeArray(), + frictionArray = frictionArray.GetNativeArray(), + staticFrictionArray = staticFrictionArray.GetNativeArray(), + collisionNormalArray = collisionNormalArray.GetNativeArray(), + + // collider + colliderFlagArray = cm.flagArray.GetNativeArray(), + colliderCenterArray = cm.centerArray.GetNativeArray(), + colliderFramePositions = cm.framePositions.GetNativeArray(), + colliderFrameRotations = cm.frameRotations.GetNativeArray(), + colliderFrameScales = cm.frameScales.GetNativeArray(), + colliderOldFramePositions = cm.oldFramePositions.GetNativeArray(), + colliderOldFrameRotations = cm.oldFrameRotations.GetNativeArray(), + colliderNowPositions = cm.nowPositions.GetNativeArray(), + colliderNowRotations = cm.nowRotations.GetNativeArray(), + colliderOldPositions = cm.oldPositions.GetNativeArray(), + colliderOldRotations = cm.oldRotations.GetNativeArray(), + colliderMainColliderIndices = cm.mainColliderIndices.GetNativeArray(), + }; + splitClothJobHandle = splitPre_C_Job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); + + // セルフコリジョンのインターセクトバッファの生成(開始) + bool useIntersectJob = false; + if (useSelfCollision && maxUpdateCount > 0 && useIntersect) + { + // インターセクトバッファの生成 + // インターセクトパーティクルフラグクリア + var selfDetectionIntersect_job = new SelfCollisionConstraint.SelfDetectionIntersectJob() { - uint pack = DataUtility.Pack12_20(teamId, bendIndex); - stepTriangleBendIndexArray[start + i] = (int)pack; - } - } + workerCount = workerCount, + // div + frameIndex = Time.frameCount % Define.System.SelfCollisionIntersectDiv, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + // self collision + primitiveArrayB = selfCollisionConstraint.primitiveArrayB.GetNativeArray(), + uniformGridStartCountBuffer = selfCollisionConstraint.uniformGridStartCountBuffer.GetNativeArray(), + // buffer + intersectQueue = selfCollisionConstraint.intersectQueue.AsParallelWriter(), + }; + selfIntersectJobHandle = selfDetectionIntersect_job.Schedule(splitClothTeamCount * workerCount, 1, jobHandle); - // エッジコライダーコリジョン - int colliderCount = tdata.ColliderCount; - if (parameter.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Edge && tdata.proxyEdgeChunk.IsValid && colliderCount > 0) - { - int ecnt = tdata.proxyEdgeChunk.dataLength; - int estart = tdata.proxyEdgeChunk.startIndex; - start = stepEdgeCollisionIndexCounter.InterlockedStartIndex(ecnt); - for (int i = 0; i < ecnt; i++) + // インターセクトバッファをリストに変換 + var selfConvertIntersectList_job = new SelfCollisionConstraint.SelfConvertIntersectListJob() { - stepEdgeCollisionIndexArray[start + i] = estart + i; - } + intersectQueue = selfCollisionConstraint.intersectQueue, + intersectList = selfCollisionConstraint.intersectList, + }; + selfIntersectJobHandle = selfConvertIntersectList_job.Schedule(selfIntersectJobHandle); + useIntersectJob = true; } - // モーション制約パーティクル - if (parameter.motionConstraint.useMaxDistance || parameter.motionConstraint.useBackstop) + // ■ステップループ + for (int updateIndex = 0; updateIndex < maxUpdateCount; updateIndex++) { - start = motionParticleIndexCounter.InterlockedStartIndex(pcnt); - for (int i = 0; i < pcnt; i++) + bool isFirstStep = updateIndex == 0; + + // チーム更新 + // コライダーの更新 + var splitStep_A_job = new SplitStep_A_Job() { - motionParticleIndexArray[start + i] = pstart + i; - } - } + updateIndex = updateIndex, + simulationPower = tim.SimulationPower, + simulationDeltaTime = tim.SimulationDeltaTime, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + centerDataArray = tm.centerDataArray.GetNativeArray(), + teamWindArray = tm.teamWindArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + // collider + colliderFlagArray = cm.flagArray.GetNativeArray(), + colliderSizeArray = cm.sizeArray.GetNativeArray(), + colliderFramePositions = cm.framePositions.GetNativeArray(), + colliderFrameRotations = cm.frameRotations.GetNativeArray(), + colliderFrameScales = cm.frameScales.GetNativeArray(), + colliderOldFramePositions = cm.oldFramePositions.GetNativeArray(), + colliderOldFrameRotations = cm.oldFrameRotations.GetNativeArray(), + colliderNowPositions = cm.nowPositions.GetNativeArray(), + colliderNowRotations = cm.nowRotations.GetNativeArray(), + colliderOldPositions = cm.oldPositions.GetNativeArray(), + colliderOldRotations = cm.oldRotations.GetNativeArray(), + colliderWorkDataArray = cm.workDataArray.GetNativeArray(), + }; + splitClothJobHandle = splitStep_A_job.Schedule(splitClothTeamCount, 1, splitClothJobHandle); - // セルフコリジョン - bool useSelfEdgeEdge = tdata.flag.TestAny(TeamManager.Flag_Self_EdgeEdge, 3); - bool useSelfPointTriangle = tdata.flag.TestAny(TeamManager.Flag_Self_PointTriangle, 3); - bool useSelfTrianglePoint = tdata.flag.TestAny(TeamManager.Flag_Self_TrianglePoint, 3); - if (useSelfEdgeEdge) - { - int ecnt = tdata.EdgeCount; - start = selfEdgeEdgeCounter.InterlockedStartIndex(ecnt); - for (int i = 0; i < ecnt; i++) + // 速度更新、外力の影響、慣性シフト + var splitStep_B_job = new SplitStep_B_Job() { - // 上位16bit:チームID, 下位16bit:Edgeインデックス - uint pack = DataUtility.Pack32(teamId, i); - selfEdgeEdgeIndexArray[start + i] = pack; - } - } - if (useSelfPointTriangle) - { - start = selfPointTriangleCounter.InterlockedStartIndex(pcnt); - for (int i = 0; i < pcnt; i++) + workerCount = workerCount, + updateIndex = updateIndex, + simulationPower = tim.SimulationPower, + simulationDeltaTime = tim.SimulationDeltaTime, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + centerDataArray = tm.centerDataArray.GetNativeArray(), + teamWindArray = tm.teamWindArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + // wind + windZoneCount = wm.WindCount, + windDataArray = wm.windDataArray.GetNativeArray(), + // vmesh + attributes = vm.attributes.GetNativeArray(), + depthArray = vm.vertexDepths.GetNativeArray(), + positions = vm.positions.GetNativeArray(), + rotations = vm.rotations.GetNativeArray(), + vertexRootIndices = vm.vertexRootIndices.GetNativeArray(), + // particle + nextPosArray = nextPosArray.GetNativeArray(), + oldPosArray = oldPosArray.GetNativeArray(), + basePosArray = basePosArray.GetNativeArray(), + baseRotArray = baseRotArray.GetNativeArray(), + oldPositionArray = oldPositionArray.GetNativeArray(), + oldRotationArray = oldRotationArray.GetNativeArray(), + velocityPosArray = velocityPosArray.GetNativeArray(), + velocityArray = velocityArray.GetNativeArray(), + frictionArray = frictionArray.GetNativeArray(), + // buffer + stepBasicPositionBuffer = stepBasicPositionBuffer, + stepBasicRotationBuffer = stepBasicRotationBuffer, + }; + splitClothJobHandle = splitStep_B_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); + + // ベースラインの基準姿勢を計算 + var splitStep_C_job = new SplitStep_C_Job() { - // 上位16bit:チームID, 下位16bit:Pointインデックス - uint pack = DataUtility.Pack32(teamId, i); - selfPointTriangleIndexArray[start + i] = pack; - } - } - if (useSelfTrianglePoint) - { - int tcnt = tdata.TriangleCount; - start = selfTrianglePointCounter.InterlockedStartIndex(tcnt); - for (int i = 0; i < tcnt; i++) + workerCount = workerCount, + updateIndex = updateIndex, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + // vmesh + attributes = vm.attributes.GetNativeArray(), + vertexRootIndices = vm.vertexRootIndices.GetNativeArray(), + vertexParentIndices = vm.vertexParentIndices.GetNativeArray(), + baseLineStartDataIndices = vm.baseLineStartDataIndices.GetNativeArray(), + baseLineDataCounts = vm.baseLineDataCounts.GetNativeArray(), + baseLineData = vm.baseLineData.GetNativeArray(), + vertexLocalPositions = vm.vertexLocalPositions.GetNativeArray(), + vertexLocalRotations = vm.vertexLocalRotations.GetNativeArray(), + // particle + basePosArray = basePosArray.GetNativeArray(), + baseRotArray = baseRotArray.GetNativeArray(), + // buffer + stepBasicPositionBuffer = stepBasicPositionBuffer, + stepBasicRotationBuffer = stepBasicRotationBuffer, + }; + splitClothJobHandle = splitStep_C_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); + + // テザー + // 距離 + var splitStep_D_job = new SplitStep_D_Job() { - // 上位16bit:チームID, 下位16bit:Triangleインデックス - uint pack = DataUtility.Pack32(teamId, i); - selfTrianglePointIndexArray[start + i] = pack; - } - } - if (useSelfEdgeEdge || useSelfPointTriangle || useSelfTrianglePoint) - { - start = selfParticleCounter.InterlockedStartIndex(pcnt); - for (int i = 0; i < pcnt; i++) + workerCount = workerCount, + updateIndex = updateIndex, + simulationPower = tim.SimulationPower, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + centerDataArray = tm.centerDataArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + // vmesh + attributes = vm.attributes.GetNativeArray(), + depthArray = vm.vertexDepths.GetNativeArray(), + vertexRootIndices = vm.vertexRootIndices.GetNativeArray(), + // particle + nextPosArray = nextPosArray.GetNativeArray(), + basePosArray = basePosArray.GetNativeArray(), + velocityPosArray = velocityPosArray.GetNativeArray(), + frictionArray = frictionArray.GetNativeArray(), + // distance + distanceIndexArray = distanceConstraint.indexArray.GetNativeArray(), + distanceDataArray = distanceConstraint.dataArray.GetNativeArray(), + distanceDistanceArray = distanceConstraint.distanceArray.GetNativeArray(), + // buffer + stepBasicPositionBuffer = stepBasicPositionBuffer, + }; + splitClothJobHandle = splitStep_D_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); + + // アングル + var splitStep_Angle_job = new SplitStep_Angle_Job() { - selfParticleIndexArray[start + i] = pstart + i; - } - } + workerCount = workerCount, + updateIndex = updateIndex, + simulationPower = tim.SimulationPower, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + // vmesh + attributes = vm.attributes.GetNativeArray(), + depthArray = vm.vertexDepths.GetNativeArray(), + vertexRootIndices = vm.vertexRootIndices.GetNativeArray(), + vertexParentIndices = vm.vertexParentIndices.GetNativeArray(), + baseLineStartDataIndices = vm.baseLineStartDataIndices.GetNativeArray(), + baseLineDataCounts = vm.baseLineDataCounts.GetNativeArray(), + baseLineData = vm.baseLineData.GetNativeArray(), + // particle + nextPosArray = nextPosArray.GetNativeArray(), + //basePosArray = basePosArray.GetNativeArray(), + velocityPosArray = velocityPosArray.GetNativeArray(), + frictionArray = frictionArray.GetNativeArray(), + // distance + distanceIndexArray = distanceConstraint.indexArray.GetNativeArray(), + distanceDataArray = distanceConstraint.dataArray.GetNativeArray(), + distanceDistanceArray = distanceConstraint.distanceArray.GetNativeArray(), + // buffer + stepBasicPositionBuffer = stepBasicPositionBuffer, + stepBasicRotationBuffer = stepBasicRotationBuffer, + // buffer2 + tempVectorBufferA = tempVectorBufferA, + tempVectorBufferB = tempVectorBufferB, + tempFloatBufferA = tempFloatBufferA, + tempRotationBufferA = tempRotationBufferA, + tempRotationBufferB = tempRotationBufferB, + }; + splitClothJobHandle = splitStep_Angle_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); - //Debug.Log($"Step:{updateIndex}, updateParticleCount:{jobParticleIndexList.Length}"); - } - } - - [BurstCompile] - struct StartSimulationStepJob : IJobParallelForDefer - { - public float4 simulationPower; - public float simulationDeltaTime; - - [Unity.Collections.ReadOnly] - public NativeArray stepParticleIndexArray; - - // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [Unity.Collections.ReadOnly] - public NativeArray depthArray; - [Unity.Collections.ReadOnly] - public NativeArray positions; - [Unity.Collections.ReadOnly] - public NativeArray rotations; - [Unity.Collections.ReadOnly] - public NativeArray vertexRootIndices; - - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - [Unity.Collections.ReadOnly] - public NativeArray centerDataArray; - [Unity.Collections.ReadOnly] - public NativeArray teamWindArray; - - // wind - [Unity.Collections.ReadOnly] - public NativeArray windDataArray; - - // particle - [Unity.Collections.ReadOnly] - public NativeArray teamIdArray; - [Unity.Collections.ReadOnly] - public NativeArray oldPosArray; - [Unity.Collections.ReadOnly] - public NativeArray velocityArray; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray nextPosArray; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray basePosArray; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray baseRotArray; - [Unity.Collections.ReadOnly] - public NativeArray oldPositionArray; - [Unity.Collections.ReadOnly] - public NativeArray oldRotationArray; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray velocityPosArray; - [Unity.Collections.ReadOnly] - public NativeArray frictionArray; - - // buffer - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray stepBasicPositionArray; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray stepBasicRotationArray; - - - // ステップパーティクルごと - public void Execute(int index) - { - int pindex = stepParticleIndexArray[index]; - int teamId = teamIdArray[pindex]; - var tdata = teamDataArray[teamId]; - int l_index = pindex - tdata.particleChunk.startIndex; - - // 各カテゴリのデータインデックス - int vindex = tdata.proxyCommonChunk.startIndex + l_index; - - // パラメータ - var param = parameterArray[teamId]; - - // 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; - - // ステップ基本位置 - stepBasicPositionArray[pindex] = basePos; - stepBasicRotationArray[pindex] = baseRot; - - // 移動パーティクル - if (attr.IsMove() || tdata.IsSpring) - { - var cdata = centerDataArray[teamId]; - - // 重量 - //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); // 二次曲線 - 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.EvaluateCurveClamp01(depth); - velocity *= math.saturate(1.0f - damping * simulationPower.z); - - // 外力 - float3 force = 0; - - // 重力 - float3 gforce = param.gravityDirection * (param.gravity * tdata.gravityRatio); - force += gforce; - - // 外力 - float3 exForce = 0; - float mass = MathUtility.CalcMass(depth); - switch (tdata.forceMode) + // トライアングルベンド + var splitStep_Triangle_job = new SplitStep_Triangle_Job() { - 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; + workerCount = workerCount, + updateIndex = updateIndex, + simulationPower = tim.SimulationPower, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + // vmesh + attributes = vm.attributes.GetNativeArray(), + depthArray = vm.vertexDepths.GetNativeArray(), + // particle + nextPosArray = nextPosArray.GetNativeArray(), + frictionArray = frictionArray.GetNativeArray(), + // triangle bending + bendingTrianglePairArray = bendingConstraint.trianglePairArray.GetNativeArray(), + bendingRestAngleOrVolumeArray = bendingConstraint.restAngleOrVolumeArray.GetNativeArray(), + bendingSignOrVolumeArray = bendingConstraint.signOrVolumeArray.GetNativeArray(), + // buffer2 + tempVectorBufferA = tempVectorBufferA, + tempCountBuffer = tempCountBuffer, + }; + splitClothJobHandle = splitStep_Triangle_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); - // 風力 - force += Wind(teamId, tdata, param.wind, cdata, vindex, pindex, depth); - - // 外力チームスケール倍率 - 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); - } - - // 速度計算用の移動前の位置 - velocityPosArray[pindex] = velocityPos; - - // 予測位置格納 - nextPosArray[pindex] = nextPos; - } - - void Spring(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) + // トライアングルベンド集計 + // コライダーコリジョンPoint + var splitStep_E_job = new SplitStep_E_Job() { - v *= (limitDistance / len); - } + workerCount = workerCount, + updateIndex = updateIndex, + simulationPower = tim.SimulationPower, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + // vmesh + attributes = vm.attributes.GetNativeArray(), + depthArray = vm.vertexDepths.GetNativeArray(), + // particle + nextPosArray = nextPosArray.GetNativeArray(), + basePosArray = basePosArray.GetNativeArray(), + velocityPosArray = velocityPosArray.GetNativeArray(), + frictionArray = frictionArray.GetNativeArray(), + collisionNormalArray = collisionNormalArray.GetNativeArray(), + // collider + colliderFlagArray = cm.flagArray.GetNativeArray(), + colliderWorkDataArray = cm.workDataArray.GetNativeArray(), + // buffer2 + tempVectorBufferA = tempVectorBufferA, + tempCountBuffer = tempCountBuffer, + }; + splitClothJobHandle = splitStep_E_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); - // 楕円クランプ - if (springParams.normalLimitRatio < 1.0f) + // コライダーコリジョンEdge + if (useEdgeCollision) { - // もっとスマートにならないか.. - 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) + var splitStep_Edge_job = new SplitStep_Edge_Job() { - v -= dir * (math.abs(ylen) - y) * math.sign(ylen); + workerCount = workerCount, + updateIndex = updateIndex, + simulationPower = tim.SimulationPower, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + // vmesh + attributes = vm.attributes.GetNativeArray(), + depthArray = vm.vertexDepths.GetNativeArray(), + edges = vm.edges.GetNativeArray(), + // particle + nextPosArray = nextPosArray.GetNativeArray(), + // collider + colliderFlagArray = cm.flagArray.GetNativeArray(), + colliderWorkDataArray = cm.workDataArray.GetNativeArray(), + // buffer2 + tempVectorBufferA = tempVectorBufferA, + tempVectorBufferB = tempVectorBufferB, + tempCountBuffer = tempCountBuffer, + tempFloatBufferA = tempFloatBufferA, + }; + splitClothJobHandle = splitStep_Edge_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); + } + + if (useSelfCollision) + { + // ■セルフコリジョンあり + // コライダーコリジョンEdge集計 + // 距離 + // モーション + var splitStep_F_Self_job = new SplitStep_F_Self_Job() + { + workerCount = workerCount, + updateIndex = updateIndex, + simulationPower = tim.SimulationPower, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + // vmesh + attributes = vm.attributes.GetNativeArray(), + depthArray = vm.vertexDepths.GetNativeArray(), + // particle + nextPosArray = nextPosArray.GetNativeArray(), + basePosArray = basePosArray.GetNativeArray(), + baseRotArray = baseRotArray.GetNativeArray(), + velocityPosArray = velocityPosArray.GetNativeArray(), + frictionArray = frictionArray.GetNativeArray(), + collisionNormalArray = collisionNormalArray.GetNativeArray(), + // distance + distanceIndexArray = distanceConstraint.indexArray.GetNativeArray(), + distanceDataArray = distanceConstraint.dataArray.GetNativeArray(), + distanceDistanceArray = distanceConstraint.distanceArray.GetNativeArray(), + // buffer2 + tempVectorBufferA = tempVectorBufferA, + tempVectorBufferB = tempVectorBufferB, + tempCountBuffer = tempCountBuffer, + tempFloatBufferA = tempFloatBufferA, + }; + splitClothJobHandle = splitStep_F_Self_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); + + // セルフコリジョンのインターセクトバッファ更新ジョブを合流させる + if (isFirstStep && useIntersectJob) + { + splitClothJobHandle = JobHandle.CombineDependencies(selfIntersectJobHandle, splitClothJobHandle); } - } - } - 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; - } - - - float3 Wind(int teamId, in TeamManager.TeamData tdata, in WindParams windParams, in InertiaConstraint.CenterData cdata, int vindex, int pindex, float depth) - { - float3 windForce = 0; - - // 基準ルート座標 - // (1)チームごとにずらす - // (2)同期率によりルートラインごとにずらす - // (3)チームの座標やパーティクルの座標は計算に入れない - int rootIndex = vertexRootIndices[vindex]; - float3 windPos = (teamId + 1) * 4.19230645f + (rootIndex * 0.0023963f * (1.0f - windParams.synchronization) * 100); - - // ゾーンごとの風影響計算 - var teamWindData = teamWindArray[teamId]; - int cnt = teamWindData.ZoneCount; - for (int i = 0; i < cnt; i++) - { - var windInfo = teamWindData.windZoneList[i]; - var windData = windDataArray[windInfo.windId]; - windForce += WindForceBlend(windInfo, windParams, windPos, windData.turbulence); - } - -#if true - // 移動風影響計算 - if (windParams.movingWind > 0.01f) - { - windForce += WindForceBlend(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; - } - - float3 WindForceBlend(in TeamWindInfo windInfo, in WindParams windParams, in float3 windPos, float windTurbulence) - { - float windMain = windInfo.main; - if (windMain < 0.01f) - return 0; - - // 風速係数 - 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; - } - } - - /// - /// ベースラインごとに初期姿勢を求める - /// これは制約の解決で利用される - /// AnimationPoseRatioが1.0ならば不要なのでスキップされる - /// - [BurstCompile] - struct UpdateStepBasicPotureJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray stepBaseLineIndexArray; - - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - - // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [Unity.Collections.ReadOnly] - public NativeArray vertexParentIndices; - [Unity.Collections.ReadOnly] - public NativeArray vertexLocalPositions; - [Unity.Collections.ReadOnly] - public NativeArray vertexLocalRotations; - [Unity.Collections.ReadOnly] - public NativeArray baseLineStartDataIndices; - [Unity.Collections.ReadOnly] - public NativeArray baseLineDataCounts; - [Unity.Collections.ReadOnly] - public NativeArray baseLineData; - //[Unity.Collections.ReadOnly] - //public NativeArray vertexToTransformRotations; - - // particle - [Unity.Collections.ReadOnly] - public NativeArray basePosArray; - [Unity.Collections.ReadOnly] - public NativeArray baseRotArray; - - // buffer - [NativeDisableParallelForRestriction] - public NativeArray stepBasicPositionArray; - [NativeDisableParallelForRestriction] - public NativeArray stepBasicRotationArray; - - // ステップ実行ベースラインごと - public void Execute(int index) - { - // チームは有効であることが保証されている - uint pack = (uint)stepBaseLineIndexArray[index]; - int teamId = DataUtility.Unpack32Hi(pack); - int bindex = DataUtility.Unpack32Low(pack); - - var tdata = teamDataArray[teamId]; - - // アニメーションポーズ使用の有無 - // 初期姿勢の計算が不要なら抜ける - float blendRatio = tdata.animationPoseRatio; - //bool isBasePose = blendRatio > 0.99f; - if (blendRatio > 0.99f) - return; - - int b_datastart = tdata.baseLineDataChunk.startIndex; - int p_start = tdata.particleChunk.startIndex; - int v_start = tdata.proxyCommonChunk.startIndex; - //int vt_start = tdata.proxyBoneChunk.startIndex; - - // チームスケール - float3 scl = tdata.initScale * tdata.scaleRatio; - - int b_start = baseLineStartDataIndices[bindex]; - int b_cnt = baseLineDataCounts[bindex]; - int b_dataindex = b_start + b_datastart; - //if (isBasePose == false) - { - 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() == false || p_index < 0) - //{ - // // 固定もしくはアニメーションポーズを使用 - // // basePos/baseRotをそのままコピーする - // var bpos = basePosArray[pindex]; - // var brot = baseRotArray[pindex]; - - // stepBasicPositionArray[pindex] = bpos; - // stepBasicRotationArray[pindex] = brot; - //} - //else - if (attr.IsMove() && p_index >= 0) + // セルフコリジョン + if (isFirstStep) { - // 移動 - // 親から姿勢を算出する - var lpos = vertexLocalPositions[vindex]; - var lrot = vertexLocalRotations[vindex]; - var ppos = stepBasicPositionArray[p_pindex]; - var prot = stepBasicRotationArray[p_pindex]; - stepBasicPositionArray[pindex] = math.mul(prot, lpos * scl) + ppos; - stepBasicRotationArray[pindex] = math.mul(prot, lrot); - } - } - } + // ■初回ステップ + // (チームごとPoint/Edge/Triangle3分割) + // プリミティブ情報更新(nextPos/oldPos,invMass,thickness,aabb) + // 最大プリミティブサイズ算出、グリッドサイズ算出 + // プリミティブ用のインターセクトフラグ更新 + var selfStep_UpdatePrimitive_job = new SelfCollisionConstraint.SelfStep_UpdatePrimitiveJob() + { + workerCount = 3, + updateIndex = updateIndex, + simulationPower = tim.SimulationPower, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + // particle + nextPosArray = nextPosArray.GetNativeArray(), + oldPosArray = oldPosArray.GetNativeArray(), + frictionArray = frictionArray.GetNativeArray(), + // self collision + useIntersect = useIntersect, + primitiveArrayB = selfCollisionConstraint.primitiveArrayB.GetNativeArray(), + intersectFlagArray = selfCollisionConstraint.intersectFlagArray, + }; + splitClothJobHandle = selfStep_UpdatePrimitive_job.Schedule(splitClothTeamCount * 3, 1, splitClothJobHandle); - // アニメーション姿勢とブレンド - 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; + // (チームごとPoint/Edge/Triangle3分割) + // プリミティブのグリッド座標算出 + // プリミティブをグリッド座標でソート + // グリッド情報の作成 + var selfStep_UpdateGrid_job = new SelfCollisionConstraint.SelfStep_UpdateGridJob() + { + kindCount = 3, + updateIndex = updateIndex, + simulationPower = tim.SimulationPower, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + // self collision + primitiveArrayB = selfCollisionConstraint.primitiveArrayB.GetNativeArray(), + uniformGridStartCountBuffer = selfCollisionConstraint.uniformGridStartCountBuffer.GetNativeArray(), + }; + splitClothJobHandle = selfStep_UpdateGrid_job.Schedule(splitClothTeamCount * 3, 1, splitClothJobHandle); - var bpos = basePosArray[pindex]; - var brot = baseRotArray[pindex]; + // コンタクトバッファの生成(EdgeEdge/PointTriangle) + // チームごと+特殊分散 + var selfStep_DetectionContact_job = new SelfCollisionConstraint.SelfStep_DetectionContactJob() + { + updateIndex = updateIndex, + workerCount = workerCount, + teamCount = splitClothTeamCount, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + // particle + nextPosArray = nextPosArray.GetNativeArray(), + oldPosArray = oldPosArray.GetNativeArray(), + // self collision + primitiveArrayB = selfCollisionConstraint.primitiveArrayB.GetNativeArray(), + uniformGridStartCountBuffer = selfCollisionConstraint.uniformGridStartCountBuffer.GetNativeArray(), + // buffer + contactQueue = selfCollisionConstraint.contactQueue.AsParallelWriter(), + }; + // Self:(EdgeEdge/PointTriangle/TrianglePoint), Sync:(EdgeEdge/PointTriangle/TrianglePoint) = 6 + splitClothJobHandle = selfStep_DetectionContact_job.Schedule(splitClothTeamCount * 6 * workerCount, 1, splitClothJobHandle); - stepBasicPositionArray[pindex] = math.lerp(stepBasicPositionArray[pindex], bpos, blendRatio); - stepBasicRotationArray[pindex] = math.slerp(stepBasicRotationArray[pindex], brot, blendRatio); - //stepBasicPositionArray[pindex] = isBasePose ? bpos : math.lerp(stepBasicPositionArray[pindex], bpos, blendRatio); - //stepBasicRotationArray[pindex] = isBasePose ? brot : math.slerp(stepBasicRotationArray[pindex], brot, blendRatio); - } - } - } - } - - /// - /// ステップ終了後の座標確定処理 - /// - [BurstCompile] - struct EndSimulationStepJob : IJobParallelForDefer - { - public float simulationDeltaTime; - - [Unity.Collections.ReadOnly] - public NativeArray stepParticleIndexArray; - - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - [Unity.Collections.ReadOnly] - public NativeArray centerDataArray; - - // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [Unity.Collections.ReadOnly] - public NativeArray vertexDepths; - - // particle - [Unity.Collections.ReadOnly] - public NativeArray teamIdArray; - [Unity.Collections.ReadOnly] - public NativeArray nextPosArray; - [NativeDisableParallelForRestriction] - public NativeArray oldPosArray; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray velocityArray; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray realVelocityArray; - [Unity.Collections.ReadOnly] - public NativeArray velocityPosArray; - [NativeDisableParallelForRestriction] - public NativeArray frictionArray; - [NativeDisableParallelForRestriction] - public NativeArray staticFrictionArray; - [Unity.Collections.ReadOnly] - public NativeArray collisionNormalArray; - - // ステップ有効パーティクルごと - public void Execute(int index) - { - // パーティクルは有効であることが保証されている - int pindex = stepParticleIndexArray[index]; - int teamId = teamIdArray[pindex]; - var tdata = teamDataArray[teamId]; - var cdata = centerDataArray[teamId]; - var param = parameterArray[teamId]; - - int pstart = tdata.particleChunk.startIndex; - int l_index = pindex - pstart; - - // 各カテゴリのデータインデックス - int vindex = tdata.proxyCommonChunk.startIndex + l_index; - - var attr = attributes[vindex]; - var depth = vertexDepths[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?) + // コンタクトバッファをリストに変換 + // ここは並列化できない + var selfStep_ConvertContactList_job = new SelfCollisionConstraint.SelfStep_ConvertContactListJob() + { + contactQueue = selfCollisionConstraint.contactQueue, + contactList = selfCollisionConstraint.contactList, + }; + splitClothJobHandle = selfStep_ConvertContactList_job.Schedule(splitClothJobHandle); } else { - // 接線速度に応じて係数を減少 - var vel = tangentVelocity - staticFrictionParam; - var value = math.max(vel / 0.2f, 0.05f); - staticFriction = math.saturate(staticFriction - value); + // ■2ステップ以降 + // コンタクトバッファごと + // 現在のnextPos/oldPosから変位を求め衝突の有無とs/t/nなどを求める + // aabbは更新なし + var selfStep_UpdateContact_job = new SelfCollisionConstraint.SelfStep_UpdateContactJob() + { + first = updateIndex == 0, + //first = true, + contactList = selfCollisionConstraint.contactList, + // particle + nextPosArray = nextPosArray.GetNativeArray(), + oldPosArray = oldPosArray.GetNativeArray(), + // self collision + primitiveArrayB = selfCollisionConstraint.primitiveArrayB.GetNativeArray(), + }; + splitClothJobHandle = selfStep_UpdateContact_job.Schedule(selfCollisionConstraint.contactList, 256, splitClothJobHandle); } - // 接線方向に位置を巻き戻す - tanv *= staticFriction; - nextPos -= tanv; - velocityOldPos -= tanv; + // セルフコリジョン + // コンタクトバッファ解決(反復) + for (int i = 0; i < Define.System.SelfCollisionSolverIteration; i++) + { + // コンタクトバッファ解決 + // コンタクトバッファごと + var selfStep_SolverContact_job = new SelfCollisionConstraint.SelfStep_SolverContactJob() + { + // particle + nextPosArray = nextPosArray.GetNativeArray(), + // self collision + primitiveArrayB = selfCollisionConstraint.primitiveArrayB.GetNativeArray(), + contactList = selfCollisionConstraint.contactList, + // buffer2 + tempVectorBufferA = tempVectorBufferA, + tempCountBuffer = tempCountBuffer, + }; + splitClothJobHandle = selfStep_SolverContact_job.Schedule(selfCollisionConstraint.contactList, 128, splitClothJobHandle); + + // 集計 + // チームごと + var selfStep_SumContact_job = new SelfCollisionConstraint.SelfStep_SumContactJob() + { + updateIndex = updateIndex, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + // particle + nextPosArray = nextPosArray.GetNativeArray(), + // buffer2 + tempVectorBufferA = tempVectorBufferA, + tempCountBuffer = tempCountBuffer, + }; + splitClothJobHandle = selfStep_SumContact_job.Schedule(splitClothTeamCount, 1, splitClothJobHandle); + } + + // 座標確定 + // コライダーの後更新 + var splitStep_G_Self_job = new SplitStep_G_Self_Job() + { + workerCount = workerCount, + updateIndex = updateIndex, + simulationDeltaTime = tim.SimulationDeltaTime, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + centerDataArray = tm.centerDataArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + // vmesh + attributes = vm.attributes.GetNativeArray(), + depthArray = vm.vertexDepths.GetNativeArray(), + // particle + nextPosArray = nextPosArray.GetNativeArray(), + oldPosArray = oldPosArray.GetNativeArray(), + velocityPosArray = velocityPosArray.GetNativeArray(), + velocityArray = velocityArray.GetNativeArray(), + realVelocityArray = realVelocityArray.GetNativeArray(), + frictionArray = frictionArray.GetNativeArray(), + staticFrictionArray = staticFrictionArray.GetNativeArray(), + collisionNormalArray = collisionNormalArray.GetNativeArray(), + // collider + colliderNowPositions = cm.nowPositions.GetNativeArray(), + colliderNowRotations = cm.nowRotations.GetNativeArray(), + colliderOldPositions = cm.oldPositions.GetNativeArray(), + colliderOldRotations = cm.oldRotations.GetNativeArray(), + }; + splitClothJobHandle = splitStep_G_Self_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); } 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) + // ■セルフコリジョンなし + // コライダーコリジョンEdge集計 + // 距離 + // モーション + // 座標確定 + // コライダーの後更新 + var splitStep_FG_NoSelf_job = new SplitStep_FG_NoSelf_Job() { - 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); - } + workerCount = workerCount, + updateIndex = updateIndex, + simulationPower = tim.SimulationPower, + simulationDeltaTime = tim.SimulationDeltaTime, + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + centerDataArray = tm.centerDataArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + // vmesh + attributes = vm.attributes.GetNativeArray(), + depthArray = vm.vertexDepths.GetNativeArray(), + // particle + nextPosArray = nextPosArray.GetNativeArray(), + oldPosArray = oldPosArray.GetNativeArray(), + basePosArray = basePosArray.GetNativeArray(), + baseRotArray = baseRotArray.GetNativeArray(), + velocityPosArray = velocityPosArray.GetNativeArray(), + velocityArray = velocityArray.GetNativeArray(), + realVelocityArray = realVelocityArray.GetNativeArray(), + frictionArray = frictionArray.GetNativeArray(), + staticFrictionArray = staticFrictionArray.GetNativeArray(), + collisionNormalArray = collisionNormalArray.GetNativeArray(), + // collider + colliderNowPositions = cm.nowPositions.GetNativeArray(), + colliderNowRotations = cm.nowRotations.GetNativeArray(), + colliderOldPositions = cm.oldPositions.GetNativeArray(), + colliderOldRotations = cm.oldRotations.GetNativeArray(), + // distance + distanceIndexArray = distanceConstraint.indexArray.GetNativeArray(), + distanceDataArray = distanceConstraint.dataArray.GetNativeArray(), + distanceDistanceArray = distanceConstraint.distanceArray.GetNativeArray(), + // buffer2 + tempVectorBufferA = tempVectorBufferA, + tempVectorBufferB = tempVectorBufferB, + tempCountBuffer = tempCountBuffer, + tempFloatBufferA = tempFloatBufferA, + }; + splitClothJobHandle = splitStep_FG_NoSelf_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); } -#endif - // 安定化用の速度割合 - velocity *= tdata.velocityWeight; - - // 書き戻し - velocityArray[pindex] = velocity; } - // 実速度 - float3 realVelocity = (nextPos - oldPos) / simulationDeltaTime; - realVelocityArray[pindex] = realVelocity; - //Debug.Log($"[{pindex}] realVelocity:{realVelocity}"); + // シミュレーション後処理 + // 表示位置の計算 + var splitPost_DisplayPos_job = new SplitPost_DisplayPos_Job() + { + workerCount = workerCount, + simulationDeltaTime = MagicaManager.Time.SimulationDeltaTime, - // 今回の予測位置を記録 - oldPosArray[pindex] = nextPos; + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + + // vmesh + attributes = vm.attributes.GetNativeArray(), + positions = vm.positions.GetNativeArray(), + rotations = vm.rotations.GetNativeArray(), + vertexRootIndices = vm.vertexRootIndices.GetNativeArray(), + + // particle + oldPosArray = oldPosArray.GetNativeArray(), + oldPositionArray = oldPositionArray.GetNativeArray(), + oldRotationArray = oldRotationArray.GetNativeArray(), + dispPosArray = dispPosArray.GetNativeArray(), + realVelocityArray = realVelocityArray.GetNativeArray(), + }; + splitClothJobHandle = splitPost_DisplayPos_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); + + // 並行でインターセクトの解決を行う + // インターセクトの結果は次のフレームで利用される + if (useIntersectJob) + { + // インターセクトバッファクリア + var self_ClearIntersect_job = new SelfCollisionConstraint.SelfClearIntersectJob() + { + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + // self collision + intersectFlagArray = selfCollisionConstraint.intersectFlagArray, + }; + solverIntersectJobHandle = self_ClearIntersect_job.Schedule(splitClothTeamCount, 1, splitClothJobHandle); + + // インターセクトバッファ解決 + var self_SolverIntersect_job = new SelfCollisionConstraint.SelfSolverIntersectJob() + { + // particle + nextPosArray = nextPosArray.GetNativeArray(), + // self collision + intersectList = selfCollisionConstraint.intersectList, + // buffer + intersectFlagArray = selfCollisionConstraint.intersectFlagArray, + }; + solverIntersectJobHandle = self_SolverIntersect_job.Schedule(selfCollisionConstraint.intersectList, 128, solverIntersectJobHandle); + } + + // クロスシミュレーションの結果をProxyMeshへ反映させる + // ラインがある場合はベースラインごとに姿勢を整える + var splitPost_CalcProxy_job = new SplitPost_CalcProxy_Job() + { + workerCount = workerCount, + + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), + + // vmesh + attributes = vm.attributes.GetNativeArray(), + positions = vm.positions.GetNativeArray(), + rotations = vm.rotations.GetNativeArray(), + baseLineStartDataIndices = vm.baseLineStartDataIndices.GetNativeArray(), + baseLineDataCounts = vm.baseLineDataCounts.GetNativeArray(), + baseLineData = vm.baseLineData.GetNativeArray(), + vertexLocalPositions = vm.vertexLocalPositions.GetNativeArray(), + vertexLocalRotations = vm.vertexLocalRotations.GetNativeArray(), + vertexChildIndexArray = vm.vertexChildIndexArray.GetNativeArray(), + vertexChildDataArray = vm.vertexChildDataArray.GetNativeArray(), + baseLineFlags = vm.baseLineFlags.GetNativeArray(), + }; + splitClothJobHandle = splitPost_CalcProxy_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); + + // トライアングルの法線接線を求める + var splitPost_CalcProxyTriangle_job = new SplitPost_CalcProxyTriangle_Job() + { + workerCount = workerCount, + + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + + // vmesh + positions = vm.positions.GetNativeArray(), + triangles = vm.triangles.GetNativeArray(), + triangleNormals = vm.triangleNormals.GetNativeArray(), + triangleTangents = vm.triangleTangents.GetNativeArray(), + uvs = vm.uv.GetNativeArray(), + }; + splitClothJobHandle = splitPost_CalcProxyTriangle_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); + + // トライアングルの法線接線から頂点の姿勢を求める + // BoneClothの場合は頂点姿勢から連動するトランスフォームのワールド姿勢を計算する + var splitPost_SumProxyTriangleAndTransform_job = new SplitPost_SumProxyTriangleAndTransform_Job() + { + workerCount = workerCount, + + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + + // transform + transformPositionArray = bm.positionArray.GetNativeArray(), + transformRotationArray = bm.rotationArray.GetNativeArray(), + + // vmesh + positions = vm.positions.GetNativeArray(), + rotations = vm.rotations.GetNativeArray(), + triangleNormals = vm.triangleNormals.GetNativeArray(), + triangleTangents = vm.triangleTangents.GetNativeArray(), + vertexToTriangles = vm.vertexToTriangles.GetNativeArray(), + normalAdjustmentRotations = vm.normalAdjustmentRotations.GetNativeArray(), + vertexToTransformRotations = vm.vertexToTransformRotations.GetNativeArray(), + }; + splitClothJobHandle = splitPost_SumProxyTriangleAndTransform_job.Schedule(splitClothTeamCount * workerCount, 1, splitClothJobHandle); + + // チーム更新後処理 + // BoneClothの場合はTransformのローカル姿勢を計算する + // コライダー更新後処理 + var splitPost_TeamCollider_job = new SplitPost_TeamCollider_Job() + { + simulationDeltaTime = MagicaManager.Time.SimulationDeltaTime, + + // team + batchSelfTeamList = tm.batchSplitClothTeamList, + teamDataArray = tm.teamDataArray.GetNativeArray(), + centerDataArray = tm.centerDataArray.GetNativeArray(), + + // collider + colliderFramePositions = cm.framePositions.GetNativeArray(), + colliderFrameRotations = cm.frameRotations.GetNativeArray(), + colliderOldFramePositions = cm.oldFramePositions.GetNativeArray(), + colliderOldFrameRotations = cm.oldFrameRotations.GetNativeArray(), + + // transform + transformPositionArray = bm.positionArray.GetNativeArray(), + transformRotationArray = bm.rotationArray.GetNativeArray(), + transformScaleArray = bm.scaleArray.GetNativeArray(), + transformLocalPositionArray = bm.localPositionArray.GetNativeArray(), + transformLocalRotationArray = bm.localRotationArray.GetNativeArray(), + + // vmesh + attributes = vm.attributes.GetNativeArray(), + vertexParentIndices = vm.vertexParentIndices.GetNativeArray(), + }; + splitClothJobHandle = splitPost_TeamCollider_job.Schedule(splitClothTeamCount, 1, splitClothJobHandle); + + // 最後にインターセクトの解決ジョブを合流 + if (useIntersectJob) + { + splitClothJobHandle = JobHandle.CombineDependencies(splitClothJobHandle, solverIntersectJobHandle); + } } - } - //========================================================================================= - /// - /// シミュレーション完了後の表示位置の計算 - /// - 未来予測 - /// - /// - /// - internal JobHandle CalcDisplayPosition(JobHandle jobHandle) - { - // ここではproxyMeshのpositionsのみを更新する - // rotationsは自動で計算されるため - var job = new CalcDisplayPositionJob() + // ■一括シミュレーションジョブ + // セルフコリジョンなし、かつプロキシメッシュの頂点数が一定値未満のジョブ + // 1つの巨大なジョブ内ですべてを完結させる + if (useNormalClothJob) { - simulationDeltaTime = MagicaManager.Time.SimulationDeltaTime, + var normalJob = new SimulationNormalJob() + { + batchNormalTeamList = tm.batchNormalClothTeamList, + simulationPower = tim.SimulationPower, + simulationDeltaTime = tim.SimulationDeltaTime, + mappingCount = tm.MappingCount, - teamDataArray = MagicaManager.Team.teamDataArray.GetNativeArray(), + // team + teamDataArray = tm.teamDataArray.GetNativeArray(), + centerDataArray = tm.centerDataArray.GetNativeArray(), + teamWindArray = tm.teamWindArray.GetNativeArray(), + parameterArray = tm.parameterArray.GetNativeArray(), - teamIdArray = teamIdArray.GetNativeArray(), - oldPosArray = oldPosArray.GetNativeArray(), - realVelocityArray = realVelocityArray.GetNativeArray(), - oldPositionArray = oldPositionArray.GetNativeArray(), - oldRotationArray = oldRotationArray.GetNativeArray(), - dispPosArray = dispPosArray.GetNativeArray(), + // wind + windZoneCount = wm.WindCount, + windDataArray = wm.windDataArray.GetNativeArray(), - attributes = MagicaManager.VMesh.attributes.GetNativeArray(), - positions = MagicaManager.VMesh.positions.GetNativeArray(), - rotations = MagicaManager.VMesh.rotations.GetNativeArray(), - }; - jobHandle = job.Schedule(ParticleCount, 32, jobHandle); + // transform + transformPositionArray = bm.positionArray.GetNativeArray(), + transformRotationArray = bm.rotationArray.GetNativeArray(), + transformScaleArray = bm.scaleArray.GetNativeArray(), + transformLocalToWorldMatrixArray = bm.localToWorldMatrixArray.GetNativeArray(), + transformLocalPositionArray = bm.localPositionArray.GetNativeArray(), + transformLocalRotationArray = bm.localRotationArray.GetNativeArray(), + transformLocalScaleArray = bm.localScaleArray.GetNativeArray(), + + // vmesh + attributes = vm.attributes.GetNativeArray(), + depthArray = vm.vertexDepths.GetNativeArray(), + localPositions = vm.localPositions.GetNativeArray(), + localNormals = vm.localNormals.GetNativeArray(), + localTangents = vm.localTangents.GetNativeArray(), + boneWeights = vm.boneWeights.GetNativeArray(), + skinBoneTransformIndices = vm.skinBoneTransformIndices.GetNativeArray(), + skinBoneBindPoses = vm.skinBoneBindPoses.GetNativeArray(), + positions = vm.positions.GetNativeArray(), + rotations = vm.rotations.GetNativeArray(), + vertexBindPoseRotations = vm.vertexBindPoseRotations.GetNativeArray(), + vertexDepths = vm.vertexDepths.GetNativeArray(), + vertexRootIndices = vm.vertexRootIndices.GetNativeArray(), + vertexParentIndices = vm.vertexParentIndices.GetNativeArray(), + baseLineStartDataIndices = vm.baseLineStartDataIndices.GetNativeArray(), + baseLineDataCounts = vm.baseLineDataCounts.GetNativeArray(), + baseLineData = vm.baseLineData.GetNativeArray(), + vertexLocalPositions = vm.vertexLocalPositions.GetNativeArray(), + vertexLocalRotations = vm.vertexLocalRotations.GetNativeArray(), + vertexChildIndexArray = vm.vertexChildIndexArray.GetNativeArray(), + vertexChildDataArray = vm.vertexChildDataArray.GetNativeArray(), + baseLineFlags = vm.baseLineFlags.GetNativeArray(), + triangles = vm.triangles.GetNativeArray(), + triangleNormals = vm.triangleNormals.GetNativeArray(), + triangleTangents = vm.triangleTangents.GetNativeArray(), + uvs = vm.uv.GetNativeArray(), + vertexToTriangles = vm.vertexToTriangles.GetNativeArray(), + normalAdjustmentRotations = vm.normalAdjustmentRotations.GetNativeArray(), + vertexToTransformRotations = vm.vertexToTransformRotations.GetNativeArray(), + edges = vm.edges.GetNativeArray(), + + // particle + nextPosArray = nextPosArray.GetNativeArray(), + oldPosArray = oldPosArray.GetNativeArray(), + oldRotArray = oldRotArray.GetNativeArray(), + basePosArray = basePosArray.GetNativeArray(), + baseRotArray = baseRotArray.GetNativeArray(), + oldPositionArray = oldPositionArray.GetNativeArray(), + oldRotationArray = oldRotationArray.GetNativeArray(), + velocityPosArray = velocityPosArray.GetNativeArray(), + dispPosArray = dispPosArray.GetNativeArray(), + velocityArray = velocityArray.GetNativeArray(), + realVelocityArray = realVelocityArray.GetNativeArray(), + frictionArray = frictionArray.GetNativeArray(), + staticFrictionArray = staticFrictionArray.GetNativeArray(), + collisionNormalArray = collisionNormalArray.GetNativeArray(), + + // collider + colliderFlagArray = cm.flagArray.GetNativeArray(), + colliderCenterArray = cm.centerArray.GetNativeArray(), + colliderSizeArray = cm.sizeArray.GetNativeArray(), + colliderFramePositions = cm.framePositions.GetNativeArray(), + colliderFrameRotations = cm.frameRotations.GetNativeArray(), + colliderFrameScales = cm.frameScales.GetNativeArray(), + colliderOldFramePositions = cm.oldFramePositions.GetNativeArray(), + colliderOldFrameRotations = cm.oldFrameRotations.GetNativeArray(), + colliderNowPositions = cm.nowPositions.GetNativeArray(), + colliderNowRotations = cm.nowRotations.GetNativeArray(), + colliderOldPositions = cm.oldPositions.GetNativeArray(), + colliderOldRotations = cm.oldRotations.GetNativeArray(), + colliderWorkDataArray = cm.workDataArray.GetNativeArray(), + colliderMainColliderIndices = cm.mainColliderIndices.GetNativeArray(), + + // inertia + fixedArray = inertiaConstraint.fixedArray.GetNativeArray(), + + // distance + distanceIndexArray = distanceConstraint.indexArray.GetNativeArray(), + distanceDataArray = distanceConstraint.dataArray.GetNativeArray(), + distanceDistanceArray = distanceConstraint.distanceArray.GetNativeArray(), + + // triangleBending + bendingTrianglePairArray = bendingConstraint.trianglePairArray.GetNativeArray(), + bendingRestAngleOrVolumeArray = bendingConstraint.restAngleOrVolumeArray.GetNativeArray(), + bendingSignOrVolumeArray = bendingConstraint.signOrVolumeArray.GetNativeArray(), + + // buffer + stepBasicPositionBuffer = stepBasicPositionBuffer, + stepBasicRotationBuffer = stepBasicRotationBuffer, + + // buffer2 + tempVectorBufferA = tempVectorBufferA, + tempVectorBufferB = tempVectorBufferB, + tempCountBuffer = tempCountBuffer, + tempFloatBufferA = tempFloatBufferA, + tempRotationBufferA = tempRotationBufferA, + tempRotationBufferB = tempRotationBufferB, + }; + normalClothJobHandle = normalJob.Schedule(normalClothTeamCount, 1, jobHandle); + } + + // ■ジョブ連結 + // !一括ジョブと分割ジョブを並行動作させる + jobHandle = JobHandle.CombineDependencies(splitClothJobHandle, normalClothJobHandle); + + // マッピングメッシュの有無で分岐 + if (MagicaManager.Team.MappingCount > 0) + { + // この2つのジョブは並列動作可能 + // ■マッピングメッシュの頂点姿勢を連動するプロキシメッシュからスキニングして求める + var job1 = vm.PostMappingMeshUpdateBatchSchedule(jobHandle, workerCount); + + // ■BoneClothのTransformへの書き込み + var job2 = bm.WriteTransformSchedule(jobHandle); + + jobHandle = JobHandle.CombineDependencies(job1, job2); + } + else + { + // ■BoneClothのTransformへの書き込み + jobHandle = bm.WriteTransformSchedule(jobHandle); + } return jobHandle; } - [BurstCompile] - struct CalcDisplayPositionJob : IJobParallelFor - { - public float simulationDeltaTime; - - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - - // particle - [Unity.Collections.ReadOnly] - public NativeArray teamIdArray; - [Unity.Collections.ReadOnly] - public NativeArray oldPosArray; - [Unity.Collections.ReadOnly] - public NativeArray realVelocityArray; - [Unity.Collections.WriteOnly] - public NativeArray oldPositionArray; - [Unity.Collections.WriteOnly] - public NativeArray oldRotationArray; - public NativeArray dispPosArray; - - // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [NativeDisableParallelForRestriction] - public NativeArray positions; - [Unity.Collections.ReadOnly] - public NativeArray rotations; - - // すべてのパーティクルごと - public void Execute(int pindex) - { - int teamId = teamIdArray[pindex]; - if (teamId == 0) - return; - - var tdata = teamDataArray[teamId]; - if (tdata.IsProcess == false) - return; - - // ■この処理は更新に関係なく実行する - - int l_index = pindex - tdata.particleChunk.startIndex; - int vindex = tdata.proxyCommonChunk.startIndex + l_index; - - var attr = attributes[vindex]; - //if (attr.IsInvalid()) - // return; - - var pos = positions[vindex]; - var rot = rotations[vindex]; - - if (attr.IsMove() || tdata.IsSpring) - { - // 移動パーティクル - var dpos = oldPosArray[pindex]; - -#if true - // 未来予測 - // 最終計算位置と実速度から次のステップ位置を予測し、その間のフレーム時間位置を表示位置とする - float3 velocity = realVelocityArray[pindex] * simulationDeltaTime; - float3 fpos = dpos + velocity; - float interval = (tdata.nowUpdateTime + simulationDeltaTime) - tdata.oldTime; - //float t = (tdata.time - tdata.oldTime) / interval; - float t = interval > 0.0f ? (tdata.time - tdata.oldTime) / interval : 0.0f; - fpos = math.lerp(dispPosArray[pindex], fpos, t); - 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; - } - } - } - - //========================================================================================= - /// - /// tempFloat3Bufferの内容をnextPosArrayに書き戻す - /// - /// - /// - /// - internal JobHandle FeedbackTempFloat3Buffer(in NativeList particleList, JobHandle jobHandle) - { - var job = new FeedbackTempPosJob() - { - jobParticleIndexList = particleList, - tempFloat3Buffer = tempFloat3Buffer, - nextPosArray = nextPosArray.GetNativeArray(), - }; - jobHandle = job.Schedule(particleList, 32, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct FeedbackTempPosJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeList jobParticleIndexList; - - [Unity.Collections.ReadOnly] - public NativeArray tempFloat3Buffer; - - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - - public void Execute(int index) - { - int pindex = jobParticleIndexList[index]; - nextPosArray[pindex] = tempFloat3Buffer[pindex]; - } - } - - internal JobHandle FeedbackTempFloat3Buffer(in ExProcessingList processingList, JobHandle jobHandle) - { - return FeedbackTempFloat3Buffer(processingList.Buffer, processingList.Counter, jobHandle); - } - - unsafe internal JobHandle FeedbackTempFloat3Buffer(in NativeArray particleArray, in NativeReference counter, JobHandle jobHandle) - { - var job = new FeedbackTempPosJob2() - { - particleIndexArray = particleArray, - tempFloat3Buffer = tempFloat3Buffer, - nextPosArray = nextPosArray.GetNativeArray(), - }; - jobHandle = job.Schedule((int*)counter.GetUnsafePtrWithoutChecks(), 32, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct FeedbackTempPosJob2 : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray particleIndexArray; - - [Unity.Collections.ReadOnly] - public NativeArray tempFloat3Buffer; - - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - - public void Execute(int index) - { - int pindex = particleIndexArray[index]; - nextPosArray[pindex] = tempFloat3Buffer[pindex]; - } - } - //========================================================================================= public void InformationLog(StringBuilder allsb) { @@ -2020,23 +1443,15 @@ namespace MagicaCloth2 sb.Append(selfCollisionConstraint.ToString()); // 汎用バッファ - sb.AppendLine($"[Step Buffer]"); - sb.AppendLine($" -processingStepParticle:{processingStepParticle}"); - sb.AppendLine($" -processingStepTriangleBending:{processingStepTriangleBending}"); - sb.AppendLine($" -processingStepEdgeCollision:{processingStepEdgeCollision}"); - sb.AppendLine($" -processingStepCollider:{processingStepCollider}"); - sb.AppendLine($" -processingStepBaseLine:{processingStepBaseLine}"); - sb.AppendLine($" -processingStepMotionParticle:{processingStepMotionParticle}"); - sb.AppendLine($" -processingSelfParticle:{processingSelfParticle}"); - sb.AppendLine($" -processingSelfPointTriangle:{processingSelfPointTriangle}"); - sb.AppendLine($" -processingSelfEdgeEdge:{processingSelfEdgeEdge}"); - sb.AppendLine($" -processingSelfTrianglePoint:{processingSelfTrianglePoint}"); sb.AppendLine($"[Buffer]"); - sb.AppendLine($" -tempFloat3Buffer:{(tempFloat3Buffer.IsCreated ? tempFloat3Buffer.Length : 0)}"); - sb.AppendLine($" -countArray:{(countArray.IsCreated ? countArray.Length : 0)}"); - sb.AppendLine($" -sumArray:{(sumArray.IsCreated ? sumArray.Length : 0)}"); sb.AppendLine($" -stepBasicPositionBuffer:{(stepBasicPositionBuffer.IsCreated ? stepBasicPositionBuffer.Length : 0)}"); sb.AppendLine($" -stepBasicRotationBuffer:{(stepBasicRotationBuffer.IsCreated ? stepBasicRotationBuffer.Length : 0)}"); + sb.AppendLine($" -tempVectorBufferA:{(tempVectorBufferA.IsCreated ? tempVectorBufferA.Length : 0)}"); + sb.AppendLine($" -tempVectorBufferB:{(tempVectorBufferB.IsCreated ? tempVectorBufferB.Length : 0)}"); + sb.AppendLine($" -tempCountBuffer:{(tempCountBuffer.IsCreated ? tempCountBuffer.Length : 0)}"); + sb.AppendLine($" -tempFloatBufferA:{(tempFloatBufferA.IsCreated ? tempFloatBufferA.Length : 0)}"); + sb.AppendLine($" -tempRotationBufferA:{(tempRotationBufferA.IsCreated ? tempRotationBufferA.Length : 0)}"); + sb.AppendLine($" -tempRotationBufferB:{(tempRotationBufferB.IsCreated ? tempRotationBufferB.Length : 0)}"); sb.AppendLine(); } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManager.cs.meta index 2b78b3e3..433b5c39 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManager.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManager.cs + uploadId: 756593 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 00000000..ed19e8f4 --- /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 00000000..ea86d1c5 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerNormal.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 1678d975c7bf0f343bf9eb89afc158fe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerNormal.cs + uploadId: 756593 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 00000000..6ae48879 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs @@ -0,0 +1,2335 @@ +// Magica Cloth 2. +// Copyright (c) 2025 MagicaSoft. +// https://magicasoft.jp +using Unity.Burst; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Jobs; +using Unity.Mathematics; + +namespace MagicaCloth2 +{ + /// + /// Split + /// セルフコリジョンあり、もしくはプロキシメッシュの頂点数が一定値以上のジョブ + /// オリジナルと同様にジョブを分割し同期しながら実行する + /// ただし最適化を行いオリジナルより軽量化している + /// + public partial class SimulationManager + { + /// + /// プロキシメッシュをスキニングし基本姿勢を求める + /// + [BurstCompile] + unsafe struct SplitPre_A_Job : IJobParallelFor + { + public int workerCount; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + + // transform + [Unity.Collections.ReadOnly] + public NativeArray transformLocalToWorldMatrixArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray localPositions; + [Unity.Collections.ReadOnly] + public NativeArray localNormals; + [Unity.Collections.ReadOnly] + public NativeArray localTangents; + [Unity.Collections.ReadOnly] + public NativeArray boneWeights; + [Unity.Collections.ReadOnly] + public NativeArray skinBoneTransformIndices; + [Unity.Collections.ReadOnly] + public NativeArray skinBoneBindPoses; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray positions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray rotations; + + // バッチ内のローカルチームインデックスごと + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + //Debug.Log(localIndex); + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + + //Debug.Log($"{localIndex}, {teamId}"); + + ref var tdata = ref *(teamPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.proxyCommonChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + // ■プロキシメッシュをスキニングし基本姿勢を求める + VirtualMeshManager.SimulationPreProxyMeshUpdate( + //new DataChunk(0, tdata.proxyCommonChunk.dataLength), + chunk, + // team + teamId, + ref tdata, + // vmesh + attributes, + localPositions, + localNormals, + localTangents, + boneWeights, + skinBoneTransformIndices, + skinBoneBindPoses, + ref positions, + ref rotations, + // transform + transformLocalToWorldMatrixArray + ); + } + } + + /// + /// チームのセンター姿勢の決定と慣性用の移動量計算 + /// + [BurstCompile] + unsafe struct SplitPre_B_Job : IJobParallelFor + { + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray teamDataArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray centerDataArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray teamWindArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // wind + public int windZoneCount; + [Unity.Collections.ReadOnly] + public NativeArray windDataArray; + + // transform + [Unity.Collections.ReadOnly] + public NativeArray transformPositionArray; + [Unity.Collections.ReadOnly] + public NativeArray transformRotationArray; + [Unity.Collections.ReadOnly] + public NativeArray transformScaleArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray positions; + [Unity.Collections.ReadOnly] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexBindPoseRotations; + + + // inertia + [Unity.Collections.ReadOnly] + public NativeArray fixedArray; + + // バッチ内のローカルチームインデックスごと + public void Execute(int localIndex) + { + //Debug.Log(localIndex); + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafePtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafePtr(); + TeamWindData* windPt = (TeamWindData*)teamWindArray.GetUnsafePtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + ref var wdata = ref *(windPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // チームのセンター姿勢の決定と慣性用の移動量計算 + TeamManager.SimulationCalcCenterAndInertiaAndWind( + simulationDeltaTime, + // team + teamId, + ref tdata, + ref cdata, + ref wdata, + ref param, + // vmesh + positions, + rotations, + vertexBindPoseRotations, + // inertia + fixedArray, + // transform + transformPositionArray, + transformRotationArray, + transformScaleArray, + // wind + windZoneCount, + windDataArray + ); + } + } + + /// + /// パーティクルの全体慣性およびリセットの適用 + /// コライダーのローカル姿勢を求める、および全体慣性とリセットの適用 + /// + [BurstCompile] + unsafe struct SplitPre_C_Job : IJobParallelFor + { + public int workerCount; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray centerDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // transform + [Unity.Collections.ReadOnly] + public NativeArray transformPositionArray; + [Unity.Collections.ReadOnly] + public NativeArray transformRotationArray; + [Unity.Collections.ReadOnly] + public NativeArray transformScaleArray; + [Unity.Collections.ReadOnly] + public NativeArray transformLocalPositionArray; + [Unity.Collections.ReadOnly] + public NativeArray transformLocalRotationArray; + [Unity.Collections.ReadOnly] + public NativeArray transformLocalScaleArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray positions; + [Unity.Collections.ReadOnly] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexDepths; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldRotArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray basePosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray baseRotArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldPositionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldRotationArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray dispPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray realVelocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray frictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray staticFrictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray collisionNormalArray; + + // collider + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderFlagArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderCenterArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderFramePositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderFrameRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderFrameScales; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldFramePositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldFrameRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderNowPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderNowRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldRotations; + [Unity.Collections.ReadOnly] + public NativeArray colliderMainColliderIndices; + + // バッチ内のローカルチームインデックスごと + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + //Debug.Log(localIndex); + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // パーティクルの全体慣性およびリセットの適用 + var p_chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (p_chunk.IsValid) + { + SimulationPreTeamUpdate( + p_chunk, + // team + ref tdata, + param, + cdata, + // vmesh + positions, + rotations, + vertexDepths, + // particle + ref nextPosArray, + ref oldPosArray, + ref oldRotArray, + ref basePosArray, + ref baseRotArray, + ref oldPositionArray, + ref oldRotationArray, + ref velocityPosArray, + ref dispPosArray, + ref velocityArray, + ref realVelocityArray, + ref frictionArray, + ref staticFrictionArray, + ref collisionNormalArray + ); + } + + // ■コライダーのローカル姿勢を求める、および全体慣性とリセットの適用 + if (tdata.colliderCount > 0) + { + var c_chunk = MathUtility.GetWorkerChunk(tdata.colliderChunk.dataLength, workerCount, workerIndex); + if (c_chunk.IsValid) + { + ColliderManager.SimulationPreUpdate( + c_chunk, + // team + ref tdata, + ref cdata, + // collider + ref colliderFlagArray, + ref colliderCenterArray, + ref colliderFramePositions, + ref colliderFrameRotations, + ref colliderFrameScales, + ref colliderOldFramePositions, + ref colliderOldFrameRotations, + ref colliderNowPositions, + ref colliderNowRotations, + ref colliderOldPositions, + ref colliderOldRotations, + ref colliderMainColliderIndices, + // transform + ref transformPositionArray, + ref transformRotationArray, + ref transformScaleArray, + ref transformLocalPositionArray, + ref transformLocalRotationArray, + ref transformLocalScaleArray + ); + } + } + } + } + + /// + /// チーム更新 + /// コライダーの更新 + /// + [BurstCompile] + unsafe struct SplitStep_A_Job : IJobParallelFor + { + public int updateIndex; + public float4 simulationPower; + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray teamDataArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray centerDataArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray teamWindArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // collider + [Unity.Collections.ReadOnly] + public NativeArray colliderFlagArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderSizeArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderFramePositions; + [Unity.Collections.ReadOnly] + public NativeArray colliderFrameRotations; + [Unity.Collections.ReadOnly] + public NativeArray colliderFrameScales; + [Unity.Collections.ReadOnly] + public NativeArray colliderOldFramePositions; + [Unity.Collections.ReadOnly] + public NativeArray colliderOldFrameRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderNowPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderNowRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderWorkDataArray; + + // バッチ内のローカルチームインデックスごと + public void Execute(int localIndex) + { + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafePtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafePtr(); + TeamWindData* windPt = (TeamWindData*)teamWindArray.GetUnsafePtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + ref var wdata = ref *(windPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // ステップ実行 + // ステップごとのチーム更新 + TeamManager.SimulationStepTeamUpdate( + updateIndex, + simulationDeltaTime, + // team + teamId, + ref tdata, + ref param, + ref cdata, + ref wdata + ); + + // コライダーの更新 + if (tdata.colliderCount > 0) + { + ColliderManager.SimulationStartStep( + // team + ref tdata, + ref cdata, + // collider + ref colliderFlagArray, + ref colliderSizeArray, + ref colliderFramePositions, + ref colliderFrameRotations, + ref colliderFrameScales, + ref colliderOldFramePositions, + ref colliderOldFrameRotations, + ref colliderNowPositions, + ref colliderNowRotations, + ref colliderOldPositions, + ref colliderOldRotations, + ref colliderWorkDataArray + ); + } + } + } + + /// + /// 速度更新、外力の影響、慣性シフト + /// + [BurstCompile] + unsafe struct SplitStep_B_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray centerDataArray; + [Unity.Collections.ReadOnly] + public NativeArray teamWindArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // wind + public int windZoneCount; + [Unity.Collections.ReadOnly] + public NativeArray windDataArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + [Unity.Collections.ReadOnly] + public NativeArray positions; + [Unity.Collections.ReadOnly] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexRootIndices; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [Unity.Collections.ReadOnly] + public NativeArray oldPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray basePosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray baseRotArray; + [Unity.Collections.ReadOnly] + public NativeArray oldPositionArray; + [Unity.Collections.ReadOnly] + public NativeArray oldRotationArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [Unity.Collections.ReadOnly] + public NativeArray velocityArray; + [Unity.Collections.ReadOnly] + public NativeArray frictionArray; + + // buffer + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray stepBasicPositionBuffer; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray stepBasicRotationBuffer; + + // バッチ内のローカルチームインデックスごと + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafeReadOnlyPtr(); + TeamWindData* windPt = (TeamWindData*)teamWindArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + ref var wdata = ref *(windPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + // 速度更新、外力の影響、慣性シフト + SimulationStepUpdateParticles( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + simulationPower, + simulationDeltaTime, + // team + teamId, + ref tdata, + ref cdata, + ref param, + ref wdata, + // wind + ref windDataArray, + // vmesh + ref attributes, + ref depthArray, + ref positions, + ref rotations, + ref vertexRootIndices, + // particle + ref nextPosArray, + ref oldPosArray, + ref basePosArray, + ref baseRotArray, + ref oldPositionArray, + ref oldRotationArray, + ref velocityPosArray, + ref velocityArray, + ref frictionArray, + // buffer + ref stepBasicPositionBuffer, + ref stepBasicRotationBuffer + ); + } + } + + /// + /// ベースラインの基準姿勢を計算 + /// + [BurstCompile] + unsafe struct SplitStep_C_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray vertexRootIndices; + [Unity.Collections.ReadOnly] + public NativeArray vertexParentIndices; + [Unity.Collections.ReadOnly] + public NativeArray baseLineStartDataIndices; + [Unity.Collections.ReadOnly] + public NativeArray baseLineDataCounts; + [Unity.Collections.ReadOnly] + public NativeArray baseLineData; + [Unity.Collections.ReadOnly] + public NativeArray vertexLocalPositions; + [Unity.Collections.ReadOnly] + public NativeArray vertexLocalRotations; + + // particle + [Unity.Collections.ReadOnly] + public NativeArray basePosArray; + [Unity.Collections.ReadOnly] + public NativeArray baseRotArray; + + // buffer + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray stepBasicPositionBuffer; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray stepBasicRotationBuffer; + + // バッチ内のローカルチームインデックスごと + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.baseLineChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + // 制約解決のためのステップごとの基準姿勢を計算 + // ベースラインごと + // アニメーションポーズ使用の有無 + SimulationStepUpdateBaseLinePose( + //new DataChunk(0, tdata.baseLineChunk.dataLength), + chunk, + // team + ref tdata, + // vmesh + ref attributes, + ref vertexParentIndices, + ref baseLineStartDataIndices, + ref baseLineDataCounts, + ref baseLineData, + ref vertexLocalPositions, + ref vertexLocalRotations, + // particle + ref basePosArray, + ref baseRotArray, + // buffer + ref stepBasicPositionBuffer, + ref stepBasicRotationBuffer + ); + } + } + + /// + /// テザー + /// 距離 + /// + [BurstCompile] + unsafe struct SplitStep_D_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray centerDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + [Unity.Collections.ReadOnly] + public NativeArray vertexRootIndices; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [Unity.Collections.ReadOnly] + public NativeArray basePosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [Unity.Collections.ReadOnly] + public NativeArray frictionArray; + + // distance + [Unity.Collections.ReadOnly] + public NativeArray distanceIndexArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDataArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDistanceArray; + + // buffer + [Unity.Collections.ReadOnly] + public NativeArray stepBasicPositionBuffer; + + // バッチ内のローカルチームインデックスごと + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + TetherConstraint.SolverConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + ref cdata, + // vmesh + ref attributes, + ref depthArray, + ref vertexRootIndices, + // particle + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + // buffer + ref stepBasicPositionBuffer + ); + + DistanceConstraint.SolverConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref basePosArray, + ref velocityPosArray, + ref frictionArray, + // constraint + ref distanceIndexArray, + ref distanceDataArray, + ref distanceDistanceArray + ); + } + } + + /// + /// アングル + /// + [BurstCompile] + unsafe struct SplitStep_Angle_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + [Unity.Collections.ReadOnly] + public NativeArray vertexRootIndices; + [Unity.Collections.ReadOnly] + public NativeArray vertexParentIndices; + [Unity.Collections.ReadOnly] + public NativeArray baseLineStartDataIndices; + [Unity.Collections.ReadOnly] + public NativeArray baseLineDataCounts; + [Unity.Collections.ReadOnly] + public NativeArray baseLineData; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [Unity.Collections.ReadOnly] + public NativeArray frictionArray; + + // distance + [Unity.Collections.ReadOnly] + public NativeArray distanceIndexArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDataArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDistanceArray; + + // buffer + [Unity.Collections.ReadOnly] + public NativeArray stepBasicPositionBuffer; + [Unity.Collections.ReadOnly] + public NativeArray stepBasicRotationBuffer; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferB; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempFloatBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempRotationBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempRotationBufferB; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.baseLineChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + AngleConstraint.SolverConstraint( + chunk, + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + ref vertexParentIndices, + ref baseLineStartDataIndices, + ref baseLineDataCounts, + ref baseLineData, + // particle + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + // buffer + ref stepBasicPositionBuffer, + ref stepBasicRotationBuffer, + // buffer2 + ref tempFloatBufferA, + ref tempVectorBufferA, + ref tempRotationBufferA, + ref tempRotationBufferB, + ref tempVectorBufferB + ); + } + } + + /// + /// トライアングルベンド + /// + [BurstCompile] + unsafe struct SplitStep_Triangle_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [Unity.Collections.ReadOnly] + public NativeArray frictionArray; + + // triangle bending + [Unity.Collections.ReadOnly] + public NativeArray bendingTrianglePairArray; + [Unity.Collections.ReadOnly] + public NativeArray bendingRestAngleOrVolumeArray; + [Unity.Collections.ReadOnly] + public NativeArray bendingSignOrVolumeArray; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempCountBuffer; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.bendingPairChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + TriangleBendingConstraint.SolverConstraint( + chunk, + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref frictionArray, + // constraints + ref bendingTrianglePairArray, + ref bendingRestAngleOrVolumeArray, + ref bendingSignOrVolumeArray, + // buffer2 + ref tempVectorBufferA, + ref tempCountBuffer + ); + } + } + + /// + /// トライアングルベンド集計 + /// コライダーコリジョンPoint + /// + [BurstCompile] + unsafe struct SplitStep_E_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [Unity.Collections.ReadOnly] + public NativeArray basePosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray frictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray collisionNormalArray; + + // collider + [Unity.Collections.ReadOnly] + public NativeArray colliderFlagArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderWorkDataArray; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempCountBuffer; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + TriangleBendingConstraint.SumConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + // particle + ref nextPosArray, + // buffer2 + ref tempVectorBufferA, + ref tempCountBuffer + ); + + // コライダーコリジョン + if (tdata.UseColliderCount > 0 && param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Point) + { + // Pointコリジョン + ColliderCollisionConstraint.SolverPointConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref frictionArray, + ref collisionNormalArray, + ref velocityPosArray, + ref basePosArray, + // collider + ref colliderFlagArray, + ref colliderWorkDataArray + ); + } + } + } + + /// + /// コライダーコリジョンEdge + /// + [BurstCompile] + unsafe struct SplitStep_Edge_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + [Unity.Collections.ReadOnly] + public NativeArray edges; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + + // collider + [Unity.Collections.ReadOnly] + public NativeArray colliderFlagArray; + [Unity.Collections.ReadOnly] + public NativeArray colliderWorkDataArray; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferB; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempCountBuffer; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempFloatBufferA; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // コライダーコリジョン + if (tdata.UseColliderCount > 0 && param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Edge) + { + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.proxyEdgeChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + // Edgeコリジョン + ColliderCollisionConstraint.SolverEdgeConstraint( + //new DataChunk(0, tdata.proxyEdgeChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + ref edges, + // particle + ref nextPosArray, + // collider + ref colliderFlagArray, + ref colliderWorkDataArray, + // buffer2 + ref tempVectorBufferA, + ref tempVectorBufferB, + ref tempCountBuffer, + ref tempFloatBufferA + ); + } + } + } + + /// + /// ■セルフコリジョンあり + /// コライダーコリジョンEdge集計 + /// 距離 + /// モーション + /// + [BurstCompile] + unsafe struct SplitStep_F_Self_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [Unity.Collections.ReadOnly] + public NativeArray basePosArray; + [Unity.Collections.ReadOnly] + public NativeArray baseRotArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray frictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray collisionNormalArray; + + // distance + [Unity.Collections.ReadOnly] + public NativeArray distanceIndexArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDataArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDistanceArray; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferB; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempCountBuffer; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempFloatBufferA; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) + return; + + // コライダーコリジョン + if (tdata.UseColliderCount > 0 && param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Edge) + { + // Edgeコリジョン集計 + ColliderCollisionConstraint.SumEdgeConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // particle + ref nextPosArray, + ref frictionArray, + ref collisionNormalArray, + // buffer2 + ref tempVectorBufferA, + ref tempVectorBufferB, + ref tempCountBuffer, + ref tempFloatBufferA + ); + } + + // コライダー衝突後はパーティクルが乱れる可能性があるためもう一度距離制約で整える。 + // これは裏返り防止などに効果大。 + DistanceConstraint.SolverConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref basePosArray, + ref velocityPosArray, + ref frictionArray, + // constraint + ref distanceIndexArray, + ref distanceDataArray, + ref distanceDistanceArray + ); + + // モーション制約はコライダーより優先 + MotionConstraint.SolverConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref basePosArray, + ref baseRotArray, + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + ref collisionNormalArray + ); + } + } + + /// + /// ■セルフコリジョンあり + /// 座標確定 + /// コライダーの後更新 + /// + [BurstCompile] + unsafe struct SplitStep_G_Self_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray centerDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + + // particle + [Unity.Collections.ReadOnly] + public NativeArray nextPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldPosArray; + [Unity.Collections.ReadOnly] + public NativeArray velocityPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray realVelocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray frictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray staticFrictionArray; + [Unity.Collections.ReadOnly] + public NativeArray collisionNormalArray; + + // collider + [Unity.Collections.ReadOnly] + public NativeArray colliderNowPositions; + [Unity.Collections.ReadOnly] + public NativeArray colliderNowRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldRotations; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid) + { + // 座標確定 + SimulationStepPostTeam( + chunk, + simulationDeltaTime, + // team + teamId, + ref tdata, + ref cdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref oldPosArray, + ref velocityArray, + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + ref staticFrictionArray, + ref collisionNormalArray, + ref realVelocityArray + ); + } + + // コライダーの後更新 + var colChunk = MathUtility.GetWorkerChunk(tdata.colliderChunk.dataLength, workerCount, workerIndex); + if (colChunk.IsValid) + { + ColliderManager.SimulationEndStep( + colChunk, + // team + ref tdata, + // collider + ref colliderNowPositions, + ref colliderNowRotations, + ref colliderOldPositions, + ref colliderOldRotations + ); + } + } + } + + /// + /// ■セルフコリジョンなし + /// コライダーコリジョンEdge集計 + /// 距離 + /// モーション + /// 座標確定 + /// コライダーの後更新 + /// + [BurstCompile] + unsafe struct SplitStep_FG_NoSelf_Job : IJobParallelFor + { + public int workerCount; + public int updateIndex; + public float4 simulationPower; + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray centerDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray depthArray; + + // particle + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray nextPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldPosArray; + [Unity.Collections.ReadOnly] + public NativeArray basePosArray; + [Unity.Collections.ReadOnly] + public NativeArray baseRotArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray velocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray realVelocityArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray frictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray staticFrictionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray collisionNormalArray; + + // collider + [Unity.Collections.ReadOnly] + public NativeArray colliderNowPositions; + [Unity.Collections.ReadOnly] + public NativeArray colliderNowRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldPositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldRotations; + + // distance + [Unity.Collections.ReadOnly] + public NativeArray distanceIndexArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDataArray; + [Unity.Collections.ReadOnly] + public NativeArray distanceDistanceArray; + + // buffer2 + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferA; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempVectorBufferB; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempCountBuffer; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray tempFloatBufferA; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (updateIndex >= tdata.updateCount) + return; + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid) + { + // コライダーコリジョン + if (tdata.UseColliderCount > 0 && param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Edge) + { + // Edgeコリジョン集計 + ColliderCollisionConstraint.SumEdgeConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // particle + ref nextPosArray, + ref frictionArray, + ref collisionNormalArray, + // buffer2 + ref tempVectorBufferA, + ref tempVectorBufferB, + ref tempCountBuffer, + ref tempFloatBufferA + ); + } + + // コライダー衝突後はパーティクルが乱れる可能性があるためもう一度距離制約で整える。 + // これは裏返り防止などに効果大。 + DistanceConstraint.SolverConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + simulationPower, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref nextPosArray, + ref basePosArray, + ref velocityPosArray, + ref frictionArray, + // constraint + ref distanceIndexArray, + ref distanceDataArray, + ref distanceDistanceArray + ); + + // モーション制約はコライダーより優先 + MotionConstraint.SolverConstraint( + //new DataChunk(0, tdata.particleChunk.dataLength), + chunk, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref basePosArray, + ref baseRotArray, + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + ref collisionNormalArray + ); + + // 座標確定 + SimulationStepPostTeam( + chunk, + simulationDeltaTime, + // team + teamId, + ref tdata, + ref cdata, + ref param, + // vmesh + ref attributes, + ref depthArray, + // particle + ref oldPosArray, + ref velocityArray, + ref nextPosArray, + ref velocityPosArray, + ref frictionArray, + ref staticFrictionArray, + ref collisionNormalArray, + ref realVelocityArray + ); + } + + // コライダーの後更新 + var colChunk = MathUtility.GetWorkerChunk(tdata.colliderChunk.dataLength, workerCount, workerIndex); + if (colChunk.IsValid) + { + ColliderManager.SimulationEndStep( + colChunk, + // team + ref tdata, + // collider + ref colliderNowPositions, + ref colliderNowRotations, + ref colliderOldPositions, + ref colliderOldRotations + ); + } + } + } + + /// + /// 表示位置の計算 + /// + [BurstCompile] + unsafe struct SplitPost_DisplayPos_Job : IJobParallelFor + { + public int workerCount; + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray positions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexRootIndices; + + // particle + [Unity.Collections.ReadOnly] + public NativeArray oldPosArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldPositionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray oldRotationArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray dispPosArray; + [Unity.Collections.ReadOnly] + public NativeArray realVelocityArray; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // ■表示位置の決定 + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.particleChunk.dataLength, workerCount, workerIndex); + //Debug.Log($"localIndex:{localIndex}, workerIndex:{workerIndex}, workerCount:{workerCount}, chun.s:{chunk.startIndex}, chun.l:{chunk.dataLength}"); + if (chunk.IsValid) + { + SimulationCalcDisplayPosition( + chunk, + simulationDeltaTime, + // team + ref tdata, + // particle + ref oldPosArray, + ref realVelocityArray, + ref oldPositionArray, + ref oldRotationArray, + ref dispPosArray, + // vmesh + ref attributes, + ref positions, + ref rotations, + ref vertexRootIndices + + ); + } + } + } + + /// + /// クロスシミュレーションの結果をProxyMeshへ反映させる + /// ラインがある場合はベースラインごとに姿勢を整える + /// + [BurstCompile] + unsafe struct SplitPost_CalcProxy_Job : IJobParallelFor + { + public int workerCount; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + [Unity.Collections.ReadOnly] + public NativeArray parameterArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray positions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray baseLineStartDataIndices; + [Unity.Collections.ReadOnly] + public NativeArray baseLineDataCounts; + [Unity.Collections.ReadOnly] + public NativeArray baseLineData; + [Unity.Collections.ReadOnly] + public NativeArray vertexLocalPositions; + [Unity.Collections.ReadOnly] + public NativeArray vertexLocalRotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexChildIndexArray; + [Unity.Collections.ReadOnly] + public NativeArray vertexChildDataArray; + [Unity.Collections.ReadOnly] + public NativeArray baseLineFlags; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + ClothParameters* paramPt = (ClothParameters*)parameterArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var param = ref *(paramPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // ■クロスシミュレーション後の頂点姿勢計算 + // ラインがある場合はベースラインごとに姿勢を整える + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.baseLineChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid) + { + VirtualMeshManager.SimulationPostProxyMeshUpdateLine( + chunk, + // team + ref tdata, + ref param, + // vmesh + ref attributes, + ref positions, + ref rotations, + ref vertexLocalPositions, + ref vertexLocalRotations, + ref vertexChildIndexArray, + ref vertexChildDataArray, + ref baseLineFlags, + ref baseLineStartDataIndices, + ref baseLineDataCounts, + ref baseLineData + ); + } + } + } + + /// + /// トライアングルの法線接線を求める + /// + [BurstCompile] + unsafe struct SplitPost_CalcProxyTriangle_Job : IJobParallelFor + { + public int workerCount; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray positions; + [Unity.Collections.ReadOnly] + public NativeArray triangles; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray triangleNormals; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray triangleTangents; + [Unity.Collections.ReadOnly] + public NativeArray uvs; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // ■クロスシミュレーション後の頂点姿勢計算 + // トライアングルの法線接線を求める + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.proxyTriangleChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid) + { + VirtualMeshManager.SimulationPostProxyMeshUpdateTriangle( + chunk, + // team + ref tdata, + // vmesh + ref positions, + ref triangles, + ref triangleNormals, + ref triangleTangents, + ref uvs + ); + } + } + } + + /// + /// トライアングルの法線接線から頂点の姿勢を求める + /// BoneClothの場合は頂点姿勢から連動するトランスフォームのワールド姿勢を計算する + /// + [BurstCompile] + unsafe struct SplitPost_SumProxyTriangleAndTransform_Job : IJobParallelFor + { + public int workerCount; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + + // transform + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray transformPositionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray transformRotationArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray positions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray rotations; + [Unity.Collections.ReadOnly] + public NativeArray triangleNormals; + [Unity.Collections.ReadOnly] + public NativeArray triangleTangents; + [Unity.Collections.ReadOnly] + public NativeArray> vertexToTriangles; + [Unity.Collections.ReadOnly] + public NativeArray normalAdjustmentRotations; + [Unity.Collections.ReadOnly] + public NativeArray vertexToTransformRotations; + + // バッチ内のローカルチームインデックスごと + // ワーカー分割 + public void Execute(int index) + { + // チームIDとワーカーID + int localIndex = index / workerCount; + int workerIndex = index % workerCount; + + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafeReadOnlyPtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // 範囲 + var chunk = MathUtility.GetWorkerChunk(tdata.proxyCommonChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid) + { + // ■クロスシミュレーション後の頂点姿勢計算 + // トライアングルの法線接線から頂点の姿勢を求める + VirtualMeshManager.SimulationPostProxyMeshUpdateTriangleSum( + chunk, + // team + ref tdata, + // vmesh + ref rotations, + ref triangleNormals, + ref triangleTangents, + ref vertexToTriangles, + ref normalAdjustmentRotations + ); + // BoneClothの場合は頂点姿勢から連動するトランスフォームのワールド姿勢を計算する + VirtualMeshManager.SimulationPostProxyMeshUpdateWorldTransform( + chunk, + // team + ref tdata, + // vmesh + ref positions, + ref rotations, + ref vertexToTransformRotations, + // transform + ref transformPositionArray, + ref transformRotationArray + ); + } + } + } + + /// + /// チーム更新後処理 + /// BoneClothの場合はTransformのローカル姿勢を計算する + /// コライダー更新後処理 + /// + [BurstCompile] + unsafe struct SplitPost_TeamCollider_Job : IJobParallelFor + { + public float simulationDeltaTime; + + // team + [Unity.Collections.ReadOnly] + public NativeList batchSelfTeamList; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray teamDataArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray centerDataArray; + + // collider + [Unity.Collections.ReadOnly] + public NativeArray colliderFramePositions; + [Unity.Collections.ReadOnly] + public NativeArray colliderFrameRotations; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldFramePositions; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray colliderOldFrameRotations; + + // transform + [Unity.Collections.ReadOnly] + public NativeArray transformPositionArray; + [Unity.Collections.ReadOnly] + public NativeArray transformRotationArray; + [Unity.Collections.ReadOnly] + public NativeArray transformScaleArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray transformLocalPositionArray; + [NativeDisableParallelForRestriction] + [NativeDisableContainerSafetyRestriction] + public NativeArray transformLocalRotationArray; + + // vmesh + [Unity.Collections.ReadOnly] + public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray vertexParentIndices; + + // バッチ内のローカルチームインデックスごと + public void Execute(int localIndex) + { + // 各ベースポインタ + TeamManager.TeamData* teamPt = (TeamManager.TeamData*)teamDataArray.GetUnsafePtr(); + InertiaConstraint.CenterData* centerPt = (InertiaConstraint.CenterData*)centerDataArray.GetUnsafePtr(); + + int teamId = batchSelfTeamList[localIndex]; + ref var tdata = ref *(teamPt + teamId); + ref var cdata = ref *(centerPt + teamId); + + if (tdata.IsProcess == false) + return; + if (tdata.ParticleCount == 0) + return; + + // BoneClothの場合はTransformのローカル姿勢を計算する + VirtualMeshManager.SimulationPostProxyMeshUpdateLocalTransform( + // team + ref tdata, + // vmesh + ref attributes, + ref vertexParentIndices, + // transform + ref transformPositionArray, + ref transformRotationArray, + ref transformScaleArray, + ref transformLocalPositionArray, + ref transformLocalRotationArray + ); + + // ■コライダー更新後処理 + ColliderManager.SimulationPostUpdate( + // team + ref tdata, + // collider + ref colliderFramePositions, + ref colliderFrameRotations, + ref colliderOldFramePositions, + ref colliderOldFrameRotations + ); + + // ■チーム更新後処理 + TeamManager.SimulationPostTeamUpdate( + // team + ref tdata, + ref cdata + ); + } + } + } +} + diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs.meta new file mode 100644 index 00000000..5c075aaa --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2dd0faec9645ac1499b7eceb32ba4f10 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/SimulationManagerSplit.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/TimeManager.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/TimeManager.cs index 3e462d38..bcd979e0 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/TimeManager.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/TimeManager.cs @@ -96,7 +96,7 @@ namespace MagicaCloth2 //========================================================================================= void AfterFixedUpdate() { - //Debug.Log($"AF. F:{Time.frameCount}"); + //Debug.Log($"AfterFixedUpdate. F:{Time.frameCount}"); FixedUpdateCount++; } @@ -147,7 +147,7 @@ namespace MagicaCloth2 sb.AppendLine($"MaxSimulationCountPerFrame:{maxSimulationCountPerFrame}"); sb.AppendLine($"GlobalTimeScale:{GlobalTimeScale}"); sb.AppendLine($"SimulationDeltaTime:{SimulationDeltaTime}"); - sb.AppendLine($"MaxDeltaTime:{MaxDeltaTime}"); + //sb.AppendLine($"MaxDeltaTime:{MaxDeltaTime}"); sb.AppendLine($"SimulationPower:{SimulationPower}"); } sb.AppendLine(); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/TimeManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/TimeManager.cs.meta index d404ddff..14da2793 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/TimeManager.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/TimeManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/TimeManager.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/WindManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/WindManager.cs.meta index 3be0d6d5..fca333ee 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/WindManager.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/WindManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Simulation/WindManager.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamManager.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamManager.cs index 865b920d..58fa5f11 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamManager.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamManager.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Text; using Unity.Burst; using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; using Unity.Jobs; using Unity.Mathematics; using Unity.Profiling; @@ -21,19 +22,25 @@ namespace MagicaCloth2 public const int Flag_Enable = 1; // 動作状態 public const int Flag_Reset = 2; // 姿勢リセット public const int Flag_TimeReset = 3; // 時間リセット - public const int Flag_Suspend = 4; // 一時停止 + public const int Flag_SyncSuspend = 4; // 同期待ち一時停止 public const int Flag_Running = 5; // 今回のフレームでシミュレーションが実行されたかどうか - //public const int Flag_CustomSkinning = 6; // カスタムスキニングを使用(未使用) - //public const int Flag_NormalAdjustment = 9; // 法線調整(未使用) public const int Flag_Synchronization = 6; // 同期中 public const int Flag_StepRunning = 7; // ステップ実行中 public const int Flag_Exit = 8; // 存在消滅時 public const int Flag_KeepTeleport = 9; // 姿勢保持テレポート public const int Flag_InertiaShift = 10; // 慣性全体シフト - public const int Flag_CullingInvisible = 11; // カリングによる非表示状態 - public const int Flag_CullingKeep = 12; // カリング時に姿勢を保つ + public const int Flag_CameraCullingInvisible = 11; // カメラカリングによる非表示状態 + public const int Flag_CameraCullingKeep = 12; // カメラカリング時に姿勢を保つ public const int Flag_Spring = 13; // Spring利用 public const int Flag_SkipWriting = 14; // 書き込み停止(ストップモーション用) + public const int Flag_Anchor = 15; // Inertia anchorを利用中 + public const int Flag_AnchorReset = 16; // Inertia anchorの座標リセット + public const int Flag_NegativeScale = 17; // マイナススケールの有無 + public const int Flag_NegativeScaleTeleport = 18; // マイナススケールによるテレポート + public const int Flag_DistanceCullingInvisible = 19; // 距離カリングによる非表示状態 + public const int Flag_RestoreTransformOnlyOnec = 20; // Transform復元を一度のみ実行する(BoneClothのDisable時) + public const int Flag_Tangent = 21; // 接線を計算する + public const int Flag_ScaleSuspent = 22; // 極小スケールによる機能停止 // 以下セルフコリジョン // !これ以降の順番を変えないこと @@ -71,7 +78,12 @@ namespace MagicaCloth2 public BitField64 flag; /// - /// 更新モード + /// 更新モード(オリジナル) + /// + public ClothUpdateMode originalUpdateMode; + + /// + /// 更新モード(最終結果) /// public ClothUpdateMode updateMode; @@ -80,6 +92,9 @@ namespace MagicaCloth2 /// //public int frequency; + /// + /// 現在フレームの更新時間 + /// public float frameDeltaTime; /// @@ -117,11 +132,22 @@ namespace MagicaCloth2 /// public float timeScale; + /// + /// チームの最終計算用タイムスケール(0.0~1.0) + /// グローバルタイムスケールなどを考慮した値 + /// + public float nowTimeScale; + /// /// 今回のチーム更新回数(0ならばこのフレームは更新なし) /// public int updateCount; + /// + /// 今回のチーム更新スキップ回数(1以上ならばシミュレーションスキップが発生) + /// + public int skipCount; + /// /// ステップごとのフレームに対するnowUpdateTime割合 /// これは(frameStartTime ~ time)間でのnowUpdateTimeの割合 @@ -144,15 +170,42 @@ namespace MagicaCloth2 /// /// 現在の中心ワールド座標(この値はCenterData.nowWorldPositionのコピー) /// - public float3 centerWorldPosition; + //public float3 centerWorldPosition; + + /// + /// アンカーとして設定されているTransformのインスタンスID(0=なし) + /// + //public int anchorTransformId; + + /// + /// 距離カリングの測定オブジェクトID(0=メインカメラ) + /// + public int distanceReferenceObjectId; + + /// + /// コンポーネント用のTransformインデックス + /// + public int componentTransformIndex; /// /// チームスケール /// public float3 initScale; // データ生成時のセンタートランスフォームスケール public float scaleRatio; // 現在のスケール倍率 - //public float3 scaleDirection; // フリップ用:スケール値方向(xyz):(1/-1)のみ - //public float4 quaternionScale; // フリップ用:クォータニオン反転用 + + /// + /// マイナススケール + /// + public float negativeScaleSign; // マイナススケールの有無(1:正スケール, -1:マイナススケール) + public float3 negativeScaleDirection; // スケール方向(xyz):(1:正スケール, -1:マイナススケール) + public float3 negativeScaleChange; // 今回のフレームで変化したスケール(xyz):(1:変化なし, -1:反転した) + public float2 negativeScaleTriangleSign; // トライアングル法線接線フリップフラグ + public float4 negativeScaleQuaternionValue; // クォータニオン反転用 + + /// + /// MagicaClothコンポーネントのインスタンスID + /// + public int componentId; /// /// 同期チームID(0=なし) @@ -169,6 +222,11 @@ namespace MagicaCloth2 /// public int syncCenterTransformIndex; + /// + /// 連動するAnimatorのインスタンスID(0=なし) + /// + public int interlockingAnimatorId; + /// /// 初期姿勢とアニメーション姿勢のブレンド率(制約で利用) /// @@ -180,7 +238,12 @@ namespace MagicaCloth2 public float velocityWeight; /// - /// シミュレーション結果ブレンド割合(0.0 ~ 1.0) + /// 距離カリングによるブレンド割合(0.0 ~ 1.0) + /// + public float distanceWeight; + + /// + /// 最終シミュレーション結果ブレンド割合(0.0 ~ 1.0) /// public float blendWeight; @@ -335,17 +398,18 @@ namespace MagicaCloth2 /// 曲げ制約 /// public DataChunk bendingPairChunk; - //public DataChunk bendingDataChunk; - public DataChunk bendingWriteIndexChunk; - public DataChunk bendingBufferChunk; /// /// セルフコリジョン制約 /// - //public int selfQueueIndex; public DataChunk selfPointChunk; public DataChunk selfEdgeChunk; public DataChunk selfTriangleChunk; + public float selfGridSize; + public int selfPointGridCount; + public int selfEdgeGridCount; + public int selfTriangleGridCount; + public float selfMaxPrimitiveSize; //----------------------------------------------------------------- /// @@ -376,7 +440,7 @@ namespace MagicaCloth2 /// /// 処理状態 /// - public bool IsProcess => flag.IsSet(Flag_Enable) && flag.IsSet(Flag_Suspend) == false && flag.IsSet(Flag_CullingInvisible) == false; + public bool IsProcess => IsEnable && flag.IsSet(Flag_SyncSuspend) == false && IsCullingInvisible == false && IsScaleSuspend == false; /// /// 姿勢リセット有無 @@ -403,29 +467,29 @@ namespace MagicaCloth2 /// public bool IsStepRunning => flag.IsSet(Flag_StepRunning); - public bool IsCullingInvisible => flag.IsSet(Flag_CullingInvisible); - - public bool IsCullingKeep => flag.IsSet(Flag_CullingKeep); - + public bool IsCameraCullingInvisible => flag.IsSet(Flag_CameraCullingInvisible); + public bool IsCameraCullingKeep => flag.IsSet(Flag_CameraCullingKeep); + public bool IsDistanceCullingInvisible => flag.IsSet(Flag_DistanceCullingInvisible); + public bool IsCullingInvisible => IsCameraCullingInvisible || IsDistanceCullingInvisible; public bool IsSpring => flag.IsSet(Flag_Spring); - + public bool IsNegativeScale => flag.IsSet(Flag_NegativeScale); + public bool IsNegativeScaleTeleport => flag.IsSet(Flag_NegativeScaleTeleport); + public bool IsTangent => flag.IsSet(Flag_Tangent); + public bool IsScaleSuspend => flag.IsSet(Flag_ScaleSuspent); public int ParticleCount => particleChunk.dataLength; /// /// 現在有効なコライダー数 /// - public int ColliderCount => colliderCount; - + public int UseColliderCount => colliderCount; public int BaseLineCount => baseLineChunk.dataLength; - public int TriangleCount => proxyTriangleChunk.dataLength; - public int EdgeCount => proxyEdgeChunk.dataLength; //public int MappingCount => mappingDataIndexSet.Length; /// - /// 初期スケール(x軸のみで判定、均等スケールしか認めていない) + /// 初期スケール(x軸のみで判定、一様スケールしか認めていない) /// public float InitScale => initScale.x; } @@ -436,6 +500,14 @@ namespace MagicaCloth2 /// public ExNativeArray teamWindArray; + /// + /// マッピングメッシュデータフラグ + /// + public const int MappingDataFlag_ChangePositionNormal = 0; + public const int MappingDataFlag_ChangeTangent = 1; + public const int MappingDataFlag_ChangeBoneWeight = 2; + public const int MappingDataFlag_ModifyBoneWeight = 3; + /// /// マッピングメッシュデータ /// @@ -443,6 +515,11 @@ namespace MagicaCloth2 { public int teamId; + /// + /// 状態フラグ + /// + public BitField32 flag; + /// /// Mappingメッシュのセンタートランスフォーム(ダイレクト値) /// @@ -484,6 +561,11 @@ namespace MagicaCloth2 /// public float scaleRatio; + /// + /// 紐づけられているRenderDataWorkバッファへのインデックス + /// + public int renderDataWorkIndex; + public bool IsValid() { return teamId > 0; @@ -499,9 +581,13 @@ namespace MagicaCloth2 public ExNativeArray> teamMappingIndexArray; /// - /// チーム全体の最大更新回数 + /// チーム全体の集計データ + /// x:最大更新回数 + /// y:分割ジョブチームのPointコリジョンの数 + /// z:分割ジョブチームのEdgeコリジョンの数 + /// w:分割ジョブチームのSelfコリジョンの数 /// - public NativeReference maxUpdateCount; + public NativeReference teamStatus; /// /// パラメータ(teamDataArrayとインデックス連動) @@ -529,24 +615,6 @@ namespace MagicaCloth2 /// Dictionary clothProcessDict = new Dictionary(); - //========================================================================================= - bool isValid; - - /// - /// グローバルタイムスケール(0.0 ~ 1.0) - /// - //internal float globalTimeScale = 1.0f; - - /// - /// フレームのFixedUpdate回数 - /// - //int fixedUpdateCount = 0; - - /// - /// エッジコライダーコリジョンのエッジ数合計 - /// - internal int edgeColliderCollisionCount; - //========================================================================================= /// /// 登録されているチーム数(グローバルチームを含む。そのため0にはならない) @@ -563,6 +631,42 @@ namespace MagicaCloth2 /// public int ActiveTeamCount => enableTeamSet.Count; + /// + /// 今回フレームでのチーム全体の最大更新回数 + /// + public int TeamMaxUpdateCount => teamStatus.Value.x; + + //========================================================================================= + // ■作業データ + bool isValid; + + /// + /// エッジコライダーコリジョンのエッジ数合計 + /// + internal int edgeColliderCollisionCount; + + internal NativeReference edgeColliderCollisionCountBuff; + internal NativeParallelHashMap comp2SuspendCounterMap; + internal NativeParallelHashMap comp2TeamIdMap; + internal NativeParallelHashMap comp2SyncPartnerCompMap; + internal NativeParallelHashMap comp2SyncTopCompMap; + + internal NativeList batchNormalClothTeamList; + internal NativeList batchSplitClothTeamList; + + internal List parameterDirtyList; + internal List skipWritingDirtyList; + internal NativeList cullingDirtyList; + internal NativeParallelHashSet selfCollisionUpdateSet; + internal NativeParallelHashMap animatorUpdateModeMap; + + internal ExSimpleNativeArray teamAnchorTransformIndexArray; + internal ExSimpleNativeArray teamDistanceTransformIndexArray; + internal NativeParallelHashMap transformPositionMap; + internal NativeParallelHashMap transformRotationMap; + + internal HashSet cameraCullingClothSet = new HashSet(256); + //========================================================================================= public void Dispose() { @@ -585,12 +689,39 @@ namespace MagicaCloth2 parameterArray = null; centerDataArray = null; - if (maxUpdateCount.IsCreated) - maxUpdateCount.Dispose(); + if (teamStatus.IsCreated) + teamStatus.Dispose(); enableTeamSet.Clear(); clothProcessDict.Clear(); + if (edgeColliderCollisionCountBuff.IsCreated) + edgeColliderCollisionCountBuff.Dispose(); + comp2SuspendCounterMap.MC2DisposeSafe(); + comp2TeamIdMap.MC2DisposeSafe(); + comp2SyncPartnerCompMap.MC2DisposeSafe(); + comp2SyncTopCompMap.MC2DisposeSafe(); + + if (batchNormalClothTeamList.IsCreated) + batchNormalClothTeamList.Dispose(); + if (batchSplitClothTeamList.IsCreated) + batchSplitClothTeamList.Dispose(); + + parameterDirtyList?.Clear(); + skipWritingDirtyList?.Clear(); + if (cullingDirtyList.IsCreated) + cullingDirtyList.Dispose(); + if (selfCollisionUpdateSet.IsCreated) + selfCollisionUpdateSet.Dispose(); + animatorUpdateModeMap.MC2DisposeSafe(); + + teamAnchorTransformIndexArray?.Dispose(); + teamDistanceTransformIndexArray?.Dispose(); + transformPositionMap.MC2DisposeSafe(); + transformRotationMap.MC2DisposeSafe(); + + cameraCullingClothSet.Clear(); + //globalTimeScale = 1.0f; //fixedUpdateCount = 0; @@ -623,11 +754,32 @@ namespace MagicaCloth2 parameterArray.Add(new ClothParameters()); centerDataArray.Add(new InertiaConstraint.CenterData()); - maxUpdateCount = new NativeReference(Allocator.Persistent); + teamStatus = new NativeReference(Allocator.Persistent); //globalTimeScale = 1.0f; //fixedUpdateCount = 0; + // 作業用 + edgeColliderCollisionCountBuff = new NativeReference(Allocator.Persistent); + comp2SuspendCounterMap = new NativeParallelHashMap(256, Allocator.Persistent); + comp2TeamIdMap = new NativeParallelHashMap(256, Allocator.Persistent); + comp2SyncPartnerCompMap = new NativeParallelHashMap(256, Allocator.Persistent); + comp2SyncTopCompMap = new NativeParallelHashMap(256, Allocator.Persistent); + + batchNormalClothTeamList = new NativeList(Allocator.Persistent); + batchSplitClothTeamList = new NativeList(Allocator.Persistent); + + parameterDirtyList = new List(128); + skipWritingDirtyList = new List(128); + cullingDirtyList = new NativeList(128, Allocator.Persistent); + selfCollisionUpdateSet = new NativeParallelHashSet(256, Allocator.Persistent); + animatorUpdateModeMap = new NativeParallelHashMap(128, Allocator.Persistent); + + teamAnchorTransformIndexArray = new ExSimpleNativeArray(256, true); + teamDistanceTransformIndexArray = new ExSimpleNativeArray(256, true); + transformPositionMap = new NativeParallelHashMap(32, Allocator.Persistent); + transformRotationMap = new NativeParallelHashMap(32, Allocator.Persistent); + // 破棄監視更新処理 MagicaManager.afterUpdateDelegate += MonitoringProcessUpdate; @@ -654,17 +806,27 @@ namespace MagicaCloth2 // この段階でProxyMeshは完成している var team = new TeamData(); + team.componentId = cprocess.cloth.GetInstanceID(); // ★Enableフラグは立てない team.flag.SetBits(Flag_Valid, true); team.flag.SetBits(Flag_Reset, true); team.flag.SetBits(Flag_TimeReset, true); + team.originalUpdateMode = cprocess.cloth.SerializeData.updateMode; team.updateMode = cprocess.cloth.SerializeData.updateMode; //team.frequency = clothParams.solverFrequency; team.timeScale = 1.0f; team.initScale = cprocess.clothTransformRecord.scale; // 初期スケール team.scaleRatio = 1.0f; - team.centerWorldPosition = cprocess.clothTransformRecord.position; + team.negativeScaleSign = 1; + team.negativeScaleDirection = 1; + team.negativeScaleChange = 1; + team.negativeScaleQuaternionValue = 1; + team.negativeScaleTriangleSign = 1; + //team.centerWorldPosition = cprocess.clothTransformRecord.position; team.animationPoseRatio = cprocess.cloth.SerializeData.animationPoseRatio; + team.distanceWeight = 1; + team.componentTransformIndex = MagicaManager.Bone.AddComponentTransform(cprocess.cloth.transform); // コンポーネントTransform + //cprocess.componentTransformIndex = team.componentTransformIndex; // cprocessにもコピー var c = teamDataArray.Add(team); int teamId = c.startIndex; @@ -676,7 +838,6 @@ namespace MagicaCloth2 return 0; } - var wind = new TeamWindData(); wind.movingWind.time = -Define.System.WindMaxTime; teamWindArray.Add(wind); @@ -690,7 +851,7 @@ namespace MagicaCloth2 // 慣性制約 // 初期化時のセンターローカル位置を初期化 var cdata = new InertiaConstraint.CenterData(); - cdata.frameLocalPosition = cprocess.ProxyMesh.localCenterPosition.Value; + cdata.frameLocalPosition = cprocess.ProxyMeshContainer.shareVirtualMesh.localCenterPosition.Value; centerDataArray.Add(cdata); clothProcessDict.Add(teamId, cprocess); @@ -716,6 +877,7 @@ namespace MagicaCloth2 } // 制約データなど解除 + MagicaManager.Bone.RemoveComponentTransform(tdata.componentTransformIndex); // チームデータを破棄する var c = new DataChunk(teamId); @@ -725,6 +887,10 @@ namespace MagicaCloth2 parameterArray.Remove(c); centerDataArray.Remove(c); + // チーム作業バッファをクリア + teamAnchorTransformIndexArray[teamId] = 0; + teamDistanceTransformIndexArray[teamId] = 0; + clothProcessDict.Remove(teamId); } @@ -746,8 +912,12 @@ namespace MagicaCloth2 else enableTeamSet.Remove(teamId); + // 無効時には一度のみTransform復元フラグを立てる + if (sw == false) + team.flag.SetBits(Flag_RestoreTransformOnlyOnec, true); + // コライダーの有効状態(内部でコライダートランスフォームの有効状態も設定) - MagicaManager.Collider.EnableTeamCollider(teamId, sw); + MagicaManager.Collider.EnableTeamCollider(teamId); // センタートランスフォーム MagicaManager.Bone.EnableTransform(team.centerTransformIndex, sw); @@ -794,6 +964,10 @@ namespace MagicaCloth2 return ref centerDataArray.GetRef(teamId); } + internal ref MappingData GetMappingDataRef(int mindex) + { + return ref mappingDataArray.GetRef(mindex); + } public ClothProcess GetClothProcess(int teamId) { @@ -804,57 +978,41 @@ namespace MagicaCloth2 } //========================================================================================= - static readonly ProfilerMarker teamUpdateCullingProfiler = new ProfilerMarker("TeamUpdateCulling"); + static readonly ProfilerMarker teamCameraCullingPreProfiler = new ProfilerMarker("CameraCullingPre"); + static readonly ProfilerMarker teamCameraCullingProfiler = new ProfilerMarker("CameraCullingPost"); /// - /// カリング状態更新 + /// カメラカリング状態更新(前処理) + /// 次のフレームの開始時に行うレンダラー判定用のデータを収集する /// - internal void TeamCullingUpdate() + internal void CameraCullingPreProcess() { - teamUpdateCullingProfiler.Begin(); + teamCameraCullingPreProfiler.Begin(); var cm = MagicaManager.Cloth; - // ジョブでは実行できないチーム更新 - cm.ClearVisibleDict(); - var clothSet = cm.clothSet; - foreach (var cprocess in clothSet) + // ここはシミュレーション処理中なのでtdataなどにアクセスできないので注意! + cameraCullingClothSet.Clear(); + foreach (var cprocess in cm.clothSet) { - int teamId = cprocess.TeamId; - ref var tdata = ref GetTeamDataRef(teamId); - - // 動作判定 ---------------------------------------------------- - if (tdata.flag.IsSet(Flag_Enable) == false || tdata.flag.IsSet(Flag_Suspend)) + if (cprocess.IsEnable == false) + continue; + if (cprocess.IsRunning() == false) continue; - //------------------------------------------------------------- - // 現在の状態 - bool oldInvisible = tdata.IsCullingInvisible; - bool invisible; - MagicaCloth jugeCloth = cprocess.cloth; + // 判定クロス。同期時は同期先を見る + MagicaCloth jugeCloth = cprocess.SyncTopCloth != null ? cprocess.SyncTopCloth : cprocess.cloth; CullingSettings jugeSettings = jugeCloth.SerializeData.cullingSettings; - ClothProcess jugeProcess = cprocess; - - // 同期時は同期先を見る - if (tdata.syncTeamId > 0) - { - var syncProcess = GetClothProcess(tdata.syncTeamId); - if (syncProcess != null) - { - jugeCloth = syncProcess.cloth; - jugeSettings = jugeCloth.SerializeData.cullingSettings; - jugeProcess = jugeCloth.Process; - } - } + ClothProcess jugeProcess = jugeCloth.Process; // 最終的なカリングモード var cullingMode = jugeSettings.cameraCullingMode; if (cullingMode == CullingSettings.CameraCullingMode.AnimatorLinkage) { - if (jugeProcess.cullingAnimator) + if (jugeProcess.interlockingAnimator) { - switch (jugeProcess.cullingAnimator.cullingMode) + switch (jugeProcess.interlockingAnimator.cullingMode) { case AnimatorCullingMode.AlwaysAnimate: cullingMode = CullingSettings.CameraCullingMode.Off; @@ -874,7 +1032,9 @@ namespace MagicaCloth2 // カリング判定 if (jugeCloth == null || cullingMode == CullingSettings.CameraCullingMode.Off) { - invisible = false; + // カリングは行わない + cprocess.cameraCullingAnimator = null; + cprocess.cameraCullingRenderers = null; } else { @@ -883,39 +1043,84 @@ namespace MagicaCloth2 List jugeRenderers = jugeSettings.cameraCullingRenderers; if (jugeSettings.cameraCullingMethod == CullingSettings.CameraCullingMethod.AutomaticRenderer) { - jugeAnimator = jugeCloth.Process.cullingAnimator; - jugeRenderers = jugeCloth.Process.cullingAnimatorRenderers; + jugeAnimator = jugeCloth.Process.interlockingAnimator; + jugeRenderers = jugeCloth.Process.interlockingAnimatorRenderers; } + cprocess.cameraCullingAnimator = jugeAnimator; + cprocess.cameraCullingRenderers = jugeRenderers; + } + cprocess.cameraCullingMode = cullingMode; + cameraCullingClothSet.Add(cprocess.cloth); + } + + teamCameraCullingPreProfiler.End(); + } + + /// + /// カメラカリング状態更新(後処理) + /// カメラカリングは該当するRendereのisVisibleフラグから判定される + /// このフラグは前フレームのレンダリング時に設定される + /// そのため現在フレームの位置は反映されないので注意する(1フレーム遅れる) + /// + internal void CameraCullingPostProcess() + { + teamCameraCullingProfiler.Begin(); + + var cm = MagicaManager.Cloth; + cm.ClearVisibleDict(); + + foreach (var cloth in cameraCullingClothSet) + { + if (cloth == null) + continue; + + var cprocess = cloth.Process; + + // 現在の状態 + bool oldInvisible = cprocess.cameraCullingOldInvisible; + bool invisible; + + if (cprocess.cameraCullingAnimator == null && cprocess.cameraCullingRenderers == null) + { + // カリングなし + invisible = false; + } + else + { // レンダラー判定 - invisible = !cm.CheckVisible(jugeAnimator, jugeRenderers); + invisible = !cm.CheckVisible(cprocess.cameraCullingAnimator, cprocess.cameraCullingRenderers); } // 状態変更 if (oldInvisible != invisible) { - tdata.flag.SetBits(Flag_CullingInvisible, invisible); - tdata.flag.SetBits(Flag_CullingKeep, false); - //Debug.Log($"Change culling invisible:({oldInvisible}) -> ({invisible})"); + int teamId = cprocess.TeamId; + ref var tdata = ref GetTeamDataRef(teamId); + + tdata.flag.SetBits(Flag_CameraCullingInvisible, invisible); + tdata.flag.SetBits(Flag_CameraCullingKeep, false); + //Debug.Log($"Change camera culling invisible:({oldInvisible}) -> ({invisible})"); // cprocessクラスにもコピーする - cprocess.SetState(ClothProcess.State_CullingInvisible, invisible); - cprocess.SetState(ClothProcess.State_CullingKeep, false); + cprocess.SetState(ClothProcess.State_CameraCullingInvisible, invisible); + cprocess.SetState(ClothProcess.State_CameraCullingKeep, false); + cprocess.cameraCullingOldInvisible = invisible; if (invisible) { // (表示->非表示)時の振る舞い - switch (cullingMode) + switch (cprocess.cameraCullingMode) { case CullingSettings.CameraCullingMode.Reset: case CullingSettings.CameraCullingMode.Off: tdata.flag.SetBits(Flag_Reset, true); - //Debug.Log($"Culling invisible. Reset On"); + //Debug.Log($"Camera culling invisible. Reset On"); break; case CullingSettings.CameraCullingMode.Keep: - tdata.flag.SetBits(Flag_CullingKeep, true); - cprocess.SetState(ClothProcess.State_CullingKeep, true); - //Debug.Log($"Culling invisible. Keep On"); + tdata.flag.SetBits(Flag_CameraCullingKeep, true); + cprocess.SetState(ClothProcess.State_CameraCullingKeep, true); + //Debug.Log($"Camera culling invisible. Keep On"); break; } } @@ -924,237 +1129,473 @@ namespace MagicaCloth2 cprocess.UpdateRendererUse(); } } + cameraCullingClothSet.Clear(); - teamUpdateCullingProfiler.End(); + teamCameraCullingProfiler.End(); } //========================================================================================= + static readonly ProfilerMarker startClothUpdateComponentProfiler = new ProfilerMarker("StartClothUpdate.Component"); + /// /// 毎フレーム常に実行するチーム更新 + /// - パラメータ反映 + /// - 更新モード反映 + /// - アンカー/距離カリングの参照オブジェクト反映 /// - 時間の更新と実行回数の算出 /// internal void AlwaysTeamUpdate() { - // 集計 - edgeColliderCollisionCount = 0; + var cm = MagicaManager.Cloth; + var tm = MagicaManager.Time; + var rm = MagicaManager.Render; + var bm = MagicaManager.Bone; + var sm = MagicaManager.Simulation; - // ジョブでは実行できないチーム更新 - var clothSet = MagicaManager.Cloth.clothSet; - foreach (var cprocess in clothSet) + // 作業バッファクリア + edgeColliderCollisionCount = 0; + edgeColliderCollisionCountBuff.Value = 0; + cm.ClearVisibleDict(); // レンダラーの表示判定辞書をクリア + selfCollisionUpdateSet.Clear(); + teamAnchorTransformIndexArray.SetLength(TeamCount); + teamDistanceTransformIndexArray.SetLength(TeamCount); + transformPositionMap.Clear(); + transformRotationMap.Clear(); + cullingDirtyList.Clear(); + batchNormalClothTeamList.Clear(); + batchSplitClothTeamList.Clear(); + + // (1)パラメータ反映 + for (int i = 0; i < parameterDirtyList.Count;) { + var cprocess = parameterDirtyList[i]; + if (cprocess == null) + { + parameterDirtyList.RemoveAt(i); + continue; + } + if (cprocess.IsEnable == false) + { + i++; + continue; + } + + //Develop.DebugLog($"Update Parameters {teamId}"); + // コライダー更新(内部でteamData更新) + MagicaManager.Collider.UpdateColliders(cprocess); + + // カリング用アニメーターとレンダラー更新 + cprocess.UpdateCullingAnimatorAndRenderers(); + int teamId = cprocess.TeamId; ref var tdata = ref GetTeamDataRef(teamId); var cloth = cprocess.cloth; - // 動作判定 ---------------------------------------------------- - if (tdata.flag.IsSet(Flag_Enable) == false) - continue; + // 連動アニメーターのインスタンスID + tdata.interlockingAnimatorId = cprocess.interlockingAnimator != null ? cprocess.interlockingAnimator.GetInstanceID() : 0; - // 同期まち判定 - bool suspend = true; - if (cprocess.GetSuspendCounter() == 0) - suspend = false; + // パラメータ変更 + cprocess.SyncParameters(); + parameterArray[teamId] = cprocess.parameters; + tdata.originalUpdateMode = cloth.SerializeData.updateMode; + tdata.updateMode = cloth.SerializeData.updateMode; + tdata.animationPoseRatio = cloth.SerializeData.animationPoseRatio; + tdata.flag.SetBits(Flag_Spring, cprocess.clothType == ClothProcess.ClothType.BoneSpring && cprocess.parameters.springConstraint.springPower > 0.0f); // Spring利用フラグ - // 同期相手の有効状態 - if (cloth.SyncCloth != null) - { - int syncTeamId = cloth.SyncCloth.Process.TeamId; - if (syncTeamId > 0) - { - ref var syncTeamData = ref GetTeamDataRef(syncTeamId); - if (syncTeamData.flag.IsSet(Flag_Enable) && cloth.SyncCloth.Process.GetSuspendCounter() == 0) - suspend = false; // 相手も処理可能状態 - } - } - tdata.flag.SetBits(Flag_Suspend, suspend); + // セルフコリジョン更新 + selfCollisionUpdateSet.Add(teamId); - // 有効状態と同期まちフラグの2つで実行判定 - if (tdata.flag.IsSet(Flag_Enable) == false || tdata.flag.IsSet(Flag_Suspend)) - continue; + // 接線モード + tdata.flag.SetBits(Flag_Tangent, cloth.SerializeData.meshWriteMode == ClothMeshWriteMode.PositionAndNormalTangent); + cprocess.SetState(ClothProcess.State_UpdateTangent, tdata.flag.IsSet(Flag_Tangent)); - //------------------------------------------------------------- - bool selfCollisionUpdate = false; - - // パラメータ変更反映 - if (cprocess.IsEnable) - { - if (cprocess.IsState(ClothProcess.State_ParameterDirty)) - { - //Develop.DebugLog($"Update Parameters {teamId}"); - // コライダー更新(内部でteamData更新) - MagicaManager.Collider.UpdateColliders(cprocess); - - // カリング用アニメーターとレンダラー更新 - cprocess.UpdateCullingAnimatorAndRenderers(); - - // パラメータ変更 - cprocess.SyncParameters(); - parameterArray[teamId] = cprocess.parameters; - tdata.updateMode = cloth.SerializeData.updateMode; - tdata.animationPoseRatio = cloth.SerializeData.animationPoseRatio; - tdata.flag.SetBits(Flag_Spring, cprocess.clothType == ClothProcess.ClothType.BoneSpring && cprocess.parameters.springConstraint.springPower > 0.0f); // Spring利用フラグ - - // セルフコリジョン更新 - selfCollisionUpdate = true; - - cprocess.SetState(ClothProcess.State_ParameterDirty, false); - } - if (cprocess.IsState(ClothProcess.State_SkipWritingDirty)) - { - bool skipWriting = cprocess.IsState(ClothProcess.State_SkipWriting); - - // チームへ反映 - tdata.flag.SetBits(Flag_SkipWriting, skipWriting); - - // RenderDataへ反映 - foreach (var rinfo in cprocess.renderMeshInfoList) - { - var renderData = MagicaManager.Render.GetRendererData(rinfo.renderHandle); - renderData.UpdateSkipWriting(); - } - - cprocess.SetState(ClothProcess.State_SkipWritingDirty, false); - } - } - - // チーム同期 - // 同期チェーンをたどり先端のチームを参照する - int oldSyncTeamId = tdata.syncTeamId; - var syncCloth = cloth.SyncCloth; - if (syncCloth != null) - { - // デッドロック対策 - var c = syncCloth; - while (c) - { - if (c == cloth) - { - syncCloth = null; - c = null; - } - else - c = c.SyncCloth; - } - } - tdata.syncTeamId = syncCloth != null ? syncCloth.Process.TeamId : 0; - tdata.flag.SetBits(Flag_Synchronization, tdata.syncTeamId != 0); - tdata.syncCenterTransformIndex = 0; - if (oldSyncTeamId != tdata.syncTeamId) - { - // 変更あり! - - // 同期解除 - if (oldSyncTeamId > 0) - { - Develop.DebugLog($"Desynchronization! (1) {teamId}"); - ref var syncTeamData = ref GetTeamDataRef(oldSyncTeamId); - RemoveSyncParent(ref syncTeamData, teamId); - } - - // 同期変更 - if (syncCloth != null) - { - ref var syncTeamData = ref GetTeamDataRef(syncCloth.Process.TeamId); - - // 相手に自身を登録 - AddSyncParent(ref syncTeamData, teamId); - - // 時間リセットフラグクリア - tdata.flag.SetBits(Flag_TimeReset, false); - - Develop.DebugLog($"Synchronization! {teamId}->{syncCloth.Process.TeamId}"); - } - else - { - // 同期解除 - cloth.SerializeData.selfCollisionConstraint.syncPartner = null; - //tdata.frequency = cprocess.parameters.solverFrequency; - Develop.DebugLog($"Desynchronization! (2) {teamId}"); - } - - // セルフコリジョン更新 - selfCollisionUpdate = true; - } - - // 時間の同期 - if (syncCloth && tdata.syncTeamId > 0) - { - ref var syncTeamData = ref GetTeamDataRef(syncCloth.Process.TeamId); - if (syncTeamData.IsValid) - { - // 時間同期 - tdata.updateMode = syncTeamData.updateMode; - //tdata.frequency = syncTeamData.frequency; - tdata.time = syncTeamData.time; - tdata.oldTime = syncTeamData.oldTime; - tdata.nowUpdateTime = syncTeamData.nowUpdateTime; - tdata.oldUpdateTime = syncTeamData.oldUpdateTime; - tdata.frameUpdateTime = syncTeamData.frameUpdateTime; - tdata.frameOldTime = syncTeamData.frameOldTime; - tdata.timeScale = syncTeamData.timeScale; - tdata.updateCount = syncTeamData.updateCount; - tdata.frameInterpolation = syncTeamData.frameInterpolation; - //Develop.DebugLog($"Team time sync:{teamId}->{syncCloth.Process.TeamId}"); - } - - // パラメータ同期 - // 同期中は一部のパラメータを連動させる - ref var clothParam = ref GetParametersRef(teamId); - clothParam.inertiaConstraint.worldInertia = syncCloth.SerializeData.inertiaConstraint.worldInertia; - clothParam.inertiaConstraint.movementSpeedLimit = syncCloth.SerializeData.inertiaConstraint.movementSpeedLimit.GetValue(-1); - clothParam.inertiaConstraint.rotationSpeedLimit = syncCloth.SerializeData.inertiaConstraint.rotationSpeedLimit.GetValue(-1); - clothParam.inertiaConstraint.teleportMode = syncCloth.SerializeData.inertiaConstraint.teleportMode; - clothParam.inertiaConstraint.teleportDistance = syncCloth.SerializeData.inertiaConstraint.teleportDistance; - clothParam.inertiaConstraint.teleportRotation = syncCloth.SerializeData.inertiaConstraint.teleportRotation; - - // 同期先のセンタートランスフォームインデックスを記録 - tdata.syncCenterTransformIndex = syncTeamData.centerTransformIndex; - } - - // 集計まわり - ref var param = ref GetParametersRef(teamId); - if (param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Edge) - edgeColliderCollisionCount += tdata.EdgeCount; - - // セルフコリジョンのフラグやバッファ更新 - if (selfCollisionUpdate) - { - //Develop.DebugLog("Update Selfcollision"); - MagicaManager.Simulation.selfCollisionConstraint.UpdateTeam(teamId); - } + parameterDirtyList.RemoveAt(i); } + // (2)書き込み停止反映 + for (int i = 0; i < skipWritingDirtyList.Count;) + { + var cprocess = skipWritingDirtyList[i]; + if (cprocess == null) + { + skipWritingDirtyList.RemoveAt(i); + continue; + } + if (cprocess.IsEnable == false) + { + i++; + continue; + } + + bool skipWriting = cprocess.IsState(ClothProcess.State_SkipWriting); + + int teamId = cprocess.TeamId; + ref var tdata = ref GetTeamDataRef(teamId); + + // チームへ反映 + tdata.flag.SetBits(Flag_SkipWriting, skipWriting); + + // RenderDataへ反映 + foreach (var rinfo in cprocess.renderMeshInfoList) + { + var renderData = rm.GetRendererData(rinfo.renderHandle); + renderData.UpdateSkipWriting(); + } + + skipWritingDirtyList.RemoveAt(i); + } + +#if true + // (3A)チーム前処理ジョブ + // このジョブは相互参照があるので並列化できない + var job1 = new AlwaysTeamUpdatePreJob() + { + teamDataArray = teamDataArray.GetNativeArray(), + parameterArray = parameterArray.GetNativeArray(), + + comp2SuspendCounterMap = comp2SuspendCounterMap, + comp2TeamIdMap = comp2TeamIdMap, + comp2SyncPartnerCompMap = comp2SyncPartnerCompMap, + comp2SyncTopCompMap = comp2SyncTopCompMap, + selfCollisionUpdateSet = selfCollisionUpdateSet, + edgeColliderCollisionCountBuff = edgeColliderCollisionCountBuff, + }; + var jobHandle1 = job1.Schedule(); + + // (3B)コンポーネント座標読み込みジョブ + // 3Aと並列実行 + var jobHandle2 = bm.ReadComponentTransform(default); + + JobHandle.ScheduleBatchedJobs(); // 即時開始 +#endif + + // (4)他のコンポーネントを参照する必要がある処理 + startClothUpdateComponentProfiler.Begin(); + animatorUpdateModeMap.Clear(); + foreach (var cprocess in cm.clothSet) + { + if (cprocess.TeamId == 0) + continue; + + // 連動アニメーターの更新モード取得 + if (cprocess.interlockingAnimator) + { + int animatorId = cprocess.interlockingAnimator.GetInstanceID(); + if (animatorUpdateModeMap.ContainsKey(animatorId) == false) + { + animatorUpdateModeMap.Add(animatorId, (int)cprocess.interlockingAnimator.updateMode); + } + } + + // 同期時は同期先を見る + var refCloth = cprocess.SyncTopCloth != null ? cprocess.SyncTopCloth : cprocess.cloth; + var sdata = refCloth.SerializeData; + +#if true + // アンカー参照オブジェクト + var anchorTransform = sdata.inertiaConstraint.anchor; + int anchorTransformId = anchorTransform != null ? anchorTransform.GetInstanceID() : 0; + if (anchorTransformId != 0 && transformPositionMap.ContainsKey(anchorTransformId) == false) + { + // 参照オブジェクトの座標取得 + transformPositionMap.Add(anchorTransformId, anchorTransform.position); + transformRotationMap.Add(anchorTransformId, anchorTransform.rotation); + } + if (cprocess.anchorTransformId != anchorTransformId) + { + // 変更あり + cprocess.anchorTransformId = anchorTransformId; + teamAnchorTransformIndexArray[cprocess.TeamId] = anchorTransformId; + } + + // 距離カリング参照オブジェクト + int distanceObjectId = sdata.cullingSettings.distanceCullingReferenceObject != null ? sdata.cullingSettings.distanceCullingReferenceObject.GetInstanceID() : 0; + if (distanceObjectId != 0 && transformPositionMap.ContainsKey(distanceObjectId) == false) + { + // 参照オブジェクトの座標取得 + transformPositionMap.Add(distanceObjectId, sdata.cullingSettings.distanceCullingReferenceObject.transform.position); + } + if (cprocess.distanceReferenceObjectId != distanceObjectId) + { + // 変更あり + cprocess.distanceReferenceObjectId = distanceObjectId; + teamDistanceTransformIndexArray[cprocess.TeamId] = distanceObjectId; + } +#endif + } + + // メインカメラ座標 + bool hasMainCamera = Camera.main != null; + float3 mainCameraPosition = Camera.main ? Camera.main.transform.position : 0; + transformPositionMap.Add(0, mainCameraPosition); + startClothUpdateComponentProfiler.End(); + + // チーム前処理ジョブ待ち + jobHandle1.Complete(); + jobHandle2.Complete(); + edgeColliderCollisionCount = edgeColliderCollisionCountBuff.Value; + + // (5)セルフコリジョンのフラグやバッファ更新 + if (selfCollisionUpdateSet.Count() > 0) + { + foreach (var teamId in selfCollisionUpdateSet) + { + sm.selfCollisionConstraint.UpdateTeam(teamId); + } + selfCollisionUpdateSet.Clear(); + } + + // (6)チーム後処理ジョブ #if true if (ActiveTeamCount > 0) { // フレーム更新時間 float deltaTime = Time.deltaTime; - float fixedDeltaTime = MagicaManager.Time.FixedUpdateCount * Time.fixedDeltaTime; + float fixedDeltaTime = tm.FixedUpdateCount * Time.fixedDeltaTime; float unscaledDeltaTime = Time.unscaledDeltaTime; - //Debug.Log($"DeltaTime:{deltaTime}, FixedDeltaTime:{fixedDeltaTime}, fixedUpdateCount:{fixedUpdateCount}"); + + //Debug.Log($"DeltaTime:{deltaTime}, FixedDeltaTime:{fixedDeltaTime}, simulationDeltaTime:{MagicaManager.Time.SimulationDeltaTime}, maxDeltaTime:{MagicaManager.Time.MaxDeltaTime}"); + //Debug.Log($"DeltaTime:{deltaTime}, FixedDeltaTime:{fixedDeltaTime}, simulationDeltaTime:{MagicaManager.Time.SimulationDeltaTime}"); // このJobは即時実行させる - var job = new AlwaysTeamUpdateJob() + var postJob = new AlwaysTeamUpdatePostJob() { teamCount = TeamCount, unityFrameDeltaTime = deltaTime, unityFrameFixedDeltaTime = fixedDeltaTime, unityFrameUnscaledDeltaTime = unscaledDeltaTime, - globalTimeScale = MagicaManager.Time.GlobalTimeScale, - simulationDeltaTime = MagicaManager.Time.SimulationDeltaTime, - maxDeltaTime = MagicaManager.Time.MaxDeltaTime, + globalTimeScale = tm.GlobalTimeScale, + simulationDeltaTime = tm.SimulationDeltaTime, + //maxDeltaTime = MagicaManager.Time.MaxDeltaTime, + maxSimmulationCountPerFrame = tm.maxSimulationCountPerFrame, + splitProxyMeshVertexCount = sm.splitProxyMeshVertexCount, - maxUpdateCount = maxUpdateCount, + //maxUpdateCount = maxUpdateCount, + teamStatus = teamStatus, teamDataArray = teamDataArray.GetNativeArray(), parameterArray = parameterArray.GetNativeArray(), + centerDataArray = centerDataArray.GetNativeArray(), + + componentPositionArray = bm.componentPositionArray.GetNativeArray(), + componentMinScaleArray = bm.componentMinScaleArray.GetNativeArray(), + hasMainCamera = hasMainCamera, + + comp2TeamIdMap = comp2TeamIdMap, + comp2SyncTopCompMap = comp2SyncTopCompMap, + animatorUpdateModeMap = animatorUpdateModeMap, + teamAnchorTransformIndexArray = teamAnchorTransformIndexArray.GetNativeArray(), + teamDistanceTransformIndexArray = teamDistanceTransformIndexArray.GetNativeArray(), + transformPositionMap = transformPositionMap, + transformRotationMap = transformRotationMap, + cullingDirtyList = cullingDirtyList, + + batchNormalClothTeamList = batchNormalClothTeamList, + batchSplitClothTeamList = batchSplitClothTeamList, }; - job.Run(); + postJob.Run(); + + // 距離カリング反映 + if (cullingDirtyList.Length > 0) + { + foreach (int teamId in cullingDirtyList) + { + ref var tdata = ref GetTeamDataRef(teamId); + var cprocess = GetClothProcess(teamId); + + bool invisible = tdata.IsDistanceCullingInvisible; + + // cprocessクラスにもコピーする + // 距離カリングでは表示/非表示切替時に常にリセットする + // またカメラカリングのKeepは強制解除する + cprocess.SetState(ClothProcess.State_DistanceCullingInvisible, invisible); + cprocess.SetState(ClothProcess.State_CameraCullingKeep, false); + + // 対応するレンダーデータに更新を指示する + cprocess.UpdateRendererUse(); + } + } } #endif } [BurstCompile] - struct AlwaysTeamUpdateJob : IJob + unsafe struct AlwaysTeamUpdatePreJob : IJob + { + public NativeArray teamDataArray; + public NativeArray parameterArray; + + // work + public NativeParallelHashMap comp2SuspendCounterMap; + public NativeParallelHashMap comp2TeamIdMap; + public NativeParallelHashMap comp2SyncPartnerCompMap; + public NativeParallelHashMap comp2SyncTopCompMap; + public NativeParallelHashSet selfCollisionUpdateSet; + public NativeReference edgeColliderCollisionCountBuff; + + public void Execute() + { + int edgeColliderCollisionCount = 0; + TeamData* tt = (TeamData*)teamDataArray.GetUnsafePtr(); + + foreach (var kv in comp2TeamIdMap) + { + int teamId = kv.Value; + if (teamId == 0) + continue; + + int compId = kv.Key; + ref var tdata = ref *(tt + teamId); + + // 作業フラグをクリア ------------------------------------- + tdata.flag.SetBits(Flag_RestoreTransformOnlyOnec, false); + + // 動作判定 ---------------------------------------------------- + if (tdata.flag.IsSet(Flag_Enable) == false) + continue; + + // 同期まち判定 ------------------------------------------------- + bool syncSuspend = true; + if (comp2SuspendCounterMap.ContainsKey(compId) == false || comp2SuspendCounterMap[compId] == 0) + syncSuspend = false; + + // 同期相手の有効状態 + if (comp2SyncPartnerCompMap.ContainsKey(compId)) + { + int syncCompId = comp2SyncPartnerCompMap[compId]; + if (comp2TeamIdMap.ContainsKey(syncCompId)) + { + int syncTeamId = comp2TeamIdMap[syncCompId]; + if (syncTeamId > 0) + { + ref var syncTeamData = ref *(tt + syncTeamId); + int syncSuspendCounter = comp2SuspendCounterMap.ContainsKey(syncCompId) ? comp2SuspendCounterMap[syncCompId] : 0; + if (syncTeamData.IsEnable && syncSuspendCounter == 0) + syncSuspend = false; // 相手も処理可能状態 + } + } + } + tdata.flag.SetBits(Flag_SyncSuspend, syncSuspend); + + // 同期待ちなら実行できない + if (tdata.flag.IsSet(Flag_SyncSuspend)) + continue; + + // チーム同期 -------------------------------------------------- + int oldSyncTeamId = tdata.syncTeamId; + tdata.syncTeamId = 0; + if (comp2SyncPartnerCompMap.ContainsKey(compId)) + { + int syncCompId = comp2SyncPartnerCompMap[compId]; + if (comp2TeamIdMap.ContainsKey(syncCompId)) + { + int syncTeamId = comp2TeamIdMap[syncCompId]; + tdata.syncTeamId = syncTeamId; + } + } + tdata.flag.SetBits(Flag_Synchronization, tdata.syncTeamId != 0); + tdata.syncCenterTransformIndex = 0; + if (oldSyncTeamId != tdata.syncTeamId) + { + // 変更あり! + // 同期解除 + if (oldSyncTeamId > 0) + { + //Debug.Log($"Desynchronization! (1) {teamId}"); + ref var syncTeamData = ref *(tt + oldSyncTeamId); + syncTeamData.syncParentTeamId.MC2RemoveItemAtSwapBack(teamId); + } + + // 同期変更 + if (tdata.syncTeamId != 0) + { + ref var syncTeamData = ref *(tt + tdata.syncTeamId); + + // 相手に自身を登録 + // 最大7まで + if (syncTeamData.syncParentTeamId.Length == syncTeamData.syncParentTeamId.Capacity) + { + //Debug.LogWarning($"Synchronous team number limit!"); + } + else + syncTeamData.syncParentTeamId.Add(teamId); + + // 時間リセットフラグクリア + tdata.flag.SetBits(Flag_TimeReset, false); + + //Debug.Log($"Synchronization! {teamId}->{tdata.syncTeamId}"); + } + else + { + // 同期解除 + //cloth.SerializeData.selfCollisionConstraint.syncPartner = null; + //Debug.Log($"Desynchronization! (2) {teamId}"); + } + + // セルフコリジョン更新セットに追加 + selfCollisionUpdateSet.Add(teamId); + } + + // 時間とパラメータの同期 + var clothParam = parameterArray[teamId]; + + // トップ階層の同期クロスを見る + int syncTopTeamId = 0; + if (comp2SyncTopCompMap.ContainsKey(compId)) + { + int syncTopCompId = comp2SyncTopCompMap[compId]; + if (comp2TeamIdMap.ContainsKey(syncTopCompId)) + { + syncTopTeamId = comp2TeamIdMap[syncTopCompId]; + ref var syncTeamData = ref *(tt + syncTopTeamId); + + // 時間同期 + if (syncTeamData.IsValid) + { + tdata.originalUpdateMode = syncTeamData.originalUpdateMode; + tdata.updateMode = syncTeamData.updateMode; + //tdata.frequency = syncTeamData.frequency; + tdata.time = syncTeamData.time; + tdata.oldTime = syncTeamData.oldTime; + tdata.nowUpdateTime = syncTeamData.nowUpdateTime; + tdata.oldUpdateTime = syncTeamData.oldUpdateTime; + tdata.frameUpdateTime = syncTeamData.frameUpdateTime; + tdata.frameOldTime = syncTeamData.frameOldTime; + tdata.timeScale = syncTeamData.timeScale; + tdata.updateCount = syncTeamData.updateCount; + tdata.frameInterpolation = syncTeamData.frameInterpolation; + tdata.skipCount = syncTeamData.skipCount; + //Develop.DebugLog($"Team time sync:{teamId}->{syncCloth.Process.TeamId}"); + } + + // パラメータ同期 + // 同期中は一部のパラメータを連動させる + var syncClothParam = parameterArray[syncTopTeamId]; + clothParam.inertiaConstraint.anchorInertia = syncClothParam.inertiaConstraint.anchorInertia; + clothParam.inertiaConstraint.worldInertia = syncClothParam.inertiaConstraint.worldInertia; + clothParam.inertiaConstraint.movementInertiaSmoothing = syncClothParam.inertiaConstraint.movementInertiaSmoothing; + clothParam.inertiaConstraint.movementSpeedLimit = syncClothParam.inertiaConstraint.movementSpeedLimit; + clothParam.inertiaConstraint.rotationSpeedLimit = syncClothParam.inertiaConstraint.rotationSpeedLimit; + clothParam.inertiaConstraint.teleportMode = syncClothParam.inertiaConstraint.teleportMode; + clothParam.inertiaConstraint.teleportDistance = syncClothParam.inertiaConstraint.teleportDistance; + clothParam.inertiaConstraint.teleportRotation = syncClothParam.inertiaConstraint.teleportRotation; + parameterArray[teamId] = clothParam; + + // 同期先のセンタートランスフォームインデックスを記録 + tdata.syncCenterTransformIndex = syncTeamData.centerTransformIndex; + } + } + + // 集計まわり + if (clothParam.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Edge) + edgeColliderCollisionCount += tdata.EdgeCount; + } + + edgeColliderCollisionCountBuff.Value = edgeColliderCollisionCount; + } + } + + [BurstCompile] + struct AlwaysTeamUpdatePostJob : IJob { public int teamCount; public float unityFrameDeltaTime; @@ -1162,36 +1603,147 @@ namespace MagicaCloth2 public float unityFrameUnscaledDeltaTime; public float globalTimeScale; public float simulationDeltaTime; - public float maxDeltaTime; + public int maxSimmulationCountPerFrame; + public int splitProxyMeshVertexCount; - public NativeReference maxUpdateCount; + public NativeReference teamStatus; public NativeArray teamDataArray; [Unity.Collections.ReadOnly] public NativeArray parameterArray; + public NativeArray centerDataArray; + + public NativeArray componentPositionArray; + public NativeArray componentMinScaleArray; + public bool hasMainCamera; + + // work + public NativeParallelHashMap comp2TeamIdMap; + public NativeParallelHashMap comp2SyncTopCompMap; + public NativeParallelHashMap animatorUpdateModeMap; + public NativeArray teamAnchorTransformIndexArray; + public NativeArray teamDistanceTransformIndexArray; + public NativeParallelHashMap transformPositionMap; + public NativeParallelHashMap transformRotationMap; + public NativeList cullingDirtyList; + + public NativeList batchNormalClothTeamList; + public NativeList batchSplitClothTeamList; public void Execute() { int maxCount = 0; + int splitPointCollisionCount = 0; + int splitEdgeCollisionCount = 0; + int splitSelfCollisionCount = 0; - for (int teamId = 0; teamId < teamCount; teamId++) + for (int teamId = 1; teamId < teamCount; teamId++) { - if (teamId == 0) + var tdata = teamDataArray[teamId]; + int compId = tdata.componentId; + if (tdata.IsEnable == false) + continue; + if (tdata.flag.IsSet(Flag_SyncSuspend)) + continue; + + var param = parameterArray[teamId]; + + // 動作検証 + // 極小スケールによる機能停止 + tdata.flag.SetBits(Flag_ScaleSuspent, componentMinScaleArray[tdata.componentTransformIndex] < 1e-06f); + if (tdata.flag.IsSet(Flag_ScaleSuspent)) { - // グローバルチーム + teamDataArray[teamId] = tdata; continue; } - var tdata = teamDataArray[teamId]; - if (tdata.IsProcess == false) - continue; + // アンカー + int anchorTransformIndex = teamAnchorTransformIndexArray[teamId]; + bool oldAnchor = tdata.flag.IsSet(Flag_Anchor); + bool newAnchor = anchorTransformIndex != 0; + tdata.flag.SetBits(Flag_Anchor, newAnchor); + tdata.flag.SetBits(Flag_AnchorReset, oldAnchor != newAnchor); + var cdata = centerDataArray[teamId]; + cdata.anchorPosition = anchorTransformIndex != 0 ? transformPositionMap[anchorTransformIndex] : float3.zero; + cdata.anchorRotation = anchorTransformIndex != 0 ? transformRotationMap[anchorTransformIndex] : quaternion.identity; + centerDataArray[teamId] = cdata; - //Debug.Log($"Team Enable:{i}"); + // 距離カリング判定 + DistanceCullingUpdate(teamId, ref tdata, ref param); + + if (tdata.IsCullingInvisible) + { + teamDataArray[teamId] = tdata; + continue; + } + + // 更新モード + int syncTopTeamId = 0; + if (comp2SyncTopCompMap.ContainsKey(compId)) + { + int syncTopCompId = comp2SyncTopCompMap[compId]; + if (comp2TeamIdMap.ContainsKey(syncTopCompId)) + { + syncTopTeamId = comp2TeamIdMap[syncTopCompId]; + } + } + if (tdata.originalUpdateMode == ClothUpdateMode.AnimatorLinkage || syncTopTeamId > 0) + { + var originalUpdateMode = tdata.originalUpdateMode; + int animatorId = tdata.interlockingAnimatorId; + if (syncTopTeamId > 0) + { + var syncTeamData = teamDataArray[syncTopTeamId]; + originalUpdateMode = syncTeamData.originalUpdateMode; + animatorId = syncTeamData.interlockingAnimatorId; + } + + switch (originalUpdateMode) + { + case ClothUpdateMode.Normal: + case ClothUpdateMode.UnityPhysics: + case ClothUpdateMode.Unscaled: + tdata.updateMode = originalUpdateMode; + break; + case ClothUpdateMode.AnimatorLinkage: + if (animatorUpdateModeMap.ContainsKey(animatorId)) + { + AnimatorUpdateMode aniUpdateMode = (AnimatorUpdateMode)animatorUpdateModeMap[animatorId]; + switch (aniUpdateMode) + { + case AnimatorUpdateMode.Normal: + tdata.updateMode = ClothUpdateMode.Normal; + break; +#if UNITY_2023_1_OR_NEWER + case AnimatorUpdateMode.Fixed: + tdata.updateMode = ClothUpdateMode.UnityPhysics; + break; +#else + case AnimatorUpdateMode.AnimatePhysics: + tdata.updateMode = ClothUpdateMode.UnityPhysics; + break; +#endif + case AnimatorUpdateMode.UnscaledTime: + tdata.updateMode = ClothUpdateMode.Unscaled; + break; + default: + //Develop.DebugLogWarning($"[{cloth.name}] Unknown Animator UpdateMode:{interlockingAnimator.updateMode}"); + tdata.updateMode = ClothUpdateMode.Normal; + break; + } + } + else + tdata.updateMode = ClothUpdateMode.Normal; + break; + default: + //Develop.LogError($"[{cloth.name}] Unknown Cloth Update Mode:{cloth.SerializeData.updateMode}"); + tdata.updateMode = ClothUpdateMode.Normal; + break; + } + } // 時間リセット if (tdata.flag.IsSet(Flag_TimeReset)) { - //Debug.Log($"Team time Reset:{i}"); - tdata.time = 0; tdata.oldTime = 0; tdata.nowUpdateTime = 0; @@ -1201,27 +1753,37 @@ namespace MagicaCloth2 } // 更新時間 + //Debug.Log($"Team [{teamId}] updateMode:{(int)tdata.updateMode}"); float frameDeltaTime = tdata.IsFixedUpdate ? unityFrameFixedDeltaTime : (tdata.IsUnscaled ? unityFrameUnscaledDeltaTime : unityFrameDeltaTime); tdata.frameDeltaTime = frameDeltaTime; - - // 最大更新時間 - float deltaTime = math.min(frameDeltaTime, maxDeltaTime); + float deltaTime = frameDeltaTime; // タイムスケール float timeScale = tdata.timeScale * (tdata.IsUnscaled ? 1.0f : globalTimeScale); - timeScale = tdata.flag.IsSet(Flag_Suspend) ? 0.0f : timeScale; - //timeScale = tdata.IsCullingInvisible ? 0.0f : timeScale; + timeScale = tdata.flag.IsSet(Flag_SyncSuspend) ? 0.0f : timeScale; + tdata.nowTimeScale = timeScale; // 最終計算用タイムスケール // 加算時間 float addTime = deltaTime * timeScale; // 今回の加算時間 // 時間を加算 float time = tdata.time + addTime; - //Debug.Log($"[{i}] time:{time}, addTime:{addTime}, timeScale:{timeScale}, suspend:{tdata.flag.IsSet(Flag_Suspend)}"); - float interval = time - tdata.nowUpdateTime; - tdata.updateCount = (int)(interval / simulationDeltaTime); // 今回の更新回数 + + // 今回の予定更新回数 + int updateCount = (int)(interval / simulationDeltaTime); + + // 今回の更新回数(最大更新回数まで) + tdata.updateCount = math.min(updateCount, maxSimmulationCountPerFrame); + + // 今回のスキップ回数(最大更新回数超過分) + tdata.skipCount = updateCount - tdata.updateCount; + if (tdata.skipCount > 0) + { + // スキップ発生時はスキップ時間を無かったものとする + time = time - simulationDeltaTime * tdata.skipCount; + } if (tdata.updateCount > 0 && addTime == 0.0f) { @@ -1231,6 +1793,7 @@ namespace MagicaCloth2 // こうなると時間補間関連で0除算が発生して数値が壊れる // 誤差を修正する tdata.updateCount = 0; + tdata.skipCount = 0; tdata.nowUpdateTime = time - simulationDeltaTime + 0.0001f; } @@ -1257,740 +1820,119 @@ namespace MagicaCloth2 // 全体の最大実行回数 maxCount = math.max(maxCount, tdata.updateCount); - //Debug.Log($"[{teamId}] updateCount:{tdata.updateCount}, addtime:{addTime}, t.time:{tdata.time}, t.oldtime:{tdata.oldTime}"); - } + //Debug.Log($"[{teamId}] updateCount:{tdata.updateCount}, skipCount:{tdata.skipCount}, addtime:{addTime}, t.time:{tdata.time}, t.oldtime:{tdata.oldTime}, timeScale:{tdata.timeScale}"); - maxUpdateCount.Value = maxCount; - } - } - - bool AddSyncParent(ref TeamData tdata, int parentTeamId) - { - // 最大7まで - if (tdata.syncParentTeamId.Length == tdata.syncParentTeamId.Capacity) - { - Develop.LogWarning($"Synchronous team number limit!"); - return false; - } - tdata.syncParentTeamId.Add(parentTeamId); - - return true; - } - - void RemoveSyncParent(ref TeamData tdata, int parentTeamId) - { - tdata.syncParentTeamId.RemoveItemAtSwapBack(parentTeamId); - } - - //========================================================================================= - /// - /// チームごとのセンター姿勢の決定と慣性用の移動量計算 - /// および風の影響を計算 - /// - /// - /// - internal JobHandle CalcCenterAndInertiaAndWind(JobHandle jobHandle) - { - var bm = MagicaManager.Bone; - var vm = MagicaManager.VMesh; - var wm = MagicaManager.Wind; - - var job = new CalcCenterAndInertiaAndWindJob() - { - teamDataArray = teamDataArray.GetNativeArray(), - centerDataArray = MagicaManager.Team.centerDataArray.GetNativeArray(), - teamWindArray = teamWindArray.GetNativeArray(), - parameterArray = parameterArray.GetNativeArray(), - - positions = vm.positions.GetNativeArray(), - rotations = vm.rotations.GetNativeArray(), - vertexBindPoseRotations = vm.vertexBindPoseRotations.GetNativeArray(), - - fixedArray = MagicaManager.Simulation.inertiaConstraint.fixedArray.GetNativeArray(), - - transformPositionArray = bm.positionArray.GetNativeArray(), - transformRotationArray = bm.rotationArray.GetNativeArray(), - transformScaleArray = bm.scaleArray.GetNativeArray(), - - windZoneCount = wm.WindCount, - windDataArray = wm.windDataArray.GetNativeArray(), - }; - jobHandle = job.Schedule(TeamCount, 1, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct CalcCenterAndInertiaAndWindJob : IJobParallelFor - { - // team - public NativeArray teamDataArray; - public NativeArray centerDataArray; - public NativeArray teamWindArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - - // 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; - - // transform - [Unity.Collections.ReadOnly] - public NativeArray transformPositionArray; - [Unity.Collections.ReadOnly] - public NativeArray transformRotationArray; - [Unity.Collections.ReadOnly] - public NativeArray transformScaleArray; - - // wind - public int windZoneCount; - [Unity.Collections.ReadOnly] - public NativeArray windDataArray; - - // チームごと - public void Execute(int teamId) - { - if (teamId == 0) - return; - var tdata = teamDataArray[teamId]; - if (tdata.IsProcess == false) - return; - - var param = parameterArray[teamId]; - var cdata = centerDataArray[teamId]; - - // ■コンポーネントトランスフォーム同期 - // 同期中は同期先のコンポーネントトランスフォームからワールド慣性を計算する - int centerTransformIndex = (tdata.syncTeamId != 0 && tdata.flag.IsSet(Flag_Synchronization)) ? tdata.syncCenterTransformIndex : cdata.centerTransformIndex; - - // ■コンポーネント位置 - float3 componentWorldPos = transformPositionArray[centerTransformIndex]; - quaternion componentWorldRot = transformRotationArray[centerTransformIndex]; - float3 componentWorldScl = transformScaleArray[centerTransformIndex]; - cdata.componentWorldPosition = componentWorldPos; - cdata.componentWorldRotation = componentWorldRot; - - // コンポーネントスケール倍率 - float componentScaleRatio = math.length(componentWorldScl) / math.length(tdata.initScale); - - // ■クロスセンター位置 - var centerWorldPos = componentWorldPos; - var centerWorldRot = componentWorldRot; - var centerWorldScl = componentWorldScl; - - // 固定点リストがある場合は固定点の姿勢から算出する、ない場合はクロストランスフォームを使用する - if (tdata.fixedDataChunk.IsValid) - { - float3 cen = 0; - float3 nor = 0; - float3 tan = 0; - - int v_start = tdata.proxyCommonChunk.startIndex; - - int fcnt = tdata.fixedDataChunk.dataLength; - int fstart = tdata.fixedDataChunk.startIndex; - for (int i = 0; i < fcnt; i++) + // ジョブ情報の作成 + bool isSplitTeam = false; + bool isSelfCollisionJob = tdata.flag.IsSet(Flag_Self_PointPrimitive) + || tdata.flag.IsSet(Flag_Self_EdgePrimitive) + || tdata.flag.IsSet(Flag_Self_TrianglePrimitive); + if (isSelfCollisionJob) { - var l_findex = fixedArray[fstart + i]; - int vindex = l_findex + v_start; - - cen += positions[vindex]; - - var rot = rotations[vindex]; - rot = math.mul(rot, vertexBindPoseRotations[vindex]); - - nor += MathUtility.ToNormal(rot); - tan += MathUtility.ToTangent(rot); + // セルフコリジョン + // Splitジョブ + batchSplitClothTeamList.Add(teamId); + isSplitTeam = true; + splitSelfCollisionCount++; } -#if MC2_DEBUG - Develop.Assert(math.length(nor) > 0.0f); - Develop.Assert(math.length(tan) > 0.0f); -#endif - centerWorldPos = cen / fcnt; - centerWorldRot = MathUtility.ToRotation(math.normalize(nor), math.normalize(tan)); - } - var wtol = MathUtility.WorldToLocalMatrix(centerWorldPos, centerWorldRot, centerWorldScl); - - // フレーム移動量と速度 - float3 frameDeltaVector = componentWorldPos - cdata.oldComponentWorldPosition; - float frameDeltaAngle = MathUtility.Angle(cdata.oldComponentWorldRotation, componentWorldRot); - //Debug.Log($"frameDeltaVector:{frameDeltaVector}, frameDeltaAngle:{frameDeltaAngle}"); - - // ■テレポート判定(コンポーネント姿勢から判定する) - // 同期時は同期先のテレポートモードとパラメータが入っている - if (param.inertiaConstraint.teleportMode != InertiaConstraint.TeleportMode.None && tdata.IsReset == false) - { - // 移動と回転どちらか一方がしきい値を超えたらテレポートと判定 - bool isTeleport = false; - isTeleport = math.length(frameDeltaVector) >= param.inertiaConstraint.teleportDistance * componentScaleRatio ? true : isTeleport; - isTeleport = math.degrees(frameDeltaAngle) >= param.inertiaConstraint.teleportRotation ? true : isTeleport; - - if (isTeleport) + else { - switch (param.inertiaConstraint.teleportMode) + // セルフコリジョンなしではプロキシメッシュの頂点数が一定以上なら分割する + if (tdata.ParticleCount >= splitProxyMeshVertexCount) { - case InertiaConstraint.TeleportMode.Reset: - tdata.flag.SetBits(Flag_Reset, true); - break; - case InertiaConstraint.TeleportMode.Keep: - tdata.flag.SetBits(Flag_KeepTeleport, true); - break; - } - } - } - - // リセットおよび最新のセンター座標として格納 - if (tdata.IsReset) - { - cdata.oldComponentWorldPosition = componentWorldPos; - cdata.oldComponentWorldRotation = componentWorldRot; - - cdata.frameWorldPosition = centerWorldPos; - cdata.frameWorldRotation = centerWorldRot; - cdata.frameWorldScale = centerWorldScl; - cdata.oldFrameWorldPosition = centerWorldPos; - cdata.oldFrameWorldRotation = centerWorldRot; - cdata.oldFrameWorldScale = centerWorldScl; - cdata.nowWorldPosition = centerWorldPos; - cdata.nowWorldRotation = centerWorldRot; - cdata.nowWorldScale = centerWorldScl; - cdata.oldWorldPosition = centerWorldPos; - cdata.oldWorldRotation = centerWorldRot; - - tdata.centerWorldPosition = centerWorldPos; - } - else - { - cdata.frameWorldPosition = centerWorldPos; - cdata.frameWorldRotation = centerWorldRot; - cdata.frameWorldScale = centerWorldScl; - } - - // ■ワールド慣性シフト - float3 workOldComponentPosition = cdata.oldComponentWorldPosition; - quaternion workOldComponentRotation = cdata.oldComponentWorldRotation; - if (tdata.IsReset) - { - // リセット(なし) - cdata.frameComponentShiftVector = 0; - cdata.frameComponentShiftRotation = quaternion.identity; - } - else - { - cdata.frameComponentShiftVector = componentWorldPos - cdata.oldComponentWorldPosition; - cdata.frameComponentShiftRotation = MathUtility.FromToRotation(cdata.oldComponentWorldRotation, componentWorldRot); - float moveShiftRatio = 0.0f; - float rotationShiftRatio = 0.0f; - - // ■全体慣性シフト - float movementShift = 1.0f - param.inertiaConstraint.worldInertia; // 同期時は同期先の値が入っている - float rotationShift = 1.0f - param.inertiaConstraint.worldInertia; // 同期時は同期先の値が入っている - // KeepテレポートもしくはCulling時はシフト量100%で実装 - bool keep = tdata.IsKeepReset || tdata.IsCullingInvisible; - movementShift = keep ? 1.0f : movementShift; - rotationShift = keep ? 1.0f : rotationShift; - if (movementShift > Define.System.Epsilon || rotationShift > Define.System.Epsilon) - { - // 全体シフトあり - tdata.flag.SetBits(Flag_InertiaShift, true); - moveShiftRatio = movementShift; - rotationShiftRatio = rotationShift; - - workOldComponentPosition = math.lerp(workOldComponentPosition, componentWorldPos, movementShift); - workOldComponentRotation = math.slerp(workOldComponentRotation, componentWorldRot, rotationShift); - } - - // ■最大移動速度制限(全体シフトの結果から計算する) - float movementSpeedLimit = param.inertiaConstraint.movementSpeedLimit * componentScaleRatio; // 同期時は同期先の値が入っている - float rotationSpeedLimit = param.inertiaConstraint.rotationSpeedLimit; // 同期時は同期先の値が入っている - float3 deltaVector = componentWorldPos - workOldComponentPosition; - float deltaAngle = MathUtility.Angle(workOldComponentRotation, componentWorldRot); - float frameSpeed = tdata.frameDeltaTime > 0.0f ? math.length(deltaVector) / tdata.frameDeltaTime : 0.0f; - float frameRotationSpeed = tdata.frameDeltaTime > 0.0f ? math.degrees(deltaAngle) / tdata.frameDeltaTime : 0.0f; - if (frameSpeed > movementSpeedLimit && movementSpeedLimit >= 0.0f) - { - tdata.flag.SetBits(Flag_InertiaShift, true); - float moveLimitRatio = math.saturate(math.max(frameSpeed - movementSpeedLimit, 0.0f) / frameSpeed); - moveShiftRatio = math.lerp(moveShiftRatio, 1.0f, moveLimitRatio); - workOldComponentPosition = math.lerp(workOldComponentPosition, componentWorldPos, moveLimitRatio); - } - if (frameRotationSpeed > rotationSpeedLimit && rotationSpeedLimit >= 0.0f) - { - tdata.flag.SetBits(Flag_InertiaShift, true); - float rotationLimitRatio = math.saturate(math.max(frameRotationSpeed - rotationSpeedLimit, 0.0f) / frameRotationSpeed); - rotationShiftRatio = math.lerp(rotationShiftRatio, 1.0f, rotationLimitRatio); - workOldComponentRotation = math.slerp(workOldComponentRotation, componentWorldRot, rotationLimitRatio); - } - - // ■慣性シフト最終設定 - if (tdata.IsInertiaShift) - { - cdata.frameComponentShiftVector *= moveShiftRatio; - cdata.frameComponentShiftRotation = math.slerp(quaternion.identity, cdata.frameComponentShiftRotation, rotationShiftRatio); - - cdata.oldFrameWorldPosition = MathUtility.ShiftPosition(cdata.oldFrameWorldPosition, cdata.oldComponentWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); - cdata.oldFrameWorldRotation = math.mul(cdata.frameComponentShiftRotation, cdata.oldFrameWorldRotation); - - cdata.nowWorldPosition = MathUtility.ShiftPosition(cdata.nowWorldPosition, cdata.oldComponentWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); - cdata.nowWorldRotation = math.mul(cdata.frameComponentShiftRotation, cdata.nowWorldRotation); - } - } - //Debug.Log($"team:[{teamId}] centerTransformIndex:{centerTransformIndex}"); - //Debug.Log($"team:[{teamId}] worldInertia:{param.inertiaConstraint.worldInertia}"); - //Debug.Log($"team:[{teamId}] movementSpeedLimit:{param.inertiaConstraint.movementSpeedLimit}"); - //Debug.Log($"team:[{teamId}] rotationSpeedLimit:{param.inertiaConstraint.rotationSpeedLimit}"); - - // ■ワールド移動方向と速度割り出し(慣性シフト後の移動量で計算) - float3 movingVector = componentWorldPos - workOldComponentPosition; - float movingLength = math.length(movingVector); - cdata.frameMovingSpeed = tdata.frameDeltaTime > 0.0f ? movingLength / tdata.frameDeltaTime : 0.0f; - cdata.frameMovingDirection = movingLength > 1e-06f ? movingVector / movingLength : 0; - - //Debug.Log($"frameWorldPosition:{cdata.frameWorldPosition}, framwWorldRotation:{cdata.frameWorldRotation.value}"); - //Debug.Log($"oldFrameWorldPosition:{cdata.oldFrameWorldPosition}, oldFrameWorldRotation:{cdata.oldFrameWorldRotation.value}"); - //Debug.Log($"nowWorldPosition:{cdata.nowWorldPosition}, nowWorldRotation:{cdata.nowWorldRotation.value}"); - //Debug.Log($"oldWorldPosition:{cdata.oldWorldPosition}, oldWorldRotation:{cdata.oldWorldRotation.value}"); - - // センターローカル座標 - float3 localCenterPos = MathUtility.InverseTransformPoint(centerWorldPos, wtol); - cdata.frameLocalPosition = localCenterPos; - - // 速度安定化処理 - if (tdata.flag.IsSet(Flag_Reset) || tdata.flag.IsSet(Flag_TimeReset)) - { - tdata.velocityWeight = param.stablizationTimeAfterReset > 1e-06f ? 0.0f : 1.0f; - tdata.blendWeight = tdata.velocityWeight; - } - - // 風の影響を計算 - Wind(teamId, param, centerWorldPos); - - centerDataArray[teamId] = cdata; - teamDataArray[teamId] = tdata; - } - - /// - /// チームが受ける風ゾーンのリストを作成する - /// ゾーンが追加タイプでない場合はチームが接触する最も体積が小さいゾーンが1つ有効になる。 - /// ゾーンが追加タイプの場合は最大3つまでが有効になる。 - /// - /// - /// - /// - void Wind(int teamId, in ClothParameters param, in float3 centerWorldPos) - { - var oldTeamWindData = teamWindArray[teamId]; - var newTeamWindData = new TeamWindData(); - if (windZoneCount > 0 && param.wind.IsValid()) - { - float minVolume = float.MaxValue; - int addWindCount = 0; - int latestWindId = -1; - - for (int windId = 0; windId < windZoneCount; windId++) - { - var wdata = windDataArray[windId]; - if (wdata.IsValid() == false || wdata.IsEnable() == false) - continue; - - // チームが風エリアに入っているか判定する - // 加算風は最大3つまで - bool isAdditin = wdata.IsAddition(); - if (isAdditin && addWindCount >= 3) - continue; - - // 風ゾーンのローカル位置 - float3 lpos = math.transform(wdata.worldToLocalMatrix, centerWorldPos); - float llen = math.length(lpos); - - // エリア判定 - switch (wdata.mode) - { - case MagicaWindZone.Mode.BoxDirection: - var lv = math.abs(lpos) * 2; - if (lv.x > wdata.size.x || lv.y > wdata.size.y || lv.z > wdata.size.z) - continue; - break; - case MagicaWindZone.Mode.SphereDirection: - case MagicaWindZone.Mode.SphereRadial: - if (llen > wdata.size.x) - continue; - break; - } - - // エリア風の場合はボリューム判定(体積が小さいものが優先) - if (isAdditin == false && wdata.zoneVolume > minVolume) - continue; - - // 風の方向(world) - float3 mainDirection = wdata.worldWindDirection; - switch (wdata.mode) - { - case MagicaWindZone.Mode.SphereRadial: - if (llen <= 1e-06f) - continue; - var v = centerWorldPos - wdata.worldPositin; - mainDirection = math.normalize(v); - break; - } - //Debug.Log($"wdir:{mainDirection}"); - - // 風力 - float windMain = wdata.main; - switch (wdata.mode) - { - case MagicaWindZone.Mode.SphereRadial: - // 減衰 - if (llen <= 1e-06f) - continue; - float depth = math.saturate(llen / wdata.size.x); - float attenuation = wdata.attenuation.EvaluateCurveClamp01(depth); - windMain *= attenuation; - break; - } - - // 計算する風として登録する - var windInfo = new TeamWindInfo() - { - windId = windId, - time = -Define.System.WindMaxTime, // マイナス値からスタート - main = windMain, - direction = mainDirection - }; - if (isAdditin) - { - newTeamWindData.AddOrReplaceWindZone(windInfo, oldTeamWindData); - addWindCount++; + // Splitジョブ + batchSplitClothTeamList.Add(teamId); + isSplitTeam = true; } else { - newTeamWindData.RemoveWindZone(latestWindId); - newTeamWindData.AddOrReplaceWindZone(windInfo, oldTeamWindData); - minVolume = wdata.zoneVolume; - latestWindId = windId; + // Normalジョブ + batchNormalClothTeamList.Add(teamId); } } + + // SplitチームのPoint/Edgeコリジョンの有無 + if (isSplitTeam && tdata.UseColliderCount > 0) + { + if (param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Point) + splitPointCollisionCount++; + if (param.colliderCollisionConstraint.mode == ColliderCollisionConstraint.Mode.Edge) + splitEdgeCollisionCount++; + } } - // 移動風移植 - newTeamWindData.movingWind = oldTeamWindData.movingWind; - teamWindArray[teamId] = newTeamWindData; - - // debug - //newTeamWindData.DebugLog(teamId); - //Debug.Log($"[{teamId}] wind:{tdata.flag.IsSet(Flag_Wind)}, windCnt:{windInfo.windCount}, zone:{windInfo.windIdList}, dir:{windInfo.windDirectionList.c0},{windInfo.windDirectionList.c1},{windInfo.windDirectionList.c2},{windInfo.windDirectionList.c3}, main:{windInfo.windMainList}"); + teamStatus.Value = new int4(maxCount, splitPointCollisionCount, splitEdgeCollisionCount, splitSelfCollisionCount); } - } - //========================================================================================= - /// - /// ステップごとの前処理(ステップの開始に実行される) - /// - /// - /// - /// - internal JobHandle SimulationStepTeamUpdate(int updateIndex, JobHandle jobHandle) - { - var job = new SimulationStepTeamUpdateJob() + void DistanceCullingUpdate(int teamId, ref TeamData tdata, ref ClothParameters param) { - updateIndex = updateIndex, - simulationDeltaTime = MagicaManager.Time.SimulationDeltaTime, + // 現在の状態 + bool oldInvisible = tdata.IsDistanceCullingInvisible; + bool invisible; - teamDataArray = teamDataArray.GetNativeArray(), - parameterArray = parameterArray.GetNativeArray(), - centerDataArray = centerDataArray.GetNativeArray(), - teamWindArray = teamWindArray.GetNativeArray(), - }; - jobHandle = job.Schedule(TeamCount, 1, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct SimulationStepTeamUpdateJob : IJobParallelFor - { - public int updateIndex; - public float simulationDeltaTime; - - // team - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - public NativeArray centerDataArray; - public NativeArray teamWindArray; - - // チームごと - public void Execute(int teamId) - { - if (teamId == 0) - return; - var tdata = teamDataArray[teamId]; - if (tdata.IsProcess == false) - return; - - // ■ステップ実行時のみ処理する - bool runStep = updateIndex < tdata.updateCount; - tdata.flag.SetBits(Flag_StepRunning, runStep); - if (updateIndex >= tdata.updateCount) + // 距離カリングの有無 + if (param.culling.useDistanceCulling) { - teamDataArray[teamId] = tdata; - return; + // 距離カリング有効 + // 距離判定 + int transformId = teamDistanceTransformIndexArray[teamId]; + if (transformPositionMap.ContainsKey(transformId)) + { + // 現在コンポーネント位置(pos)は同期を取っていない + // これは2つのコンポーネントが同じ階層と同じ位置であることを想定しているためである + // そのため2つのコンポーネントの位置がずれていると予期せぬ動作不良を起こす危険性がある + float3 pos = componentPositionArray[tdata.componentTransformIndex]; + + // 参照オブジェクト位置(spos)は同期されている + float3 spos = transformPositionMap[transformId]; + + //Debug.Log($"[{teamId}] pos:{pos}, spos:{spos}"); + //Debug.Log($"[{teamId}] componentTransformIndex:{tdata.componentTransformIndex}, objTransformId:{transformId}"); + + float dist = math.distance(pos, spos); + float cullingDist = param.culling.distanceCullingLength; + if (hasMainCamera == false && tdata.componentTransformIndex == 0) + cullingDist = 1000000.0f; // メインカメラnull時の安全対策 + invisible = dist >= cullingDist; + + // フェードウエイト + float fadeDist = math.saturate(param.culling.distanceCullingFadeRatio) * cullingDist; + tdata.distanceWeight = 1.0f - math.saturate(math.unlerp(cullingDist - fadeDist, cullingDist, dist)); + } + else + { + // 距離カリング無効 + invisible = false; + tdata.distanceWeight = 1.0f; + } } - - //Debug.Log($"team[{teamId}] ({updateIndex}/{tdata.updateCount})"); - - // パラメータ - var param = parameterArray[teamId]; - - // ■時間更新 --------------------------------------------------- - // nowUpdateTime更新 - tdata.nowUpdateTime += simulationDeltaTime; - - // 今回のフレーム割合を計算する - // frameStartTimeからtime区間でのnowUpdateTimeの割合 - tdata.frameInterpolation = (tdata.nowUpdateTime - tdata.frameOldTime) / (tdata.time - tdata.frameOldTime); - //Debug.Log($"Team[{teamId}] time.{tdata.time}, oldTime:{tdata.oldTime}, frameTime:{tdata.frameUpdateTime}, frameOldTime:{tdata.frameOldTime}, nowUpdateTime:{tdata.nowUpdateTime}, frameInterp:{tdata.frameInterpolation}"); - - // ■センター --------------------------------------------------- - // 現在ステップでのセンタートランスフォーム姿勢を求める - var cdata = centerDataArray[teamId]; - cdata.oldWorldPosition = cdata.nowWorldPosition; - cdata.oldWorldRotation = cdata.nowWorldRotation; - cdata.nowWorldPosition = math.lerp(cdata.oldFrameWorldPosition, cdata.frameWorldPosition, tdata.frameInterpolation); - cdata.nowWorldRotation = math.slerp(cdata.oldFrameWorldRotation, cdata.frameWorldRotation, tdata.frameInterpolation); - cdata.nowWorldRotation = math.normalize(cdata.nowWorldRotation); // 必要 - float3 wscl = math.lerp(cdata.oldFrameWorldScale, cdata.frameWorldScale, tdata.frameInterpolation); - cdata.nowWorldScale = wscl; - //cdata.nowLocalToWorldMatrix = MathUtility.LocalToWorldMatrix(cdata.nowWorldPosition, cdata.nowWorldRotation, cdata.nowWorldScale); - - // 現在座標はteamDataにもコピーする - tdata.centerWorldPosition = cdata.nowWorldPosition; - - // ステップごとの移動量 - cdata.stepVector = cdata.nowWorldPosition - cdata.oldWorldPosition; - cdata.stepRotation = MathUtility.FromToRotation(cdata.oldWorldRotation, cdata.nowWorldRotation); - float stepAngle = MathUtility.Angle(cdata.oldWorldRotation, cdata.nowWorldRotation); - - // ステップごとの移動速度と回転速度 - //float stepMoveSpeed = math.length(cdata.stepVector) / simulationDeltaTime; // 移動速度(m/s) - //float stepAngularVelocity = stepAngle / simulationDeltaTime; // 回転速度(rad/s) - //cdata.angularVelocity = stepAngularVelocity; - - // ローカル慣性 - //float localInertia = 1.0f - param.inertiaConstraint.localInertia; - float localMovementInertia = 1.0f - param.inertiaConstraint.localInertia; - float localRotationInertia = 1.0f - param.inertiaConstraint.localInertia; -#if true - float3 localVector = cdata.stepVector * (1.0f - localMovementInertia); - float localMovementSpeed = math.length(localVector) / simulationDeltaTime; // ローカル移動速度(m/s) - if (localMovementSpeed > param.inertiaConstraint.localMovementSpeedLimit && param.inertiaConstraint.localMovementSpeedLimit >= 0.0f) - { - float t = param.inertiaConstraint.localMovementSpeedLimit / localMovementSpeed; - localMovementInertia = math.lerp(1.0f, localMovementInertia, t); - } - float localAngle = stepAngle * (1.0f - localRotationInertia); - float localAngleSpeed = math.degrees(localAngle / simulationDeltaTime); // ローカル回転速度(deg/s) - if (localAngleSpeed > param.inertiaConstraint.localRotationSpeedLimit && param.inertiaConstraint.localRotationSpeedLimit >= 0.0f) - { - float t = param.inertiaConstraint.localRotationSpeedLimit / localAngleSpeed; - localRotationInertia = math.lerp(1.0f, localRotationInertia, t); - } -#endif - cdata.stepMoveInertiaRatio = localMovementInertia; - cdata.stepRotationInertiaRatio = localRotationInertia; - - // 最終慣性 - cdata.inertiaVector = math.lerp(float3.zero, cdata.stepVector, localMovementInertia); - cdata.inertiaRotation = math.slerp(quaternion.identity, cdata.stepRotation, localRotationInertia); - //Debug.Log($"Team[{teamId}] stepSpeed:{stepSpeed}, moveInertiaRatio:{moveInertiaRatio}, inertiaVector:{cdata.inertiaVector}, rotationInertiaRatio:{rotationInertiaRatio}"); - - // ■遠心力用パラメータ算出 - // 今回ステップでの回転速度と回転軸 - cdata.angularVelocity = stepAngle / simulationDeltaTime; // 回転速度(rad/s) - if (cdata.angularVelocity > Define.System.Epsilon) - MathUtility.ToAngleAxis(cdata.stepRotation, out _, out cdata.rotationAxis); else - cdata.rotationAxis = 0; - //Debug.Log($"Team[{teamId}] angularVelocity:{math.degrees(cdata.angularVelocity)}, axis:{cdata.rotationAxis}, q:{cdata.stepRotation.value}"); - //Debug.Log($"Team[{teamId}] angularVelocity:{math.degrees(cdata.angularVelocity)}, now:{cdata.nowWorldRotation.value}, old:{cdata.oldWorldRotation.value}"); - - // チームスケール倍率 - tdata.scaleRatio = math.max(math.length(wscl) / math.length(tdata.initScale), 1e-06f); - //Debug.Log($"[{teamId}] scaleRatio:{tdata.scaleRatio}"); - - // ■重力方向割合 --------------------------------------------------- - float gravityDot = 1.0f; - if (math.lengthsq(param.gravityDirection) > Define.System.Epsilon) { - var falloffDir = math.mul(cdata.nowWorldRotation, cdata.initLocalGravityDirection); - gravityDot = math.dot(falloffDir, param.gravityDirection); - gravityDot = math.saturate(gravityDot * 0.5f + 0.5f); - } - tdata.gravityDot = gravityDot; - //Develop.DebugLog($"gdot:{gravityDot}"); - - // ■重力減衰 --------------------------------------------------- - float gravityRatio = 1.0f; - if (param.gravity > 1e-06f && param.gravityFalloff > 1e-06f) - { - gravityRatio = math.lerp(math.saturate(1.0f - param.gravityFalloff), 1.0f, math.saturate(1.0f - gravityDot)); - } - tdata.gravityRatio = gravityRatio; - - // 速度安定化時間の速度割合を更新 - if (tdata.velocityWeight < 1.0f) - { - float addw = param.stablizationTimeAfterReset > 1e-06f ? simulationDeltaTime / param.stablizationTimeAfterReset : 1.0f; - tdata.velocityWeight = math.saturate(tdata.velocityWeight + addw); - } - //Debug.Log($"{tdata.velocityWeight}"); - - // シミュレーション結果のブレンド割合 - tdata.blendWeight = math.saturate(tdata.velocityWeight * param.blendWeight); - //Debug.Log($"{tdata.blendWeight}"); - - // 風の時間更新 - UpdateWind(teamId, tdata, param.wind, cdata); - - // データ格納 - teamDataArray[teamId] = tdata; - centerDataArray[teamId] = cdata; - //Debug.Log($"[{updateIndex}/{updateCount}] frameRatio:{data.frameInterpolation}, inertiaPosition:{idata.inertiaPosition}"); - } - - // 各風ゾーンの時間更新 - void UpdateWind(int teamId, in TeamData tdata, in WindParams windParams, in InertiaConstraint.CenterData cdata) - { - if (windParams.IsValid() == false) - return; - - var teamWindData = teamWindArray[teamId]; - - // ゾーン風 - int cnt = teamWindData.ZoneCount; - for (int i = 0; i < cnt; i++) - { - var windInfo = teamWindData.windZoneList[i]; - UpdateWindTime(ref windInfo, windParams.frequency, simulationDeltaTime); - teamWindData.windZoneList[i] = windInfo; + // 距離カリング無効 + invisible = false; + tdata.distanceWeight = 1.0f; } - // 移動風 - var movingWindInfo = teamWindData.movingWind; - movingWindInfo.main = 0; - if (windParams.movingWind > 0.01f) + // 状態変更 + if (oldInvisible != invisible) { - movingWindInfo.main = (cdata.frameMovingSpeed * windParams.movingWind) / tdata.scaleRatio; - movingWindInfo.direction = -cdata.frameMovingDirection; - UpdateWindTime(ref movingWindInfo, windParams.frequency, simulationDeltaTime); + tdata.flag.SetBits(Flag_DistanceCullingInvisible, invisible); + //Debug.Log($"Change distance culling invisible:({oldInvisible}) -> ({invisible})"); + + // 距離カリングでは表示/非表示切替時に常にリセットする + // またカメラカリングのKeepは強制解除する + tdata.flag.SetBits(Flag_Reset, true); + tdata.flag.SetBits(Flag_CameraCullingKeep, false); + + // メインスレッド処理用のリストに追加する + cullingDirtyList.Add(teamId); } - teamWindData.movingWind = movingWindInfo; - - // 格納 - teamWindArray[teamId] = teamWindData; - } - - void UpdateWindTime(ref TeamWindInfo windInfo, float frequency, float simulationDeltaTime) - { - // 風速係数 - float mainRatio = windInfo.main / Define.System.WindBaseSpeed; // 0.0 ~ - - // 基本周期 - float freq = 0.2f + mainRatio * 0.5f; - freq *= frequency; // 0.0 ~ 2.0f; - freq = math.min(freq, 1.5f); // max 1.5 - freq *= simulationDeltaTime; - - // 時間加算 - windInfo.time = windInfo.time + freq; - - // timeオーバーフロー対策 - if (windInfo.time > Define.System.WindMaxTime) // 約6時間 - windInfo.time -= Define.System.WindMaxTime * 2; // マイナス側から再スタート } } - //========================================================================================= - /// - /// クロスシミュレーション更新後処理 - /// - /// - /// - internal JobHandle PostTeamUpdate(JobHandle jobHandle) + internal void RemoveSyncParent(ref TeamData tdata, int parentTeamId) { - var job = new PostTeamUpdateJob() - { - teamDataArray = teamDataArray.GetNativeArray(), - centerDataArray = centerDataArray.GetNativeArray(), - }; - jobHandle = job.Schedule(teamDataArray.Length, 1, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct PostTeamUpdateJob : IJobParallelFor - { - // team - public NativeArray teamDataArray; - public NativeArray centerDataArray; - - // チームごと - public void Execute(int teamId) - { - var tdata = teamDataArray[teamId]; - if (tdata.IsProcess == false) - return; - - var cdata = centerDataArray[teamId]; - - // コンポーネント位置 - cdata.oldComponentWorldPosition = cdata.componentWorldPosition; - cdata.oldComponentWorldRotation = cdata.componentWorldRotation; - - if (tdata.IsRunning) - { - // センターを更新 - cdata.oldFrameWorldPosition = cdata.frameWorldPosition; - cdata.oldFrameWorldRotation = cdata.frameWorldRotation; - cdata.oldFrameWorldScale = cdata.frameWorldScale; - - // 外力クリア - tdata.forceMode = ClothForceMode.None; - tdata.impactForce = 0; - } - - // フラグリセット - tdata.flag.SetBits(Flag_Reset, false); - tdata.flag.SetBits(Flag_TimeReset, false); - tdata.flag.SetBits(Flag_Running, false); - tdata.flag.SetBits(Flag_StepRunning, false); - tdata.flag.SetBits(Flag_KeepTeleport, false); - tdata.flag.SetBits(Flag_InertiaShift, false); - - // 時間調整(floatの精度問題への対処) - const float limitTime = 3600.0f; // 60min - if (tdata.time > limitTime * 2) - { - tdata.time -= limitTime; - tdata.oldTime -= limitTime; - tdata.nowUpdateTime -= limitTime; - tdata.oldUpdateTime -= limitTime; - tdata.frameUpdateTime -= limitTime; - tdata.frameOldTime -= limitTime; - } - - teamDataArray[teamId] = tdata; - centerDataArray[teamId] = cdata; - } + tdata.syncParentTeamId.MC2RemoveItemAtSwapBack(parentTeamId); } //========================================================================================= @@ -2045,6 +1987,784 @@ namespace MagicaCloth2 void MonitoringProcessUpdate() => MonitoringProcess(false); + //========================================================================================= + // Simulation + //========================================================================================= + /// + /// チームごとのセンター姿勢の決定と慣性用の移動量計算 + /// および風の影響を計算 + /// + internal static void SimulationCalcCenterAndInertiaAndWind( + float simulationDeltaTime, + + // team + int teamId, + ref TeamData tdata, + ref InertiaConstraint.CenterData cdata, + ref TeamWindData windData, + ref ClothParameters param, + + // vmesh + in NativeArray positions, + in NativeArray rotations, + in NativeArray vertexBindPoseRotations, + + // inertia + in NativeArray fixedArray, + + // transform + in NativeArray transformPositionArray, + in NativeArray transformRotationArray, + in NativeArray transformScaleArray, + + // wind + int windZoneCount, + in NativeArray windDataArray + ) + { + // ■コンポーネントトランスフォーム同期 + // 同期中は同期先のコンポーネントトランスフォームからワールド慣性を計算する + int centerTransformIndex = (tdata.syncTeamId != 0 && tdata.flag.IsSet(Flag_Synchronization)) ? tdata.syncCenterTransformIndex : cdata.centerTransformIndex; + + // ■コンポーネント姿勢 + float3 componentWorldPos = transformPositionArray[centerTransformIndex]; + quaternion componentWorldRot = transformRotationArray[centerTransformIndex]; + float3 componentWorldScl = transformScaleArray[cdata.centerTransformIndex]; // ただしスケールは同期させない!(v2.11.1) + cdata.componentWorldPosition = componentWorldPos; + cdata.componentWorldRotation = componentWorldRot; + cdata.componentWorldScale = componentWorldScl; + //Debug.Log($"componentWorldPos:{componentWorldPos}, componentWorldRot:{componentWorldRot.value}"); + + // コンポーネントスケール倍率 + float componentScaleRatio = math.length(componentWorldScl) / math.length(tdata.initScale); + + // ■マイナススケール + // マイナススケールの場合は計算に必要なデータを予め作成しておく + float3 oldInverseScaleDirection = tdata.negativeScaleDirection; + tdata.negativeScaleDirection = math.sign(componentWorldScl); // 各スケールの方向(1/-1) + tdata.negativeScaleChange = oldInverseScaleDirection * tdata.negativeScaleDirection; // 今回スケール反転された方向(1:変化なし, -1:反転あり) + //Debug.Log($"inverseScaleChange:{tdata.inverseScaleChange}"); + if (componentWorldScl.x < 0 || componentWorldScl.y < 0 || componentWorldScl.z < 0) + { + tdata.negativeScaleSign = -1; // マイナススケール時は(-1) + tdata.negativeScaleQuaternionValue = new float4(-math.sign(componentWorldScl), 1); // 回転反転用 + tdata.negativeScaleTriangleSign.x = (componentWorldScl.x < 0 || componentWorldScl.z < 0) ? -1 : 1; // TriangleBendingの法線フリップフラグ + tdata.negativeScaleTriangleSign.y = componentWorldScl.x < 0 ? -1 : 1; // TriangleBendingの接線フリップフラグ + tdata.flag.SetBits(Flag_NegativeScale, true); + } + else + { + tdata.negativeScaleSign = 1; + tdata.negativeScaleQuaternionValue = 1; + tdata.negativeScaleTriangleSign = 1; + tdata.flag.SetBits(Flag_NegativeScale, false); + } + // 以前とスケール方向が変わっていたいたら軸反転テレポートを行う + if (oldInverseScaleDirection.Equals(tdata.negativeScaleDirection) == false) + { + // 軸反転テレポート + // 本体がスケール反転するためシミュレーションに影響が出ないように必要な座標系を同様に反転させる + // 一旦クロスローカル空間に戻し軸反転してからワールドに書き戻す + tdata.flag.SetBits(Flag_NegativeScaleTeleport, true); + //Debug.LogWarning($"Negative Scale detection!"); + + // コンポーネント反転用マトリックス + float4x4 nowComponentLW = float4x4.TRS(componentWorldPos, componentWorldRot, componentWorldScl); + float4x4 oldComponentLW = float4x4.TRS(cdata.oldComponentWorldPosition, cdata.oldComponentWorldRotation, cdata.oldComponentWorldScale); + float4x4 componentNegativeM = math.mul(nowComponentLW, math.inverse(oldComponentLW)); + + // コンポーネント空間のものを反転させる + // Transformに関するものは回転を反転させる必要はない + cdata.oldComponentWorldPosition = MathUtility.TransformPoint(cdata.oldComponentWorldPosition, componentNegativeM); + cdata.oldComponentWorldScale = componentWorldScl; // スケールはリセット + cdata.oldAnchorPosition = MathUtility.TransformPoint(cdata.oldAnchorPosition, componentNegativeM); + cdata.smoothingVelocity = MathUtility.TransformVector(cdata.smoothingVelocity, componentNegativeM); + } + + float3 oldComponentWorldPosition = cdata.oldComponentWorldPosition; + quaternion oldComponentWorldRotation = cdata.oldComponentWorldRotation; + float3 oldComponentWorldScale = cdata.oldComponentWorldScale; + + // ■クロスセンター位置 + var centerWorldPos = componentWorldPos; + var centerWorldRot = componentWorldRot; + + // 固定点リストがある場合は固定点の姿勢から算出する、ない場合はクロストランスフォームを使用する + if (tdata.fixedDataChunk.IsValid) + { + float3 cen = 0; + float3 nor = 0; + float3 tan = 0; + + int v_start = tdata.proxyCommonChunk.startIndex; + + int fcnt = tdata.fixedDataChunk.dataLength; + int fstart = tdata.fixedDataChunk.startIndex; + for (int i = 0; i < fcnt; i++) + { + var l_findex = fixedArray[fstart + i]; + int vindex = l_findex + v_start; + + cen += positions[vindex]; + + var rot = rotations[vindex]; + + // マイナススケール + if (tdata.negativeScaleSign < 0) + { + MathUtility.ToNormalTangent(rot, out float3 n, out float3 t); + rot = MathUtility.ToRotation(-n, -t); + } + + // 頂点バインドポーズを乗算して初期姿勢の一定方向に合わせる + rot = math.mul(rot, vertexBindPoseRotations[vindex]); + + nor += MathUtility.ToNormal(rot); + tan += MathUtility.ToTangent(rot); + } + + // マイナススケール + nor *= (tdata.negativeScaleDirection.x < 0 || tdata.negativeScaleDirection.z < 0) ? -1 : 1; + tan *= (tdata.negativeScaleDirection.x < 0 || tdata.negativeScaleDirection.y < 0) ? -1 : 1; + +#if MC2_DEBUG + Develop.Assert(math.length(nor) > 0.0f); + Develop.Assert(math.length(tan) > 0.0f); +#endif + centerWorldPos = cen / fcnt; + centerWorldRot = MathUtility.ToRotation(math.normalize(nor), math.normalize(tan)); // 単位化必須 + } + var wtol = MathUtility.WorldToLocalMatrix(centerWorldPos, centerWorldRot, componentWorldScl); + //Debug.Log($"centerWorldPos:{centerWorldPos}, centerWorldRot:{centerWorldRot.value}"); + //Debug.Log($"centerWorldRot nor:{math.mul(centerWorldRot, math.up())}, tan:{math.mul(centerWorldRot, math.forward())}, bin:{math.mul(centerWorldRot, math.right())}"); + + // ■マイナススケール + if (tdata.IsNegativeScaleTeleport) + { + // センター反転用変換マトリックスを計算(2) + float4x4 nowLW = float4x4.TRS(centerWorldPos, centerWorldRot, componentWorldScl); + float4x4 oldLW = float4x4.TRS(cdata.oldFrameWorldPosition, cdata.oldFrameWorldRotation, cdata.oldFrameWorldScale); + float4x4 negativeM = math.mul(nowLW, math.inverse(oldLW)); + cdata.negativeScaleMatrix = negativeM; + } + + // ■アンカー + float3 anchorDeltaVector = 0; + quaternion anchorDeltaRotation = quaternion.identity; + if (tdata.flag.IsSet(Flag_AnchorReset) || tdata.IsReset) + { + cdata.oldAnchorPosition = cdata.anchorPosition; + cdata.oldAnchorRotation = cdata.anchorRotation; + cdata.anchorComponentLocalPosition = MathUtility.InverseTransformPoint(componentWorldPos, cdata.anchorPosition, cdata.anchorRotation, 1); + } + if (tdata.flag.IsSet(Flag_Anchor)) + { + // アンカーの移動回転影響 + float3 anchorCenterPosition = MathUtility.TransformPoint(cdata.anchorComponentLocalPosition, cdata.anchorPosition, cdata.anchorRotation, 1); + anchorDeltaVector = anchorCenterPosition - oldComponentWorldPosition; + anchorDeltaRotation = MathUtility.FromToRotation(cdata.oldAnchorRotation, cdata.anchorRotation); + + // アンカーの影響割合 + float anchorRatio = 1.0f - param.inertiaConstraint.anchorInertia; + anchorDeltaVector = math.lerp(float3.zero, anchorDeltaVector, anchorRatio); + anchorDeltaRotation = math.slerp(quaternion.identity, anchorDeltaRotation, anchorRatio); + + // 打ち消す + oldComponentWorldPosition += anchorDeltaVector; + oldComponentWorldRotation = math.mul(anchorDeltaRotation, oldComponentWorldRotation); + + tdata.flag.SetBits(Flag_InertiaShift, true); + } + + // フレーム移動量と速度 + float3 frameDeltaVector = componentWorldPos - oldComponentWorldPosition; + float frameDeltaAngle = MathUtility.Angle(oldComponentWorldRotation, componentWorldRot); + //Debug.Log($"frameDeltaVector:{frameDeltaVector}, frameDeltaAngle:{frameDeltaAngle}"); + + // ■テレポート判定(コンポーネント姿勢から判定する) + // 同期時は同期先のテレポートモードとパラメータが入っている + if (param.inertiaConstraint.teleportMode != InertiaConstraint.TeleportMode.None && tdata.IsReset == false) + { + // 移動と回転どちらか一方がしきい値を超えたらテレポートと判定 + bool isTeleport = false; + isTeleport = math.length(frameDeltaVector) >= param.inertiaConstraint.teleportDistance * componentScaleRatio ? true : isTeleport; + isTeleport = math.degrees(frameDeltaAngle) >= param.inertiaConstraint.teleportRotation ? true : isTeleport; + + if (isTeleport) + { + //Debug.Log($"[{teamId}] Auto Teleport!"); + switch (param.inertiaConstraint.teleportMode) + { + case InertiaConstraint.TeleportMode.Reset: + tdata.flag.SetBits(Flag_Reset, true); + break; + case InertiaConstraint.TeleportMode.Keep: + tdata.flag.SetBits(Flag_KeepTeleport, true); + break; + } + } + } + + // ■スムージング + // ワールド慣性の急激な変化および小刻みな変化によりクロスが乱れる問題を解消するために慣性をスムージングする + // ・慣性の急激な変化(急発進・急停止)によるクロスの乱れの緩和 + // ・慣性の小刻みな変化によるクロスの振動の緩和 + float3 smoothDeltaVector = 0; +#if true + if (param.inertiaConstraint.movementInertiaSmoothing >= 1e-06f) + { + // 慣性速度をスムージングする + // 測定はシミュレーションが実行される場合のみ行う(そうしないと振動が発生する) + if (tdata.IsRunning) + { + float3 frameDeltaVelocity = tdata.frameDeltaTime > 0.0f ? frameDeltaVector / tdata.frameDeltaTime : 0; // 速度ベクトル(m/s) + float movementSpeedLimit = param.inertiaConstraint.movementSpeedLimit * componentScaleRatio; // 同期時は同期先の値が入っている + if (movementSpeedLimit >= 0.0f) + { + // 最大速度制限 + frameDeltaVelocity = MathUtility.ClampVector(frameDeltaVelocity, movementSpeedLimit); + } + float averageRatio = math.saturate(math.pow(1.0f - param.inertiaConstraint.movementInertiaSmoothing, 3.0f) * 0.99f + 0.01f); + cdata.smoothingVelocity = math.lerp(cdata.smoothingVelocity, frameDeltaVelocity, averageRatio); // 比重により平滑化 + } + //Debug.Log($"smoothingVelocity:{cdata.smoothingVelocity}"); + + // スムージングした慣性速度に基づいて1つ前のコンポーネント位置を補正する + // 処理的にはアンカーと同じ考え + float3 smoothPos = componentWorldPos - cdata.smoothingVelocity * tdata.frameDeltaTime; + smoothDeltaVector = smoothPos - oldComponentWorldPosition; + oldComponentWorldPosition = smoothPos; + tdata.flag.SetBits(Flag_InertiaShift, true); + } +#endif + + // リセットおよび最新のセンター座標として格納 + cdata.frameWorldPosition = centerWorldPos; + cdata.frameWorldRotation = centerWorldRot; + cdata.frameWorldScale = componentWorldScl; + if (tdata.IsReset) + { + //Debug.LogWarning($"Team Reset!"); + cdata.oldComponentWorldPosition = componentWorldPos; + cdata.oldComponentWorldRotation = componentWorldRot; + cdata.oldComponentWorldScale = componentWorldScl; + oldComponentWorldPosition = componentWorldPos; + oldComponentWorldRotation = componentWorldRot; + oldComponentWorldScale = componentWorldScl; + + cdata.oldFrameWorldPosition = centerWorldPos; + cdata.oldFrameWorldRotation = centerWorldRot; + cdata.oldFrameWorldScale = componentWorldScl; + cdata.nowWorldPosition = centerWorldPos; + cdata.nowWorldRotation = centerWorldRot; + //cdata.nowWorldScale = centerWorldScl; + cdata.oldWorldPosition = centerWorldPos; + cdata.oldWorldRotation = centerWorldRot; + //tdata.centerWorldPosition = centerWorldPos; + } + else if (tdata.IsNegativeScaleTeleport) + { + // マイナススケール + // センター空間に関するものはリセットする + //Debug.LogWarning($"Team NegativeScale Reset!"); + cdata.oldFrameWorldPosition = centerWorldPos; + cdata.oldFrameWorldRotation = centerWorldRot; + cdata.oldFrameWorldScale = componentWorldScl; + cdata.nowWorldPosition = centerWorldPos; + cdata.nowWorldRotation = centerWorldRot; + //cdata.nowWorldScale = centerWorldScl; + cdata.oldWorldPosition = centerWorldPos; + cdata.oldWorldRotation = centerWorldRot; + //tdata.centerWorldPosition = centerWorldPos; + } + + // ■ワールド慣性シフト + float3 workOldComponentPosition = oldComponentWorldPosition; + quaternion workOldComponentRotation = oldComponentWorldRotation; + if (tdata.IsReset) + { + // リセット(なし) + cdata.frameComponentShiftVector = 0; + cdata.frameComponentShiftRotation = quaternion.identity; + + // スムージングリセット + cdata.smoothingVelocity = 0; + smoothDeltaVector = 0; + } + else + { + cdata.frameComponentShiftVector = componentWorldPos - oldComponentWorldPosition; + cdata.frameComponentShiftRotation = MathUtility.FromToRotation(oldComponentWorldRotation, componentWorldRot); + //Debug.Log($"frameComponentShiftVector:{cdata.frameComponentShiftVector}, frameComponentShiftRotation:{cdata.frameComponentShiftRotation.value}"); + float moveShiftRatio = 0.0f; + float rotationShiftRatio = 0.0f; + + // ■全体慣性シフト + float movementShift = 1.0f - param.inertiaConstraint.worldInertia; // 同期時は同期先の値が入っている + float rotationShift = 1.0f - param.inertiaConstraint.worldInertia; // 同期時は同期先の値が入っている + + // KeepテレポートもしくはCulling時はシフト量100%で実装 + //bool keep = tdata.IsKeepReset || tdata.IsCameraCullingInvisible; + bool keep = tdata.IsKeepReset || tdata.IsCullingInvisible; + movementShift = keep ? 1.0f : movementShift; + rotationShift = keep ? 1.0f : rotationShift; + + if (movementShift > Define.System.Epsilon || rotationShift > Define.System.Epsilon) + { + // 全体シフトあり + tdata.flag.SetBits(Flag_InertiaShift, true); + moveShiftRatio = movementShift; + rotationShiftRatio = rotationShift; + + workOldComponentPosition = math.lerp(workOldComponentPosition, componentWorldPos, movementShift); + workOldComponentRotation = math.slerp(workOldComponentRotation, componentWorldRot, rotationShift); + } + + // ■最大移動速度制限(全体シフトの結果から計算する) + float movementSpeedLimit = param.inertiaConstraint.movementSpeedLimit * componentScaleRatio; // 同期時は同期先の値が入っている + float rotationSpeedLimit = param.inertiaConstraint.rotationSpeedLimit; // 同期時は同期先の値が入っている + float3 deltaVector = componentWorldPos - workOldComponentPosition; + float deltaAngle = MathUtility.Angle(workOldComponentRotation, componentWorldRot); + float frameSpeed = tdata.frameDeltaTime > 0.0f ? math.length(deltaVector) / tdata.frameDeltaTime : 0.0f; + float frameRotationSpeed = tdata.frameDeltaTime > 0.0f ? math.degrees(deltaAngle) / tdata.frameDeltaTime : 0.0f; + if (frameSpeed > movementSpeedLimit && movementSpeedLimit >= 0.0f) + { + tdata.flag.SetBits(Flag_InertiaShift, true); + float moveLimitRatio = math.saturate(math.max(frameSpeed - movementSpeedLimit, 0.0f) / frameSpeed); + moveShiftRatio = math.lerp(moveShiftRatio, 1.0f, moveLimitRatio); + workOldComponentPosition = math.lerp(workOldComponentPosition, componentWorldPos, moveLimitRatio); + } + if (frameRotationSpeed > rotationSpeedLimit && rotationSpeedLimit >= 0.0f) + { + tdata.flag.SetBits(Flag_InertiaShift, true); + float rotationLimitRatio = math.saturate(math.max(frameRotationSpeed - rotationSpeedLimit, 0.0f) / frameRotationSpeed); + rotationShiftRatio = math.lerp(rotationShiftRatio, 1.0f, rotationLimitRatio); + workOldComponentRotation = math.slerp(workOldComponentRotation, componentWorldRot, rotationLimitRatio); + } + + // その他の影響 + float otherShiftRatio = 0.0f; + + // 更新スキップによるシフト + // 更新スキップ時はスキップ時間分ワールド慣性シフトを行う + if (tdata.skipCount > 0) + { + otherShiftRatio = math.lerp(otherShiftRatio, 1.0f, math.saturate((tdata.skipCount * simulationDeltaTime) / (tdata.frameDeltaTime * tdata.nowTimeScale))); + } + + // 安定化時間中は慣性を抑える + if (tdata.velocityWeight < 1.0f) + { + otherShiftRatio = math.lerp(otherShiftRatio, 1.0f, 1.0f - tdata.velocityWeight); + } + + // タイムスケール + // タイムスケールの影響分ワールド慣性シフトを行う + if (tdata.nowTimeScale < 1.0f) + { + otherShiftRatio = math.lerp(otherShiftRatio, 1.0f, 1.0f - tdata.nowTimeScale); + } + + if (otherShiftRatio > 0.0f) + { + tdata.flag.SetBits(Flag_InertiaShift, true); + moveShiftRatio = math.lerp(moveShiftRatio, 1.0f, otherShiftRatio); + workOldComponentPosition = math.lerp(workOldComponentPosition, componentWorldPos, otherShiftRatio); + rotationShiftRatio = math.lerp(rotationShiftRatio, 1.0f, otherShiftRatio); + workOldComponentRotation = math.slerp(workOldComponentRotation, componentWorldRot, otherShiftRatio); + } + + // ■慣性シフト最終設定 + if (tdata.IsInertiaShift) + { + //Debug.Log($"moveShiftRatio:{moveShiftRatio}, rotationShiftRatio:{rotationShiftRatio}"); + + cdata.frameComponentShiftVector *= moveShiftRatio; + cdata.frameComponentShiftRotation = math.slerp(quaternion.identity, cdata.frameComponentShiftRotation, rotationShiftRatio); + + // アンカーによる打ち消し + cdata.frameComponentShiftVector += anchorDeltaVector; + cdata.frameComponentShiftRotation = math.mul(anchorDeltaRotation, cdata.frameComponentShiftRotation); + + // スムージング影響打ち消し + cdata.frameComponentShiftVector += smoothDeltaVector; + + cdata.oldFrameWorldPosition = MathUtility.ShiftPosition(cdata.oldFrameWorldPosition, cdata.oldComponentWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); + cdata.oldFrameWorldRotation = math.mul(cdata.frameComponentShiftRotation, cdata.oldFrameWorldRotation); + + cdata.nowWorldPosition = MathUtility.ShiftPosition(cdata.nowWorldPosition, cdata.oldComponentWorldPosition, cdata.frameComponentShiftVector, cdata.frameComponentShiftRotation); + cdata.nowWorldRotation = math.mul(cdata.frameComponentShiftRotation, cdata.nowWorldRotation); + } + } + //Debug.Log($"team:[{teamId}] frameComponentShiftVector:{cdata.frameComponentShiftVector}, frameComponentShiftRotation:{cdata.frameComponentShiftRotation}"); + //Debug.Log($"team:[{teamId}] centerTransformIndex:{centerTransformIndex}"); + //Debug.Log($"team:[{teamId}] worldInertia:{param.inertiaConstraint.worldInertia}"); + //Debug.Log($"team:[{teamId}] movementSpeedLimit:{param.inertiaConstraint.movementSpeedLimit}"); + //Debug.Log($"team:[{teamId}] rotationSpeedLimit:{param.inertiaConstraint.rotationSpeedLimit}"); + + // ■ワールド移動方向と速度割り出し(慣性シフト後の移動量で計算) + float3 movingVector = componentWorldPos - workOldComponentPosition; + float movingLength = math.length(movingVector); + cdata.frameMovingSpeed = tdata.frameDeltaTime > 0.0f ? movingLength / tdata.frameDeltaTime : 0.0f; + cdata.frameMovingSpeed *= tdata.nowTimeScale > 1e-06f ? 1.0f / tdata.nowTimeScale : 0.0f; // タイムスケール考慮 + cdata.frameMovingDirection = movingLength > 1e-06f ? movingVector / movingLength : 0; + + //Debug.Log($"frameWorldPosition:{cdata.frameWorldPosition}, framwWorldRotation:{cdata.frameWorldRotation.value}"); + //Debug.Log($"oldFrameWorldPosition:{cdata.oldFrameWorldPosition}, oldFrameWorldRotation:{cdata.oldFrameWorldRotation.value}"); + //Debug.Log($"nowWorldPosition:{cdata.nowWorldPosition}, nowWorldRotation:{cdata.nowWorldRotation.value}"); + //Debug.Log($"oldWorldPosition:{cdata.oldWorldPosition}, oldWorldRotation:{cdata.oldWorldRotation.value}"); + + // センターローカル座標 + float3 localCenterPos = MathUtility.InverseTransformPoint(centerWorldPos, wtol); + cdata.frameLocalPosition = localCenterPos; + + // 速度安定化処理 + if (tdata.flag.IsSet(Flag_Reset) || tdata.flag.IsSet(Flag_TimeReset)) + { + tdata.velocityWeight = param.stablizationTimeAfterReset > 1e-06f ? 0.0f : 1.0f; + tdata.blendWeight = tdata.velocityWeight; + } + + // 風の影響を計算 ======================================================== + //var oldTeamWindData = teamWindArray[teamId]; + var newTeamWindData = new TeamWindData(); + if (windZoneCount > 0 && param.wind.IsValid()) + { + float minVolume = float.MaxValue; + int addWindCount = 0; + int latestWindId = -1; + + for (int windId = 0; windId < windZoneCount; windId++) + { + var wdata = windDataArray[windId]; + if (wdata.IsValid() == false || wdata.IsEnable() == false) + continue; + + // チームが風エリアに入っているか判定する + // 加算風は最大3つまで + bool isAdditin = wdata.IsAddition(); + if (isAdditin && addWindCount >= 3) + continue; + + // 風ゾーンのローカル位置 + float3 lpos = math.transform(wdata.worldToLocalMatrix, centerWorldPos); + float llen = math.length(lpos); + + // エリア判定 + switch (wdata.mode) + { + case MagicaWindZone.Mode.BoxDirection: + var lv = math.abs(lpos) * 2; + if (lv.x > wdata.size.x || lv.y > wdata.size.y || lv.z > wdata.size.z) + continue; + break; + case MagicaWindZone.Mode.SphereDirection: + case MagicaWindZone.Mode.SphereRadial: + if (llen > wdata.size.x) + continue; + break; + } + + // エリア風の場合はボリューム判定(体積が小さいものが優先) + if (isAdditin == false && wdata.zoneVolume > minVolume) + continue; + + // 風の方向(world) + float3 mainDirection = wdata.worldWindDirection; + switch (wdata.mode) + { + case MagicaWindZone.Mode.SphereRadial: + if (llen <= 1e-06f) + continue; + var v = centerWorldPos - wdata.worldPositin; + mainDirection = math.normalize(v); + break; + } + //Debug.Log($"wdir:{mainDirection}"); + + // 風力 + float windMain = wdata.main; + switch (wdata.mode) + { + case MagicaWindZone.Mode.SphereRadial: + // 減衰 + if (llen <= 1e-06f) + continue; + float depth = math.saturate(llen / wdata.size.x); + float attenuation = wdata.attenuation.MC2EvaluateCurveClamp01(depth); + windMain *= attenuation; + break; + } + + // 計算する風として登録する + var windInfo = new TeamWindInfo() + { + windId = windId, + time = -Define.System.WindMaxTime, // マイナス値からスタート + main = windMain, + direction = mainDirection + }; + if (isAdditin) + { + newTeamWindData.AddOrReplaceWindZone(windInfo, windData); + addWindCount++; + } + else + { + newTeamWindData.RemoveWindZone(latestWindId); + newTeamWindData.AddOrReplaceWindZone(windInfo, windData); + minVolume = wdata.zoneVolume; + latestWindId = windId; + } + } + } + + // 移動風移植 + newTeamWindData.movingWind = windData.movingWind; + windData.CopyFrom(newTeamWindData); + } + + /// + /// ステップごとの前処理(ステップの開始に実行される) + /// + internal static void SimulationStepTeamUpdate( + int updateIndex, + float simulationDeltaTime, + // team + int teamId, + ref TeamData tdata, + ref ClothParameters param, + ref InertiaConstraint.CenterData cdata, + ref TeamWindData wdata + ) + { + // ■ステップ実行時のみ処理する + bool runStep = updateIndex < tdata.updateCount; + tdata.flag.SetBits(Flag_StepRunning, runStep); + + //Debug.Log($"team[{teamId}] ({updateIndex}/{tdata.updateCount})"); + + // ■時間更新 --------------------------------------------------- + // nowUpdateTime更新 + tdata.nowUpdateTime += simulationDeltaTime; + + // 今回のフレーム割合を計算する + // frameStartTimeからtime区間でのnowUpdateTimeの割合 + //tdata.frameInterpolation = (tdata.nowUpdateTime - tdata.frameOldTime) / (tdata.time - tdata.frameOldTime); + // 念の為、0除算チェックと0-1クランプを入れる + float b = tdata.time - tdata.frameOldTime; + tdata.frameInterpolation = b > 0 ? math.saturate((tdata.nowUpdateTime - tdata.frameOldTime) / b) : 1.0f; + + //Debug.Log($"Team[{teamId}] time.{tdata.time}, oldTime:{tdata.oldTime}, frameTime:{tdata.frameUpdateTime}, frameOldTime:{tdata.frameOldTime}, nowUpdateTime:{tdata.nowUpdateTime}, frameInterp:{tdata.frameInterpolation}"); + + // ■センター --------------------------------------------------- + // 現在ステップでのセンタートランスフォーム姿勢を求める + cdata.oldWorldPosition = cdata.nowWorldPosition; + cdata.oldWorldRotation = cdata.nowWorldRotation; + cdata.nowWorldPosition = math.lerp(cdata.oldFrameWorldPosition, cdata.frameWorldPosition, tdata.frameInterpolation); + cdata.nowWorldRotation = math.slerp(cdata.oldFrameWorldRotation, cdata.frameWorldRotation, tdata.frameInterpolation); + cdata.nowWorldRotation = math.normalize(cdata.nowWorldRotation); // 必要 + float3 wscl = math.lerp(cdata.oldFrameWorldScale, cdata.frameWorldScale, tdata.frameInterpolation); + //cdata.nowWorldScale = wscl; + + // ステップごとの移動量 + cdata.stepVector = cdata.nowWorldPosition - cdata.oldWorldPosition; + cdata.stepRotation = MathUtility.FromToRotation(cdata.oldWorldRotation, cdata.nowWorldRotation); + float stepAngle = MathUtility.Angle(cdata.oldWorldRotation, cdata.nowWorldRotation); + //Debug.Log($"Team[{teamId}] stepVector:{cdata.stepVector}, stepRotation:{cdata.stepRotation}, stepAngle:{stepAngle}"); + //Debug.Log($"Team[{teamId}] stepVector:{math.length(cdata.stepVector)}, frameInterpolation:{tdata.frameInterpolation}"); + + // ローカル慣性 + float localMovementInertia = 1.0f - param.inertiaConstraint.localInertia; + float localRotationInertia = 1.0f - param.inertiaConstraint.localInertia; +#if true + float3 localVector = cdata.stepVector * (1.0f - localMovementInertia); + float localMovementSpeed = math.length(localVector) / simulationDeltaTime; // ローカル移動速度(m/s) + if (localMovementSpeed > param.inertiaConstraint.localMovementSpeedLimit && param.inertiaConstraint.localMovementSpeedLimit >= 0.0f) + { + float t = param.inertiaConstraint.localMovementSpeedLimit / localMovementSpeed; + localMovementInertia = math.lerp(1.0f, localMovementInertia, t); + } + float localAngle = stepAngle * (1.0f - localRotationInertia); + float localAngleSpeed = math.degrees(localAngle / simulationDeltaTime); // ローカル回転速度(deg/s) + if (localAngleSpeed > param.inertiaConstraint.localRotationSpeedLimit && param.inertiaConstraint.localRotationSpeedLimit >= 0.0f) + { + float t = param.inertiaConstraint.localRotationSpeedLimit / localAngleSpeed; + localRotationInertia = math.lerp(1.0f, localRotationInertia, t); + } +#endif + cdata.stepMoveInertiaRatio = localMovementInertia; + cdata.stepRotationInertiaRatio = localRotationInertia; + + // 最終慣性 + cdata.inertiaVector = math.lerp(float3.zero, cdata.stepVector, localMovementInertia); + cdata.inertiaRotation = math.slerp(quaternion.identity, cdata.stepRotation, localRotationInertia); + //Debug.Log($"Team[{teamId}] localMovementInertia:{localMovementInertia}, localRotationInertia:{localRotationInertia}, inertiaVector:{cdata.inertiaVector}, inertiaRotation:{cdata.inertiaRotation}"); + + // ■遠心力用パラメータ算出 + // 今回ステップでの回転速度と回転軸 + cdata.angularVelocity = stepAngle / simulationDeltaTime; // 回転速度(rad/s) + if (cdata.angularVelocity > Define.System.Epsilon) + MathUtility.ToAngleAxis(cdata.stepRotation, out _, out cdata.rotationAxis); + else + cdata.rotationAxis = 0; + //Debug.Log($"Team[{teamId}] angularVelocity:{math.degrees(cdata.angularVelocity)}, axis:{cdata.rotationAxis}, q:{cdata.stepRotation.value}"); + //Debug.Log($"Team[{teamId}] angularVelocity:{math.degrees(cdata.angularVelocity)}, now:{cdata.nowWorldRotation.value}, old:{cdata.oldWorldRotation.value}"); + + // チームスケール倍率 + tdata.scaleRatio = math.max(math.length(wscl) / math.length(tdata.initScale), 1e-06f); + //Debug.Log($"[{teamId}] scaleRatio:{tdata.scaleRatio}"); + + // ■重力方向割合 --------------------------------------------------- + float gravityDot = 1.0f; + if (math.lengthsq(param.worldGravityDirection) > Define.System.Epsilon) + { + // マイナススケール + float3 initLocalGravityDirection = cdata.initLocalGravityDirection; + initLocalGravityDirection.y *= tdata.negativeScaleDirection.y; // Yマイナススケール時のみY軸を反転 + + var worldFalloffDir = math.mul(cdata.nowWorldRotation, initLocalGravityDirection); + gravityDot = math.dot(worldFalloffDir, param.worldGravityDirection); + gravityDot = math.saturate(gravityDot * 0.5f + 0.5f); + } + tdata.gravityDot = gravityDot; + //Develop.DebugLog($"gdot:{gravityDot}"); + + // ■重力減衰 --------------------------------------------------- + float gravityRatio = 1.0f; + if (param.gravity > 1e-06f && param.gravityFalloff > 1e-06f) + { + gravityRatio = math.lerp(math.saturate(1.0f - param.gravityFalloff), 1.0f, math.saturate(1.0f - gravityDot)); + } + tdata.gravityRatio = gravityRatio; + + // 速度安定化時間の速度割合を更新 + if (tdata.velocityWeight < 1.0f) + { + float addw = param.stablizationTimeAfterReset > 1e-06f ? simulationDeltaTime / param.stablizationTimeAfterReset : 1.0f; + tdata.velocityWeight = math.saturate(tdata.velocityWeight + addw); + } + //Debug.Log($"{tdata.velocityWeight}"); + + // シミュレーション結果のブレンド割合 + tdata.blendWeight = math.saturate(tdata.velocityWeight * param.blendWeight * tdata.distanceWeight); + //Debug.Log($"{tdata.blendWeight}"); + + // 風の時間更新 + UpdateWind(simulationDeltaTime, teamId, tdata, param.wind, cdata, ref wdata); + + //Debug.Log($"[{updateIndex}/{updateCount}] frameRatio:{data.frameInterpolation}, inertiaPosition:{idata.inertiaPosition}"); + } + + // 各風ゾーンの時間更新 + static void UpdateWind( + float simulationDeltaTime, + int teamId, + in TeamData tdata, + in WindParams windParams, + in InertiaConstraint.CenterData cdata, + ref TeamWindData teamWindData + ) + { + if (windParams.IsValid() == false) + return; + + // ゾーン風 + int cnt = teamWindData.ZoneCount; + for (int i = 0; i < cnt; i++) + { + var windInfo = teamWindData.windZoneList[i]; + UpdateWindTime(ref windInfo, windParams.frequency, simulationDeltaTime); + teamWindData.windZoneList[i] = windInfo; + } + + // 移動風 + var movingWindInfo = teamWindData.movingWind; + movingWindInfo.main = 0; + if (windParams.movingWind > 0.01f) + { + movingWindInfo.main = (cdata.frameMovingSpeed * windParams.movingWind) / tdata.scaleRatio; + movingWindInfo.direction = -cdata.frameMovingDirection; + UpdateWindTime(ref movingWindInfo, windParams.frequency, simulationDeltaTime); + } + teamWindData.movingWind = movingWindInfo; + } + + static void UpdateWindTime(ref TeamWindInfo windInfo, float frequency, float simulationDeltaTime) + { + // 風速係数 + float mainRatio = windInfo.main / Define.System.WindBaseSpeed; // 0.0 ~ + + // 基本周期 + float freq = 0.2f + mainRatio * 0.5f; + freq *= frequency; // 0.0 ~ 2.0f; + freq = math.min(freq, 1.5f); // max 1.5 + freq *= simulationDeltaTime; + + // 時間加算 + windInfo.time = windInfo.time + freq; + + // timeオーバーフロー対策 + if (windInfo.time > Define.System.WindMaxTime) // 約6時間 + windInfo.time -= Define.System.WindMaxTime * 2; // マイナス側から再スタート + } + + /// + /// クロスシミュレーション更新後処理 + /// + internal static void SimulationPostTeamUpdate( + // team + ref TeamData tdata, + ref InertiaConstraint.CenterData cdata + ) + { + // コンポーネント位置 + cdata.oldComponentWorldPosition = cdata.componentWorldPosition; + cdata.oldComponentWorldRotation = cdata.componentWorldRotation; + cdata.oldComponentWorldScale = cdata.componentWorldScale; + + if (tdata.IsRunning) + { + // センターを更新 + cdata.oldFrameWorldPosition = cdata.frameWorldPosition; + cdata.oldFrameWorldRotation = cdata.frameWorldRotation; + cdata.oldFrameWorldScale = cdata.frameWorldScale; + + // 外力クリア + tdata.forceMode = ClothForceMode.None; + tdata.impactForce = 0; + + // スキップ + tdata.skipCount = 0; + } + + // アンカー + cdata.oldAnchorPosition = cdata.anchorPosition; + cdata.oldAnchorRotation = cdata.anchorRotation; + cdata.anchorComponentLocalPosition = MathUtility.InverseTransformPoint(cdata.componentWorldPosition, cdata.anchorPosition, cdata.anchorRotation, 1); + + // フラグリセット + tdata.flag.SetBits(Flag_Reset, false); + tdata.flag.SetBits(Flag_TimeReset, false); + tdata.flag.SetBits(Flag_Running, false); + tdata.flag.SetBits(Flag_StepRunning, false); + tdata.flag.SetBits(Flag_KeepTeleport, false); + tdata.flag.SetBits(Flag_InertiaShift, false); + tdata.flag.SetBits(Flag_NegativeScaleTeleport, false); + + // 時間調整(floatの精度問題への対処) + const float limitTime = 3600.0f; // 60min + if (tdata.time > limitTime * 2) + { + tdata.time -= limitTime; + tdata.oldTime -= limitTime; + tdata.nowUpdateTime -= limitTime; + tdata.oldUpdateTime -= limitTime; + tdata.frameUpdateTime -= limitTime; + tdata.frameOldTime -= limitTime; + } + } + //========================================================================================= public void InformationLog(StringBuilder allsb) { @@ -2096,17 +2816,15 @@ namespace MagicaCloth2 continue; } - //sb.AppendLine($"ID:{i} [{cprocess.Name}] state:0x{cprocess.GetStateFlag().Value:X}, Flag:0x{tdata.flag.Value:X}, Particle:{tdata.ParticleCount}, Collider:{cprocess.ColliderCapacity} Proxy:{tdata.proxyMeshType}, Mapping:{tdata.MappingCount}"); - sb.AppendLine($"ID:{i} [{cprocess.Name}] state:0x{cprocess.GetStateFlag().Value:X}, Flag:0x{tdata.flag.Value:X}, Particle:{tdata.ParticleCount}, Collider:{cprocess.ColliderCapacity} Proxy:{tdata.proxyMeshType}, Mapping:{mappingList.Length}"); + sb.AppendLine($"ID:{i} [{cprocess.Name}] state:0x{cprocess.GetStateFlag().Value:X}, Flag:0x{tdata.flag.Value:X}, Particle:{tdata.ParticleCount}, Collider:{cprocess.colliderDict.Count} Proxy:{tdata.proxyMeshType}, Mapping:{mappingList.Length}"); sb.AppendLine($" -centerTransformIndex {tdata.centerTransformIndex}"); - sb.AppendLine($" -centerWorldPosition {tdata.centerWorldPosition}"); sb.AppendLine($" -initScale {tdata.initScale}"); sb.AppendLine($" -scaleRatio {tdata.scaleRatio}"); sb.AppendLine($" -animationPoseRatio {tdata.animationPoseRatio}"); sb.AppendLine($" -blendWeight {tdata.blendWeight}"); // 同期 - sb.AppendLine($" Sync:{cloth.SyncCloth}, SyncParentCount:{tdata.syncParentTeamId.Length}"); + sb.AppendLine($" Sync:{cloth.SyncPartnerCloth}, SyncParentCount:{tdata.syncParentTeamId.Length}"); // chunk情報 sb.AppendLine($" -ProxyTransformChunk {tdata.proxyTransformChunk}"); @@ -2124,16 +2842,11 @@ namespace MagicaCloth2 sb.AppendLine($" -colliderCount {tdata.colliderCount}"); // mapping情報 - //var teamMapping = teamMappingIndexArray[i]; - //sb.AppendLine($" *Mapping Count {tdata.MappingCount}"); sb.AppendLine($" *Mapping Count {mappingList.Length}"); - //if (tdata.MappingCount > 0) if (mappingList.Length > 0) { - //for (int j = 0; j < tdata.MappingCount; j++) for (int j = 0; j < mappingList.Length; j++) { - //int mid = tdata.mappingDataIndexSet[j]; int mid = mappingList[j]; var mdata = mappingDataArray[mid]; sb.AppendLine($" *Mapping Mid:{mid}, Vertex:{mdata.VertexCount}"); @@ -2145,6 +2858,7 @@ namespace MagicaCloth2 sb.AppendLine($" -sameSpace:{mdata.sameSpace}"); sb.AppendLine($" -toMappingMatrix:{mdata.toMappingMatrix}"); sb.AppendLine($" -scaleRatio:{mdata.scaleRatio}"); + sb.AppendLine($" -renderDataWorkIndex:{mdata.renderDataWorkIndex}"); } } @@ -2170,6 +2884,21 @@ namespace MagicaCloth2 allsb.Append(sb); } allsb.AppendLine(); + + // MappingData + sb.Clear(); + int mappingCount = mappingDataArray.Count; + sb.AppendLine($"#MappingData Count:{mappingCount}"); + for (int i = 0; i < mappingCount; i++) + { + var mdata = mappingDataArray[i]; + if (mdata.IsValid() == false) + continue; + + sb.AppendLine($"[{i}] teamId:{mdata.teamId}, renderDataWorkIndex:{mdata.renderDataWorkIndex}"); + } + Debug.Log(sb.ToString()); + allsb.Append(sb); } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamManager.cs.meta index adc08cd3..d15aa013 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamManager.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamManager.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamWindData.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamWindData.cs index 8397dd50..48697c0f 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamWindData.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamWindData.cs @@ -86,6 +86,12 @@ namespace MagicaCloth2 } } + public void CopyFrom(in TeamWindData wdata) + { + windZoneList = wdata.windZoneList; + movingWind = wdata.movingWind; + } + //public void DebugLog(int teamId) //{ // Debug.Log($"TeamWindData:{teamId}, zoneCnt:{ZoneCount}"); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamWindData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamWindData.cs.meta index 77695a70..14a18956 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamWindData.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamWindData.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/Team/TeamWindData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformData.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformData.cs index 4d3fc52a..882419e4 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformData.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformData.cs @@ -3,6 +3,7 @@ // https://magicasoft.jp using System; using System.Collections.Generic; +using System.Text; using Unity.Burst; using Unity.Collections; using Unity.Jobs; @@ -16,7 +17,7 @@ namespace MagicaCloth2 /// TransformAccessArrayを中心とした一連のTransform管理クラス /// スレッドで利用できるように様々な工夫を行っている /// - public class TransformData : IDisposable + public partial class TransformData : IDisposable { internal List transformList; @@ -101,10 +102,7 @@ namespace MagicaCloth2 Queue emptyStack; //========================================================================================= - public TransformData() - { - Init(100); - } + public TransformData() { } public TransformData(int capacity) { @@ -133,7 +131,7 @@ namespace MagicaCloth2 public void Dispose() { - transformList.Clear(); + transformList?.Clear(); idArray?.Dispose(); parentIdArray?.Dispose(); flagArray?.Dispose(); @@ -145,15 +143,11 @@ namespace MagicaCloth2 localPositionArray?.Dispose(); localRotationArray?.Dispose(); inverseRotationArray?.Dispose(); - emptyStack.Clear(); + emptyStack?.Clear(); // transformAccessArrayはメインスレッドのみ if (transformAccessArray.isCreated) { - //if (MagicaManager.Discard != null) - // MagicaManager.Discard.AddMain(transformAccessArray); - //else - // transformAccessArray.Dispose(); transformAccessArray.Dispose(); } } @@ -161,6 +155,7 @@ namespace MagicaCloth2 public int Count => transformList.Count; public int RootCount => rootIdList?.Count ?? 0; public bool IsDirty => isDirty; + public bool IsEmpty => transformList == null; //========================================================================================= /// @@ -951,5 +946,19 @@ namespace MagicaCloth2 { return math.inverse(GetLocalToWorldMatrix(index)); } + + //========================================================================================= + public override string ToString() + { + int transformListCount = transformList?.Count ?? 0; + + StringBuilder sb = new StringBuilder(); + sb.AppendLine("==== TransformData ===="); + sb.AppendLine($"isDirty:{isDirty}"); + sb.AppendLine($"transformList:{transformListCount}"); + sb.AppendLine($"flagArray:{flagArray.Length}"); + + return sb.ToString(); + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformData.cs.meta index 0fa8e2e3..3c0bf5a7 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformData.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformData.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs new file mode 100644 index 00000000..79d9f301 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs @@ -0,0 +1,117 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using System.Collections.Generic; +using Unity.Mathematics; +using UnityEngine; + +namespace MagicaCloth2 +{ + public partial class TransformData + { + /// + /// PreBuildの共有部分保存データ + /// + [System.Serializable] + public class ShareSerializationData + { + public ExSimpleNativeArray.SerializationData flagArray; + public ExSimpleNativeArray.SerializationData initLocalPositionArray; + public ExSimpleNativeArray.SerializationData initLocalRotationArray; + } + + public ShareSerializationData ShareSerialize() + { + var sdata = new ShareSerializationData(); + try + { + sdata.flagArray = flagArray.Serialize(); + sdata.initLocalPositionArray = initLocalPositionArray.Serialize(); + sdata.initLocalRotationArray = initLocalRotationArray.Serialize(); + } + catch (Exception exception) + { + Debug.LogException(exception); + } + + return sdata; + } + + public static TransformData ShareDeserialize(ShareSerializationData sdata) + { + if (sdata == null) + return null; + + var tdata = new TransformData(); + try + { + tdata.flagArray = new ExSimpleNativeArray(sdata.flagArray); + tdata.initLocalPositionArray = new ExSimpleNativeArray(sdata.initLocalPositionArray); + tdata.initLocalRotationArray = new ExSimpleNativeArray(sdata.initLocalRotationArray); + } + catch (Exception exception) + { + Debug.LogException(exception); + } + + return tdata; + } + + //========================================================================================= + /// + /// PreBuild固有部分の保存データ + /// + [System.Serializable] + public class UniqueSerializationData : ITransform + { + public Transform[] transformArray; + + public void GetUsedTransform(HashSet transformSet) + { + if (transformArray != null) + { + foreach (var t in transformArray) + { + if (t) + transformSet.Add(t); + } + } + } + + public void ReplaceTransform(Dictionary replaceDict) + { + if (transformArray != null) + { + for (int i = 0; i < transformArray.Length; i++) + { + var t = transformArray[i]; + if (t) + { + int id = t.GetInstanceID(); + if (id != 0 && replaceDict.ContainsKey(id)) + { + transformArray[i] = replaceDict[id]; + } + } + } + } + } + } + + public UniqueSerializationData UniqueSerialize() + { + var sdata = new UniqueSerializationData(); + try + { + sdata.transformArray = transformList.ToArray(); + } + catch (Exception exception) + { + Debug.LogException(exception); + } + + return sdata; + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs.meta new file mode 100644 index 00000000..4f30eb9d --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 7ae8000d77bdbae4b86315fcc83b2518 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformDataSerialization.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformManager.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformManager.cs index 3f503055..a28aeb47 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformManager.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformManager.cs @@ -31,6 +31,16 @@ namespace MagicaCloth2 /// internal ExNativeArray initLocalRotationArray; + /// + /// シミュレーションの基準となるlocalPosition + /// + internal ExNativeArray baseLocalPositionArray; + + /// + /// シミュレーションの基準となるlocalRotation + /// + internal ExNativeArray baseLocalRotationArray; + /// /// ワールド座標 /// @@ -44,7 +54,7 @@ namespace MagicaCloth2 /// /// ワールド逆回転 /// - internal ExNativeArray inverseRotationArray; + //internal ExNativeArray inverseRotationArray; /// /// ワールドスケール @@ -62,6 +72,16 @@ namespace MagicaCloth2 /// internal ExNativeArray localRotationArray; + /// + /// ローカルスケール + /// + internal ExNativeArray localScaleArray; + + /// + /// ワールド変換マトリックス + /// + internal ExNativeArray localToWorldMatrixArray; + /// /// 接続チームID(0=なし) /// @@ -78,15 +98,17 @@ namespace MagicaCloth2 //========================================================================================= /// - /// 書き込み用トランスフォームのデータ参照インデックス - /// つまり上記配列へのインデックス + /// コンポーネント用ワールド姿勢 /// - //internal ExNativeArray writeIndexArray; + internal ExNativeArray componentPositionArray; + internal ExNativeArray componentMinScaleArray; // このスケール値はXYZの最小の絶対値(用途は0スケール判定) /// - /// 書き込み用トランスフォームアクセス配列 + /// コンポーネント用トランスフォーム /// - //internal TransformAccessArray writeTransformAccessArray; + internal TransformAccessArray componentTransformAccessArray; + + internal NativeReference existFixedTeam; bool isValid; @@ -98,24 +120,32 @@ namespace MagicaCloth2 flagArray?.Dispose(); initLocalPositionArray?.Dispose(); initLocalRotationArray?.Dispose(); + baseLocalPositionArray?.Dispose(); + baseLocalRotationArray?.Dispose(); positionArray?.Dispose(); rotationArray?.Dispose(); - inverseRotationArray?.Dispose(); + //inverseRotationArray?.Dispose(); scaleArray?.Dispose(); localPositionArray?.Dispose(); localRotationArray?.Dispose(); + localScaleArray?.Dispose(); + localToWorldMatrixArray?.Dispose(); teamIdArray?.Dispose(); //writeIndexArray?.Dispose(); flagArray = null; initLocalPositionArray = null; initLocalRotationArray = null; + baseLocalPositionArray = null; + baseLocalRotationArray = null; positionArray = null; rotationArray = null; - inverseRotationArray = null; + //inverseRotationArray = null; scaleArray = null; localPositionArray = null; localRotationArray = null; + localScaleArray = null; + localToWorldMatrixArray = null; teamIdArray = null; //writeIndexArray = null; @@ -123,6 +153,14 @@ namespace MagicaCloth2 transformAccessArray.Dispose(); //if (writeTransformAccessArray.isCreated) // writeTransformAccessArray.Dispose(); + + componentPositionArray?.Dispose(); + componentMinScaleArray?.Dispose(); + if (componentTransformAccessArray.isCreated) + componentTransformAccessArray.Dispose(); + + if (existFixedTeam.IsCreated) + existFixedTeam.Dispose(); } public void EnterdEditMode() @@ -138,16 +176,26 @@ namespace MagicaCloth2 flagArray = new ExNativeArray(capacity); initLocalPositionArray = new ExNativeArray(capacity); initLocalRotationArray = new ExNativeArray(capacity); + baseLocalPositionArray = new ExNativeArray(capacity); + baseLocalRotationArray = new ExNativeArray(capacity); positionArray = new ExNativeArray(capacity); rotationArray = new ExNativeArray(capacity); - inverseRotationArray = new ExNativeArray(capacity); + //inverseRotationArray = new ExNativeArray(capacity); scaleArray = new ExNativeArray(capacity); localPositionArray = new ExNativeArray(capacity); localRotationArray = new ExNativeArray(capacity); + localScaleArray = new ExNativeArray(capacity); + localToWorldMatrixArray = new ExNativeArray(capacity); teamIdArray = new ExNativeArray(capacity); transformAccessArray = new TransformAccessArray(capacity); + componentPositionArray = new ExNativeArray(capacity); + componentMinScaleArray = new ExNativeArray(capacity); + componentTransformAccessArray = new TransformAccessArray(capacity); + + existFixedTeam = new NativeReference(Allocator.Persistent); + isValid = true; } @@ -158,30 +206,34 @@ namespace MagicaCloth2 //========================================================================================= /// - /// TransformDataを追加する + /// VirtualMeshのTransformDataを追加する /// /// /// - internal DataChunk AddTransform(TransformData tdata, int teamId) + internal DataChunk AddTransform(VirtualMeshContainer cmesh, int teamId) { if (isValid == false) return default; - Debug.Assert(tdata != null); - int cnt = tdata.Count; + Debug.Assert(cmesh != null); + int cnt = cmesh.GetTransformCount(); // データコピー追加 - var c = flagArray.AddRange(tdata.flagArray); - initLocalPositionArray.AddRange(tdata.initLocalPositionArray); - initLocalRotationArray.AddRange(tdata.initLocalRotationArray); + var c = flagArray.AddRange(cmesh.shareVirtualMesh.transformData.flagArray); + initLocalPositionArray.AddRange(cmesh.shareVirtualMesh.transformData.initLocalPositionArray); + initLocalRotationArray.AddRange(cmesh.shareVirtualMesh.transformData.initLocalRotationArray); + baseLocalPositionArray.AddRange(cmesh.shareVirtualMesh.transformData.initLocalPositionArray); + baseLocalRotationArray.AddRange(cmesh.shareVirtualMesh.transformData.initLocalRotationArray); // 領域のみ追加 positionArray.AddRange(cnt); rotationArray.AddRange(cnt); - inverseRotationArray.AddRange(cnt); + //inverseRotationArray.AddRange(cnt); scaleArray.AddRange(cnt); localPositionArray.AddRange(cnt); localRotationArray.AddRange(cnt); + localScaleArray.AddRange(cnt); + localToWorldMatrixArray.AddRange(cnt); // チームID teamIdArray.AddRange(cnt, (short)teamId); @@ -190,16 +242,19 @@ namespace MagicaCloth2 int nowcnt = transformAccessArray.length; // データチャンクの開始まで埋める + var meshT = cmesh.GetCenterTransform(); int start = c.startIndex; while (nowcnt < start) { - transformAccessArray.Add(null); + transformAccessArray.Add(meshT); nowcnt++; } for (int i = 0; i < cnt; i++) { - var t = tdata.transformList[i]; + Transform t = cmesh.GetTransformFromIndex(i); + if (t == null) + t = meshT; int index = c.startIndex + i; if (index < nowcnt) transformAccessArray[index] = t; @@ -215,7 +270,7 @@ namespace MagicaCloth2 /// /// /// - internal DataChunk AddTransform(int count, int teamId) + internal DataChunk AddTransform(int count, int teamId, Transform t) { if (isValid == false) return default; @@ -224,30 +279,34 @@ namespace MagicaCloth2 var c = flagArray.AddRange(count); initLocalPositionArray.AddRange(count); initLocalRotationArray.AddRange(count); + baseLocalPositionArray.AddRange(count); + baseLocalRotationArray.AddRange(count); positionArray.AddRange(count); rotationArray.AddRange(count); - inverseRotationArray.AddRange(count); + //inverseRotationArray.AddRange(count); scaleArray.AddRange(count); localPositionArray.AddRange(count); localRotationArray.AddRange(count); + localScaleArray.AddRange(count); + localToWorldMatrixArray.AddRange(count); // チームID teamIdArray.AddRange(count, (short)teamId); - // トランスフォームはすべてnullで登録する + // トランスフォームはすべてnullで登録する(Unity6.1でnull登録はNGになった!) int nowcnt = transformAccessArray.length; // データチャンクの開始まで埋める int start = c.startIndex; while (nowcnt < start) { - transformAccessArray.Add(null); + transformAccessArray.Add(t); nowcnt++; } for (int i = 0; i < count; i++) { - Transform t = null; + //Transform t = null; int index = c.startIndex + i; if (index < nowcnt) transformAccessArray[index] = t; @@ -273,12 +332,16 @@ namespace MagicaCloth2 var c = flagArray.Add(flag); initLocalPositionArray.Add(t.localPosition); initLocalRotationArray.Add(t.localRotation); + baseLocalPositionArray.Add(t.localPosition); + baseLocalRotationArray.Add(t.localRotation); positionArray.Add(t.position); rotationArray.Add(t.rotation); - inverseRotationArray.Add(math.inverse(t.rotation)); + //inverseRotationArray.Add(math.inverse(t.rotation)); scaleArray.Add(t.lossyScale); localPositionArray.Add(t.localPosition); localRotationArray.Add(t.localRotation); + localScaleArray.Add(t.localScale); + localToWorldMatrixArray.Add(float4x4.identity); // ここは単位行列 // チームID teamIdArray.Add((short)teamId); @@ -311,12 +374,16 @@ namespace MagicaCloth2 flagArray[index] = flag; initLocalPositionArray[index] = t.localPosition; initLocalRotationArray[index] = t.localRotation; + baseLocalPositionArray[index] = t.localPosition; + baseLocalRotationArray[index] = t.localRotation; positionArray[index] = t.position; rotationArray[index] = t.rotation; - inverseRotationArray[index] = math.inverse(t.rotation); + //inverseRotationArray[index] = math.inverse(t.rotation); scaleArray[index] = t.lossyScale; localPositionArray[index] = t.localPosition; localRotationArray[index] = t.localRotation; + localScaleArray[index] = t.localScale; + //localToWorldMatrix[index] = t.localToWorldMatrix; // ここは不要 teamIdArray[index] = (short)teamId; transformAccessArray[index] = t; } @@ -342,12 +409,16 @@ namespace MagicaCloth2 flagArray[toIndex] = flagArray[fromIndex]; initLocalPositionArray[toIndex] = initLocalPositionArray[fromIndex]; initLocalRotationArray[toIndex] = initLocalRotationArray[fromIndex]; + baseLocalPositionArray[toIndex] = baseLocalPositionArray[fromIndex]; + baseLocalRotationArray[toIndex] = baseLocalRotationArray[fromIndex]; positionArray[toIndex] = positionArray[fromIndex]; rotationArray[toIndex] = rotationArray[fromIndex]; - inverseRotationArray[toIndex] = inverseRotationArray[fromIndex]; + //inverseRotationArray[toIndex] = inverseRotationArray[fromIndex]; scaleArray[toIndex] = scaleArray[fromIndex]; localPositionArray[toIndex] = localPositionArray[fromIndex]; localRotationArray[toIndex] = localRotationArray[fromIndex]; + localScaleArray[toIndex] = localScaleArray[fromIndex]; + //localToWorldMatrix[toIndex] = localToWorldMatrix[fromIndex]; // ここは不要 transformAccessArray[toIndex] = transformAccessArray[fromIndex]; teamIdArray[toIndex] = teamIdArray[fromIndex]; } @@ -366,12 +437,16 @@ namespace MagicaCloth2 flagArray.RemoveAndFill(c); initLocalPositionArray.Remove(c); initLocalRotationArray.Remove(c); + baseLocalPositionArray.Remove(c); + baseLocalRotationArray.Remove(c); positionArray.Remove(c); rotationArray.Remove(c); - inverseRotationArray.Remove(c); + //inverseRotationArray.Remove(c); scaleArray.Remove(c); localPositionArray.Remove(c); localRotationArray.Remove(c); + localScaleArray.Remove(c); + localToWorldMatrixArray.Remove(c); teamIdArray.RemoveAndFill(c, 0); // トランスフォーム削除 @@ -454,12 +529,16 @@ namespace MagicaCloth2 var nc = flagArray.Expand(c, newLength); initLocalPositionArray.Expand(c, newLength); initLocalRotationArray.Expand(c, newLength); + baseLocalPositionArray.Expand(c, newLength); + baseLocalRotationArray.Expand(c, newLength); positionArray.Expand(c, newLength); rotationArray.Expand(c, newLength); - inverseRotationArray.Expand(c, newLength); + //inverseRotationArray.Expand(c, newLength); scaleArray.Expand(c, newLength); localPositionArray.Expand(c, newLength); localRotationArray.Expand(c, newLength); + localScaleArray.Expand(c, newLength); + localToWorldMatrixArray.Expand(c, newLength); // チームID teamIdArray.Expand(c, newLength); @@ -467,8 +546,11 @@ namespace MagicaCloth2 // トランスフォームアクセス配列の拡張 if (c.startIndex != nc.startIndex) { + // 旧領域の先頭Transform + Transform frontT = transformAccessArray[c.startIndex]; + while (transformAccessArray.length < (nc.startIndex + nc.dataLength)) - transformAccessArray.Add(null); + transformAccessArray.Add(frontT); for (int i = 0; i < c.dataLength; i++) { @@ -490,11 +572,14 @@ namespace MagicaCloth2 /// public JobHandle RestoreTransform(JobHandle jobHandle) { + existFixedTeam.Value = false; if (Count > 0) { //Debug.Log("RestoreTransform"); var job = new RestoreTransformJob() { + existFixedTeam = existFixedTeam, + flagList = flagArray.GetNativeArray(), localPositionArray = initLocalPositionArray.GetNativeArray(), localRotationArray = initLocalRotationArray.GetNativeArray(), @@ -511,6 +596,9 @@ namespace MagicaCloth2 [BurstCompile] struct RestoreTransformJob : IJobParallelForTransform { + [NativeDisableParallelForRestriction] + public NativeReference existFixedTeam; + [Unity.Collections.ReadOnly] public NativeArray flagList; @@ -531,19 +619,102 @@ namespace MagicaCloth2 if (transform.isValid == false) return; var flag = flagList[index]; - if (flag.IsSet(Flag_Enable) == false) - return; if (flag.IsSet(Flag_Restore) == false) return; - // Keepカリング時はスキップする int teamId = teamIdArray[index]; var tdata = teamDataArray[teamId]; - if (tdata.IsCullingInvisible && tdata.IsCullingKeep) + + // 一度のみ復元フラグが立っている場合は実行する + if (flag.IsSet(Flag_Enable) == false && tdata.flag.IsSet(TeamManager.Flag_RestoreTransformOnlyOnec) == false) + return; + + // Keepカリング時はスキップする + if ((tdata.IsCameraCullingInvisible && tdata.IsCameraCullingKeep) || tdata.IsDistanceCullingInvisible) return; transform.localPosition = localPositionArray[index]; transform.localRotation = localRotationArray[index]; + + // 物理更新チームの存在 + if (tdata.IsFixedUpdate) + existFixedTeam.Value = true; + + //Debug.Log($"RestoreTransform [{index}] lpos:{localPositionArray[index]}, lrot:{localRotationArray[index]}"); + } + } + + //========================================================================================= + /// + /// UnityPhysicsチームかつFixedUpdateが実行されなかったフレームは退避させておいたベース姿勢で再度復元させる + /// + /// + /// + /// + public JobHandle RestoreBaseTransform(JobHandle jobHandle) + { + if (Count > 0) + { + //Debug.Log("RestoreTransform"); + var job = new RestoreBaseTransformJob() + { + flagList = flagArray.GetNativeArray(), + baseLocalPositionArray = baseLocalPositionArray.GetNativeArray(), + baseLocalRotationArray = baseLocalRotationArray.GetNativeArray(), + teamIdArray = teamIdArray.GetNativeArray(), + + teamDataArray = MagicaManager.Team.teamDataArray.GetNativeArray(), + }; + jobHandle = job.Schedule(transformAccessArray, jobHandle); + } + + return jobHandle; + } + + [BurstCompile] + struct RestoreBaseTransformJob : IJobParallelForTransform + { + [Unity.Collections.ReadOnly] + public NativeArray flagList; + [Unity.Collections.ReadOnly] + public NativeArray baseLocalPositionArray; + [Unity.Collections.ReadOnly] + public NativeArray baseLocalRotationArray; + [Unity.Collections.ReadOnly] + public NativeArray teamIdArray; + + // team + [Unity.Collections.ReadOnly] + public NativeArray teamDataArray; + + + public void Execute(int index, TransformAccess transform) + { + if (transform.isValid == false) + return; + var flag = flagList[index]; + if (flag.IsSet(Flag_Restore) == false) + return; + + int teamId = teamIdArray[index]; + var tdata = teamDataArray[teamId]; + + // Fixed更新チームのみ + if (tdata.IsFixedUpdate == false) + return; + + // 一度のみ復元フラグが立っている場合は実行する + if (flag.IsSet(Flag_Enable) == false && tdata.flag.IsSet(TeamManager.Flag_RestoreTransformOnlyOnec) == false) + return; + + // Keepカリング時はスキップする + if ((tdata.IsCameraCullingInvisible && tdata.IsCameraCullingKeep) || tdata.IsDistanceCullingInvisible) + return; + + transform.localPosition = baseLocalPositionArray[index]; + transform.localRotation = baseLocalRotationArray[index]; + + //Debug.Log($"RestoreTransform [{index}] lpos:{baseLocalPositionArray[index]}, lrot:{baseLocalRotationArray[index].value}"); } } @@ -553,21 +724,25 @@ namespace MagicaCloth2 /// /// /// - public JobHandle ReadTransform(JobHandle jobHandle) + public JobHandle ReadTransformSchedule(JobHandle jobHandle) { if (Count > 0) { - // todo:未来予測などがあると色々複雑化するところ - var job = new ReadTransformJob() { + fixedUpdateCount = MagicaManager.Time.FixedUpdateCount, + flagList = flagArray.GetNativeArray(), positionArray = positionArray.GetNativeArray(), rotationArray = rotationArray.GetNativeArray(), scaleList = scaleArray.GetNativeArray(), localPositionArray = localPositionArray.GetNativeArray(), localRotationArray = localRotationArray.GetNativeArray(), - inverseRotationArray = inverseRotationArray.GetNativeArray(), + localScaleArray = localScaleArray.GetNativeArray(), + //inverseRotationArray = inverseRotationArray.GetNativeArray(), + localToWorldMatrixArray = localToWorldMatrixArray.GetNativeArray(), + baseLocalPositionArray = baseLocalPositionArray.GetNativeArray(), + baseLocalRotationArray = baseLocalRotationArray.GetNativeArray(), teamIdArray = teamIdArray.GetNativeArray(), @@ -582,6 +757,8 @@ namespace MagicaCloth2 [BurstCompile] struct ReadTransformJob : IJobParallelForTransform { + public int fixedUpdateCount; + [Unity.Collections.ReadOnly] public NativeArray flagList; @@ -596,7 +773,15 @@ namespace MagicaCloth2 [Unity.Collections.WriteOnly] public NativeArray localRotationArray; [Unity.Collections.WriteOnly] - public NativeArray inverseRotationArray; + public NativeArray localScaleArray; + //[Unity.Collections.WriteOnly] + //public NativeArray inverseRotationArray; + [Unity.Collections.WriteOnly] + public NativeArray localToWorldMatrixArray; + [Unity.Collections.WriteOnly] + public NativeArray baseLocalPositionArray; + [Unity.Collections.WriteOnly] + public NativeArray baseLocalRotationArray; [Unity.Collections.ReadOnly] public NativeArray teamIdArray; @@ -615,7 +800,7 @@ namespace MagicaCloth2 if (flag.IsSet(Flag_Read) == false) return; - // カリング時は書き込まない + // カリング時は読み込まない int teamId = teamIdArray[index]; var tdata = teamDataArray[teamId]; if (tdata.IsCullingInvisible) @@ -629,6 +814,7 @@ namespace MagicaCloth2 rotationArray[index] = rot; localPositionArray[index] = transform.localPosition; localRotationArray[index] = transform.localRotation; + localScaleArray[index] = transform.localScale; // マトリックスから正確なスケール値を算出する(これはTransform.lossyScaleと等価) var irot = math.inverse(rot); @@ -636,8 +822,24 @@ namespace MagicaCloth2 var scl = new float3(m2.c0.x, m2.c1.y, m2.c2.z); scaleList[index] = scl; + //Debug.Log($"ReadTransform [{index}] pos:{pos}, rot:{rot}, scl:{scl}"); + //Debug.Log($"LtoW:\n{LtoW}"); + // ワールド->ローカル変換用の逆クォータニオン - inverseRotationArray[index] = math.inverse(rot); + //inverseRotationArray[index] = math.inverse(rot); + + // ワールド変換マトリックス + localToWorldMatrixArray[index] = LtoW; + + // 今回の姿勢を基本姿勢として退避させる + // Fixed更新チームかつFixedUpdateが実行されている場合、そもそもFixed更新出ない場合は毎回 + if ((tdata.IsFixedUpdate && fixedUpdateCount > 0) || tdata.IsFixedUpdate == false) + { + baseLocalPositionArray[index] = transform.localPosition; + baseLocalRotationArray[index] = transform.localRotation; + } + + //Debug.Log($"ReadTransform [{index}] pos:{pos}, rot:{rot}"); } } @@ -648,7 +850,7 @@ namespace MagicaCloth2 /// /// /// - public JobHandle WriteTransform(JobHandle jobHandle) + public JobHandle WriteTransformSchedule(JobHandle jobHandle) { var job = new WriteTransformJob() { @@ -697,12 +899,17 @@ namespace MagicaCloth2 if (flag.IsSet(Flag_Enable) == false) return; - // カリング時は書き込まない int teamId = teamIdArray[index]; var tdata = teamDataArray[teamId]; + + // カリング時は書き込まない if (tdata.IsCullingInvisible) return; + // 極小スケール時は書き込まない + if (tdata.IsScaleSuspend) + return; + // 書き込み停止中ならスキップ if (tdata.flag.IsSet(TeamManager.Flag_SkipWriting)) return; @@ -711,20 +918,115 @@ namespace MagicaCloth2 { // ワールド回転 transform.rotation = worldRotations[index]; + //Debug.Log($"WriteTransform [{index}] (World!) rot:{worldRotations[index]}"); // BoneSpringのみワールド座標を書き込む if (tdata.IsSpring) + { transform.position = worldPositions[index]; + } } else if (flag.IsSet(Flag_LocalPosRotWrite)) { // ローカル座標・回転を書き込む transform.localPosition = localPositions[index]; transform.localRotation = localRotations[index]; + + //Debug.Log($"WriteTransform [{index}] (local!) lpos:{localPositions[index]}, lrot:{localRotations[index]}"); } } } + //========================================================================================= + /// + /// コンポーネント用トランスフォームの登録 + /// + /// + /// + internal int AddComponentTransform(Transform t) + { + if (isValid == false) + return -1; + Debug.Assert(t); + + int index = componentPositionArray.Add(float3.zero).startIndex; + componentMinScaleArray.Add(1); + + // トランスフォーム + int nowcnt = componentTransformAccessArray.length; + if (index < nowcnt) + componentTransformAccessArray[index] = t; + else + componentTransformAccessArray.Add(t); + + return index; + } + + /// + /// コンポーネント用トランスフォームの削除 + /// + /// + internal void RemoveComponentTransform(int index) + { + if (isValid == false) + return; + if (index < 0) + return; + + componentPositionArray.Remove(index); + componentMinScaleArray.Remove(index); + + // トランスフォーム削除 + componentTransformAccessArray[index] = null; + } + + /// + /// トランスフォームを読み込むジョブを発行する + /// + /// + /// + internal JobHandle ReadComponentTransform(JobHandle jobHandle) + { + if (componentPositionArray.Count > 0) + { + var job = new ReadComponentTransformJob() + { + positionArray = componentPositionArray.GetNativeArray(), + minScaleArray = componentMinScaleArray.GetNativeArray(), + }; + jobHandle = job.ScheduleReadOnly(componentTransformAccessArray, 16, jobHandle); + } + + return jobHandle; + } + + [BurstCompile] + struct ReadComponentTransformJob : IJobParallelForTransform + { + [Unity.Collections.WriteOnly] + public NativeArray positionArray; + [Unity.Collections.WriteOnly] + public NativeArray minScaleArray; + + public void Execute(int index, TransformAccess transform) + { + if (transform.isValid == false) + return; + + positionArray[index] = transform.position; + + // スケールXYZの最小の絶対値 + // コンポーネントの0スケール判定に使用 + float3 scl = transform.localToWorldMatrix.lossyScale; + float minScale = math.cmin(math.abs(scl)); + minScaleArray[index] = minScale; + + //Debug.Log(scl); + //Debug.Log(minScale); + } + } + + //========================================================================================= public void InformationLog(StringBuilder allsb) { @@ -736,17 +1038,22 @@ namespace MagicaCloth2 } else { + // transform int tcnt = transformAccessArray.isCreated ? transformAccessArray.length : 0; sb.AppendLine($"Transform Manager. Length:{tcnt}"); sb.AppendLine($" -flagArray:{flagArray.ToSummary()}"); sb.AppendLine($" -initLocalPositionArray:{initLocalPositionArray.ToSummary()}"); sb.AppendLine($" -initLocalRotationArray:{initLocalRotationArray.ToSummary()}"); + sb.AppendLine($" -baseLocalPositionArray:{baseLocalPositionArray.ToSummary()}"); + sb.AppendLine($" -baseLocalRotationArray:{baseLocalRotationArray.ToSummary()}"); sb.AppendLine($" -positionArray:{positionArray.ToSummary()}"); sb.AppendLine($" -rotationArray:{rotationArray.ToSummary()}"); - sb.AppendLine($" -inverseRotationArray:{inverseRotationArray.ToSummary()}"); + //sb.AppendLine($" -inverseRotationArray:{inverseRotationArray.ToSummary()}"); sb.AppendLine($" -scaleArray:{scaleArray.ToSummary()}"); sb.AppendLine($" -localPositionArray:{localPositionArray.ToSummary()}"); sb.AppendLine($" -localRotationArray:{localRotationArray.ToSummary()}"); + sb.AppendLine($" -localScaleArray:{localScaleArray.ToSummary()}"); + sb.AppendLine($" -localToWorldMatirxArray:{localToWorldMatrixArray.ToSummary()}"); sb.AppendLine($" -teamIdArray:{teamIdArray.ToSummary()}"); if (transformAccessArray.isCreated) @@ -765,6 +1072,28 @@ namespace MagicaCloth2 sb.AppendLine($") {t?.name ?? "(null)"}"); } } + + // component + tcnt = componentTransformAccessArray.isCreated ? componentTransformAccessArray.length : 0; + sb.AppendLine($"Component Transform Manager. Length:{tcnt}"); + sb.AppendLine($" -componentPositionArray:{componentPositionArray.ToSummary()}"); + sb.AppendLine($" -componentMinScaleArray:{componentMinScaleArray.ToSummary()}"); + if (componentTransformAccessArray.isCreated) + { + for (int i = 0; i < tcnt; i++) + { + var t = componentTransformAccessArray[i]; + var flag = flagArray[i]; + var teamId = teamIdArray[i]; + sb.Append($" [{i}] team:{teamId} ("); + sb.Append(flag.IsSet(Flag_Enable) ? "E" : ""); + sb.Append(flag.IsSet(Flag_Restore) ? "R" : ""); + sb.Append(flag.IsSet(Flag_Read) ? "r" : ""); + sb.Append(flag.IsSet(Flag_WorldRotWrite) ? "W" : ""); + sb.Append(flag.IsSet(Flag_LocalPosRotWrite) ? "w" : ""); + sb.AppendLine($") {t?.name ?? "(null)"}"); + } + } } sb.AppendLine(); Debug.Log(sb.ToString()); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformManager.cs.meta index 261139a3..3961e260 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformManager.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformManager.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecord.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecord.cs index 9505ec4b..6918139b 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecord.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecord.cs @@ -22,19 +22,23 @@ namespace MagicaCloth2 public Matrix4x4 worldToLocalMatrix; public int pid; - public TransformRecord(Transform t) + public TransformRecord(Transform t, bool read) { if (t) { transform = t; id = t.GetInstanceID(); - localPosition = t.localPosition; - localRotation = t.localRotation; - position = t.position; - rotation = t.rotation; - scale = t.lossyScale; - localToWorldMatrix = t.localToWorldMatrix; - worldToLocalMatrix = t.worldToLocalMatrix; + + if (read) + { + localPosition = t.localPosition; + localRotation = t.localRotation; + position = t.position; + rotation = t.rotation; + scale = t.lossyScale; + localToWorldMatrix = t.localToWorldMatrix; + worldToLocalMatrix = t.worldToLocalMatrix; + } if (t.parent) pid = t.parent.GetInstanceID(); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecord.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecord.cs.meta index 51c57ba4..da0cb9c3 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecord.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecord.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecord.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs new file mode 100644 index 00000000..df3990ca --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs @@ -0,0 +1,82 @@ +// Magica Cloth 2. +// Copyright (c) 2025 MagicaSoft. +// https://magicasoft.jp +using System.Collections.Generic; +using UnityEngine; + +namespace MagicaCloth2 +{ + [System.Serializable] + public class TransformRecordSerializeData : ITransform + { + public Transform transform; // 利用しないが念の為に記録 + public Vector3 localPosition; + public Quaternion localRotation; + public Vector3 position; + public Quaternion rotation; + public Vector3 scale; // lossy scale + public Matrix4x4 localToWorldMatrix; + public Matrix4x4 worldToLocalMatrix; + + public void Serialize(TransformRecord tr) + { + Debug.Assert(tr != null); + + transform = tr.transform; + localPosition = tr.localPosition; + localRotation = tr.localRotation; + position = tr.position; + rotation = tr.rotation; + scale = tr.scale; + localToWorldMatrix = tr.localToWorldMatrix; + worldToLocalMatrix = tr.worldToLocalMatrix; + } + + public void Deserialize(TransformRecord tr) + { + Debug.Assert(tr != null); + + // 座標系のみ復元する + tr.localPosition = localPosition; + tr.localRotation = localRotation; + tr.position = position; + tr.rotation = rotation; + tr.scale = scale; + tr.localToWorldMatrix = localToWorldMatrix; + tr.worldToLocalMatrix = worldToLocalMatrix; + } + + public int GetLocalHash() + { + int hash = 0; + if (transform) + hash += (123 + transform.childCount * 345); + + return hash; + } + + public int GetGlobalHash() + { + int hash = 0; + + // ローカル姿勢のみ + hash += localPosition.GetHashCode(); + hash += localRotation.GetHashCode(); + + return hash; + } + + public void GetUsedTransform(HashSet transformSet) + { + if (transform) + transformSet.Add(transform); + } + + public void ReplaceTransform(Dictionary replaceDict) + { + int id = transform != null ? transform.GetInstanceID() : 0; + if (id != 0 && replaceDict.ContainsKey(id)) + transform = replaceDict[id]; + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs.meta new file mode 100644 index 00000000..51f0c1c2 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f4930f42a38b269439caa19e9603c9aa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/TransformManager/TransformRecordSerializeData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/VirtualMesh/VirtualMeshManager.cs b/Assets/External/MagicaCloth2/Scripts/Core/Manager/VirtualMesh/VirtualMeshManager.cs index 193f00d4..16fd987e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/VirtualMesh/VirtualMeshManager.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/VirtualMesh/VirtualMeshManager.cs @@ -102,7 +102,7 @@ namespace MagicaCloth2 public ExNativeArray uv; - public int VertexCount => teamIds?.Count ?? 0; + public int ProxyVertexCount => teamIds?.Count ?? 0; // ■トライアングル ----------------------------------------------------- public ExNativeArray triangleTeamIdArray; @@ -122,7 +122,7 @@ namespace MagicaCloth2 /// public ExNativeArray triangleTangents; - public int TriangleCount => triangles?.Count ?? 0; + public int ProxyTriangleCount => triangles?.Count ?? 0; // ■エッジ ------------------------------------------------------------- public ExNativeArray edgeTeamIdArray; @@ -137,7 +137,7 @@ namespace MagicaCloth2 /// public ExNativeArray edgeFlags; - public int EdgeCount => edges?.Count ?? 0; + public int ProxyEdgeCount => edges?.Count ?? 0; // ■ベースライン ------------------------------------------------------- /// @@ -165,7 +165,7 @@ namespace MagicaCloth2 /// public ExNativeArray baseLineData; - public int BaseLineCount => baseLineFlags?.Count ?? 0; + public int ProxyBaseLineCount => baseLineFlags?.Count ?? 0; // ■メッシュ基本(共通) ------------------------------------------------- public ExNativeArray localPositions; @@ -175,8 +175,7 @@ namespace MagicaCloth2 public ExNativeArray skinBoneTransformIndices; public ExNativeArray skinBoneBindPoses; - // ■MeshClothのみ ----------------------------------------------------- - public int MeshClothVertexCount => localPositions?.Count ?? 0; + public int ProxyLocalPositionCount => localPositions?.Count ?? 0; // ■BoneClothのみ ----------------------------------------------------- public ExNativeArray vertexToTransformRotations; @@ -193,15 +192,16 @@ namespace MagicaCloth2 public ExNativeArray mappingAttributes; public ExNativeArray mappingLocalPositins; public ExNativeArray mappingLocalNormals; - //public ExNativeArray mappingLocalTangents; + public ExNativeArray mappingLocalTangents; public ExNativeArray mappingBoneWeights; +#if MC2_DEBUG public ExNativeArray mappingPositions; - public ExNativeArray mappingNormals; - + //public ExNativeArray mappingNormals; + //public ExNativeArray mappingTangents; +#endif public int MappingVertexCount => mappingIdArray?.Count ?? 0; - //========================================================================================= bool isValid = false; @@ -299,19 +299,20 @@ namespace MagicaCloth2 mappingAttributes?.Dispose(); mappingLocalPositins?.Dispose(); mappingLocalNormals?.Dispose(); - //mappingLocalTangents?.Dispose(); + mappingLocalTangents?.Dispose(); mappingBoneWeights?.Dispose(); +#if MC2_DEBUG mappingPositions?.Dispose(); - mappingNormals?.Dispose(); + //mappingNormals?.Dispose(); + //mappingTangents?.Dispose(); +#endif mappingIdArray = null; mappingReferenceIndices = null; mappingAttributes = null; mappingLocalPositins = null; mappingLocalNormals = null; - //mappingLocalTangents = null; + mappingLocalTangents = null; mappingBoneWeights = null; - mappingPositions = null; - mappingNormals = null; } public void EnterdEditMode() @@ -376,10 +377,13 @@ namespace MagicaCloth2 mappingAttributes = new ExNativeArray(capacity, create); mappingLocalPositins = new ExNativeArray(capacity, create); mappingLocalNormals = new ExNativeArray(capacity, create); - //mappingLocalTangents = new ExNativeArray(capacity, create); + mappingLocalTangents = new ExNativeArray(capacity, create); mappingBoneWeights = new ExNativeArray(capacity, create); +#if MC2_DEBUG mappingPositions = new ExNativeArray(capacity, create); - mappingNormals = new ExNativeArray(capacity, create); + //mappingNormals = new ExNativeArray(capacity, create); + //mappingTangents = new ExNativeArray(capacity, create); +#endif isValid = true; } @@ -393,18 +397,19 @@ namespace MagicaCloth2 /// /// プロキシメッシュをマネージャに登録する /// - public void RegisterProxyMesh(int teamId, VirtualMesh proxyMesh) + public void RegisterProxyMesh(int teamId, VirtualMeshContainer proxyMeshContainer) { if (isValid == false) return; ref var tdata = ref MagicaManager.Team.GetTeamDataRef(teamId); + var proxyMesh = proxyMeshContainer.shareVirtualMesh; // mesh type tdata.proxyMeshType = proxyMesh.meshType; // Transform - tdata.proxyTransformChunk = MagicaManager.Bone.AddTransform(proxyMesh.transformData, teamId); + tdata.proxyTransformChunk = MagicaManager.Bone.AddTransform(proxyMeshContainer, teamId); // center transform tdata.centerTransformIndex = proxyMesh.centerTransformIndex + tdata.proxyTransformChunk.startIndex; @@ -479,6 +484,11 @@ namespace MagicaCloth2 { tdata.proxyBoneChunk = vertexToTransformRotations.AddRange(proxyMesh.vertexToTransformRotations); } + + // 頂点間の最大距離 + //tdata.maxVertexDistance = proxyMesh.maxVertexDistance.Value; + //Debug.Log($"maxVertexDistance:{proxyMesh.maxVertexDistance.Value}"); + //Debug.Log($"averageVertexDistance:{proxyMesh.averageVertexDistance.Value}"); } /// @@ -554,13 +564,10 @@ namespace MagicaCloth2 tdata.proxyBoneChunk.Clear(); // 同時に連動するマッピングメッシュも解放する - //var mappingIndices = tdata.mappingDataIndexSet.ToArray(); - //int mcnt = tdata.mappingDataIndexSet.Length; var mappingList = MagicaManager.Team.teamMappingIndexArray[teamId]; int mcnt = mappingList.Length; for (int i = 0; i < mcnt; i++) { - //int mappingIndex = mappingIndices[i]; int mappingIndex = mappingList[i]; ExitMappingMesh(teamId, mappingIndex); } @@ -573,7 +580,11 @@ namespace MagicaCloth2 /// /// /// - public DataChunk RegisterMappingMesh(int teamId, VirtualMesh mappingMesh) + public DataChunk RegisterMappingMesh( + int teamId, + VirtualMeshContainer mappingMeshContainer, + int renderDataWorkIndex + ) { if (isValid == false) return DataChunk.Empty; @@ -582,11 +593,12 @@ namespace MagicaCloth2 ref var mappingList = ref MagicaManager.Team.GetTeamMappingRef(teamId); var mdata = new TeamManager.MappingData(); - mdata.teamId = teamId; + var mappingMesh = mappingMeshContainer.shareVirtualMesh; + // transform - var ct = mappingMesh.GetCenterTransform(); + var ct = mappingMeshContainer.GetCenterTransform(); var c = MagicaManager.Bone.AddTransform(ct, new ExBitFlag8(TransformManager.Flag_Read | TransformManager.Flag_Enable), teamId); mdata.centerTransformIndex = c.startIndex; @@ -606,15 +618,22 @@ namespace MagicaCloth2 mappingAttributes.AddRange(mappingMesh.attributes); mappingLocalPositins.AddRange(mappingMesh.localPositions); mappingLocalNormals.AddRange(mappingMesh.localNormals); - //mappingLocalTangents.AddRange(mappingMesh.localTangents); + mappingLocalTangents.AddRange(mappingMesh.localTangents); mappingBoneWeights.AddRange(mappingMesh.boneWeights); +#if MC2_DEBUG mappingPositions.AddRange(vcnt); - mappingNormals.AddRange(vcnt); + //mappingNormals.AddRange(vcnt); + //mappingTangents.AddRange(vcnt); +#endif + + // RenderMeshWorkデータと紐づけ + mdata.renderDataWorkIndex = renderDataWorkIndex; + ref var wdata = ref MagicaManager.Render.GetRenderDataWorkRef(renderDataWorkIndex); + wdata.AddMappingIndex(mappingIndex); // 再登録 MagicaManager.Team.mappingDataArray[mappingIndex] = mdata; - //tdata.mappingDataIndexSet.Set((short)mappingIndex); - mappingList.Set((short)mappingIndex); + mappingList.MC2Set((short)mappingIndex); // vmeshにも記録する mappingMesh.mappingId = mappingIndex; @@ -643,330 +662,107 @@ namespace MagicaCloth2 mappingAttributes.Remove(mdata.mappingCommonChunk); mappingLocalPositins.Remove(mdata.mappingCommonChunk); mappingLocalNormals.Remove(mdata.mappingCommonChunk); - //mappingLocalTangents.Remove(mdata.mappingCommonChunk); + mappingLocalTangents.Remove(mdata.mappingCommonChunk); mappingBoneWeights.Remove(mdata.mappingCommonChunk); +#if MC2_DEBUG mappingPositions.Remove(mdata.mappingCommonChunk); - mappingNormals.Remove(mdata.mappingCommonChunk); + //mappingNormals.Remove(mdata.mappingCommonChunk); + //mappingTangents.Remove(mdata.mappingCommonChunk); +#endif + + // RenderMeshWorkデータとの紐づけ解除 + ref var wdata = ref MagicaManager.Render.GetRenderDataWorkRef(mdata.renderDataWorkIndex); + wdata.RemoveMappingIndex(mappingIndex); // チームから削除する - //tdata.mappingDataIndexSet.RemoveItemAtSwapBack((short)mappingIndex); - mappingList.RemoveItemAtSwapBack((short)mappingIndex); + mappingList.MC2RemoveItemAtSwapBack((short)mappingIndex); MagicaManager.Team.mappingDataArray.RemoveAndFill(new DataChunk(mappingIndex, 1)); Develop.DebugLog($"ExitMappingMesh. team:{teamId}, mappingIndex:{mappingIndex}"); } + //========================================================================================= + // Simulation //========================================================================================= /// - /// ProxyMeshの現在の姿勢を計算する - /// - /// - /// - unsafe internal JobHandle PreProxyMeshUpdate(JobHandle jobHandle) - { - if (VertexCount == 0) - return jobHandle; - - var sm = MagicaManager.Simulation; - var tm = MagicaManager.Team; - var bm = MagicaManager.Bone; - - // 作業バッファ - int bufferCount = math.max(VertexCount, TriangleCount); - sm.processingStepParticle.UpdateBuffer(bufferCount); - sm.processingStepTriangleBending.UpdateBuffer(bufferCount); // mesh cloth (skinning) - sm.processingStepEdgeCollision.UpdateBuffer(BaseLineCount); - sm.processingStepMotionParticle.UpdateBuffer(TriangleCount); // triangle - - // バッファクリア - var clearJob = new ClearProxyMeshUpdateBufferJob() - { - processingCounter0 = sm.processingStepParticle.Counter, - processingCounter1 = sm.processingStepTriangleBending.Counter, - processingCounter2 = sm.processingStepEdgeCollision.Counter, - processingCounter3 = sm.processingStepMotionParticle.Counter, - }; - jobHandle = clearJob.Schedule(jobHandle); - - // [BoneCloht(1)][MeshCloth(2)]それぞれの処理頂点インデックスリストを作成する - var job1 = new CreateProxyMeshUpdateVertexList() - { - teamDataArray = tm.teamDataArray.GetNativeArray(), - - processingCounter1 = sm.processingStepTriangleBending.Counter, - processingList1 = sm.processingStepTriangleBending.Buffer, - }; - jobHandle = job1.Schedule(tm.TeamCount, 1, jobHandle); - -#if false - // [BoneCloth] Transform姿勢を頂点姿勢として取り込む - var calcBoneClothJob = new CalcTransformDirectJob() - { - jobVertexIndexList = sm.processingIntList0.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - - transformPositions = bm.positionArray.GetNativeArray(), - transformRotations = bm.rotationArray.GetNativeArray(), - - teamIds = teamIds.GetNativeArray(), - positions = positions.GetNativeArray(), - rotations = rotations.GetNativeArray(), - }; - jobHandle = calcBoneClothJob.Schedule(sm.processingIntList0.GetJobSchedulePtr(), 8, jobHandle); -#endif - - // [MeshCloth] ProxyMeshをスキニングして頂点姿勢を求める - var calcMeshClothJob = new CalcTransformOnlySkinningJob() - { - jobVertexIndexList = sm.processingStepTriangleBending.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - - teamIds = teamIds.GetNativeArray(), - attributes = attributes.GetNativeArray(), - localPositions = localPositions.GetNativeArray(), - localNormals = localNormals.GetNativeArray(), - localTangents = localTangents.GetNativeArray(), - boneWeights = boneWeights.GetNativeArray(), - skinBoneTransformIndices = skinBoneTransformIndices.GetNativeArray(), - skinBoneBindPoses = skinBoneBindPoses.GetNativeArray(), - positions = positions.GetNativeArray(), - rotations = rotations.GetNativeArray(), - - transformPositionArray = bm.positionArray.GetNativeArray(), - transformRotationArray = bm.rotationArray.GetNativeArray(), - transformScaleArray = bm.scaleArray.GetNativeArray(), - }; - jobHandle = calcMeshClothJob.Schedule(sm.processingStepTriangleBending.GetJobSchedulePtr(), 32, jobHandle); - - return jobHandle; - } - - [BurstCompile] - struct ClearProxyMeshUpdateBufferJob : IJob - { - public NativeReference processingCounter0; - public NativeReference processingCounter1; - public NativeReference processingCounter2; - public NativeReference processingCounter3; - - public void Execute() - { - processingCounter0.Value = 0; - processingCounter1.Value = 0; - processingCounter2.Value = 0; - processingCounter3.Value = 0; - } - } - - [BurstCompile] - struct CreateProxyMeshUpdateVertexList : IJobParallelFor - { - public NativeArray teamDataArray; - - // bone (direct transform) - //[NativeDisableParallelForRestriction] - //[Unity.Collections.WriteOnly] - //public NativeReference processingCounter0; - //[NativeDisableParallelForRestriction] - //[Unity.Collections.WriteOnly] - //public NativeArray processingList0; // bone - - // mesh (skinning) - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference processingCounter1; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray processingList1; // mesh - - public void Execute(int teamId) - { - // [0]はグローバルチームなのでスキップ - if (teamId == 0) - return; - - var tdata = teamDataArray[teamId]; - if (tdata.IsEnable == false) - return; - if (tdata.IsCullingInvisible) - return; - - // 頂点リストに追加 - var c = tdata.proxyCommonChunk; - if (c.dataLength == 0) - return; - - // BoneClothもMeshClothもすべてスキニングとして登録 - int start = processingCounter1.InterlockedStartIndex(c.dataLength); - for (int j = 0; j < c.dataLength; j++) - { - int vindex = c.startIndex + j; - processingList1[start + j] = vindex; - } - -#if false - if (tdata.proxyMeshType == VirtualMesh.MeshType.ProxyMesh || tdata.flag.IsSet(TeamManager.Flag_CustomSkinning)) - { - int start = processingCounter1.InterlockedStartIndex(c.dataLength); - for (int j = 0; j < c.dataLength; j++) - { - int vindex = c.startIndex + j; - processingList1[start + j] = vindex; - } - } - if (tdata.proxyMeshType == VirtualMesh.MeshType.ProxyBoneMesh) - { - int start = processingCounter0.InterlockedStartIndex(c.dataLength); - for (int j = 0; j < c.dataLength; j++) - { - int vindex = c.startIndex + j; - processingList0[start + j] = vindex; - } - } -#endif - - //Debug.Log($"Vmesh Bone:{jobVertexIndexList1.Length}, Mesh:{jobVertexIndexList2.Length}"); - } - } - -#if false - /// - /// Transformから対応する頂点に姿勢をコピーする - /// - [BurstCompile] - struct CalcTransformDirectJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray jobVertexIndexList; - - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - - // transform - [Unity.Collections.ReadOnly] - public NativeArray transformPositions; - [Unity.Collections.ReadOnly] - public NativeArray transformRotations; - - // vmesh - [Unity.Collections.ReadOnly] - public NativeArray teamIds; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray positions; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray rotations; - - public void Execute(int index) - { - int vindex = jobVertexIndexList[index]; - int teamId = teamIds[vindex]; - var tdata = teamDataArray[teamId]; - int l_index = vindex - tdata.proxyCommonChunk.startIndex; - - // 現在のトランスフォームワールド姿勢 - int tindex = tdata.proxyTransformChunk.startIndex + l_index; - var wpos = transformPositions[tindex]; - quaternion wrot = transformRotations[tindex]; - - positions[vindex] = wpos; - rotations[vindex] = wrot; - } - } -#endif - - /// - /// 頂点スキニングを行い座標・法線・接線を求める + /// プロキシメッシュの頂点スキニングを行い座標・法線・接線を求める + /// [BoneCloth][MeshCloth]兼用 /// 姿勢はワールド座標で格納される /// - [BurstCompile] - struct CalcTransformOnlySkinningJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray jobVertexIndexList; - + internal static void SimulationPreProxyMeshUpdate( + DataChunk chunk, // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; + int teamId, + ref TeamManager.TeamData tdata, // vmesh - [Unity.Collections.ReadOnly] - public NativeArray teamIds; - [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] - [Unity.Collections.WriteOnly] - public NativeArray positions; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray rotations; + in NativeArray attributes, + in NativeArray localPositions, + in NativeArray localNormals, + in NativeArray localTangents, + in NativeArray boneWeights, + in NativeArray skinBoneTransformIndices, + in NativeArray skinBoneBindPoses, + ref NativeArray positions, + ref NativeArray rotations, // transform - [Unity.Collections.ReadOnly] - public NativeArray transformPositionArray; - [Unity.Collections.ReadOnly] - public NativeArray transformRotationArray; - [Unity.Collections.ReadOnly] - public NativeArray transformScaleArray; + in NativeArray transformLocalToWorldMatrixArray + ) + { + var pc = tdata.proxyCommonChunk; + if (pc.dataLength == 0) + return; - public void Execute(int index) + // ProxyMeshをスキニングして頂点姿勢を求める + //int vindex = pc.startIndex; + int vindex = pc.startIndex + chunk.startIndex; + //int mvindex = tdata.proxyMeshChunk.startIndex; + int mvindex = tdata.proxyMeshChunk.startIndex + chunk.startIndex; + int sb_start = tdata.proxySkinBoneChunk.startIndex; + int t_start = tdata.proxyTransformChunk.startIndex; + float4x3 wpose = 0; + float4x3 _pose = 0; + float4x3 _lpose = 0; + //for (int k = 0; k < pc.dataLength; k++, vindex++, mvindex++) + for (int k = 0; k < chunk.dataLength; k++, vindex++, mvindex++) { - int vindex = jobVertexIndexList[index]; - int teamId = teamIds[vindex]; - var tdata = teamDataArray[teamId]; - int l_index = vindex - tdata.proxyCommonChunk.startIndex; - - int mvindex = tdata.proxyMeshChunk.startIndex + l_index; - int sb_start = tdata.proxySkinBoneChunk.startIndex; - int t_start = tdata.proxyTransformChunk.startIndex; - var bw = boneWeights[mvindex]; int wcnt = bw.Count; - float3 wpos = 0; - float3 wnor = 0; - float3 wtan = 0; + + wpose = 0; + _pose = 0; + + _lpose.c0 = new float4(localPositions[mvindex], 1); + _lpose.c1 = new float4(localNormals[mvindex], 0); + _lpose.c2 = new float4(localTangents[mvindex], 0); + for (int i = 0; i < wcnt; i++) { float w = bw.weights[i]; + _pose = _lpose; + //Debug.Log($"[{mvindex}] lpos:{lpos}, lnor:{lnor}, ltan:{ltan}"); + + // ボーンローカル空間に変換 int l_boneIndex = bw.boneIndices[i]; float4x4 bp = skinBoneBindPoses[sb_start + l_boneIndex]; - float4 lpos = new float4(localPositions[mvindex], 1); - float4 lnor = new float4(localNormals[mvindex], 0); - float4 ltan = new float4(localTangents[mvindex], 0); - - float3 pos = math.mul(bp, lpos).xyz; - float3 nor = math.mul(bp, lnor).xyz; - float3 tan = math.mul(bp, ltan).xyz; + _pose = math.mul(bp, _pose); + // 現在のワールド空間に変換 int tindex = skinBoneTransformIndices[sb_start + l_boneIndex] + t_start; - var tpos = transformPositionArray[tindex]; - var trot = transformRotationArray[tindex]; - var tscl = transformScaleArray[tindex]; - MathUtility.TransformPositionNormalTangent(tpos, trot, tscl, ref pos, ref nor, ref tan); + var lw = transformLocalToWorldMatrixArray[tindex]; + _pose = math.mul(lw, _pose); - wpos += pos * w; - wnor += nor * w; - wtan += tan * w; + // ウエイト + wpose += _pose * w; } + float3 wpos = wpose.c0.xyz; + float3 wnor = wpose.c1.xyz; + float3 wtan = wpose.c2.xyz; + // バインドポーズにスケールが入るので単位化する必要がある #if MC2_DEBUG Develop.Assert(math.length(wnor) > 0.0f); @@ -978,329 +774,38 @@ namespace MagicaCloth2 positions[vindex] = wpos; rotations[vindex] = wrot; + + //Debug.Log($"[{teamId}] pv:{vindex}, wpos:{wpos}"); } } - //========================================================================================= /// /// クロスシミュレーションの結果をProxyMeshへ反映させる + /// ラインがある場合はベースラインごとに姿勢を整える /// - /// - /// - internal unsafe JobHandle PostProxyMeshUpdate(JobHandle jobHandle) - { - if (VertexCount == 0) - return jobHandle; - - var sm = MagicaManager.Simulation; - var tm = MagicaManager.Team; - var bm = MagicaManager.Bone; - - // バッファクリア - var clearJob = new ClearProxyMeshUpdateBufferJob() - { - processingCounter0 = sm.processingStepParticle.Counter, - processingCounter1 = sm.processingStepTriangleBending.Counter, - processingCounter2 = sm.processingStepEdgeCollision.Counter, - processingCounter3 = sm.processingStepMotionParticle.Counter, - }; - jobHandle = clearJob.Schedule(jobHandle); - - // 今回更新が必要な各インデックスリストを作成する - var createUpdateListJob = new CreatePostProxyMeshUpdateListJob() - { - teamDataArray = tm.teamDataArray.GetNativeArray(), - - // Triangle Vertex - processingCounter0 = sm.processingStepParticle.Counter, - processingList0 = sm.processingStepParticle.Buffer, - - // Transform Vertex - processingCounter1 = sm.processingStepTriangleBending.Counter, - processingList1 = sm.processingStepTriangleBending.Buffer, - - // Base line - processingCounter2 = sm.processingStepEdgeCollision.Counter, - processingList2 = sm.processingStepEdgeCollision.Buffer, - - // Triangle - processingCounter3 = sm.processingStepMotionParticle.Counter, - processingList3 = sm.processingStepMotionParticle.Buffer, - }; - jobHandle = createUpdateListJob.Schedule(tm.TeamCount, 1, jobHandle); - - // ラインがある場合はベースラインごとに姿勢を整える - if (BaseLineCount > 0) - { - // ラインの法線・接線を求める - // (ローカル座標空間) - var calcBaseLineNormalTangentJob = new CalcBaseLineNormalTangentJob() - { - jobBaseLineList = sm.processingStepEdgeCollision.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - parameterArray = tm.parameterArray.GetNativeArray(), - - attributes = attributes.GetNativeArray(), - positions = positions.GetNativeArray(), - rotations = rotations.GetNativeArray(), - vertexLocalPositions = vertexLocalPositions.GetNativeArray(), - vertexLocalRotations = vertexLocalRotations.GetNativeArray(), - parentIndices = vertexParentIndices.GetNativeArray(), - childIndexArray = vertexChildIndexArray.GetNativeArray(), - childDataArray = vertexChildDataArray.GetNativeArray(), - - baseLineFlags = baseLineFlags.GetNativeArray(), - baseLineTeamIds = baseLineTeamIds.GetNativeArray(), - baseLineStartIndices = baseLineStartDataIndices.GetNativeArray(), - baseLineCounts = baseLineDataCounts.GetNativeArray(), - baseLineIndices = baseLineData.GetNativeArray(), - }; - jobHandle = calcBaseLineNormalTangentJob.Schedule(sm.processingStepEdgeCollision.GetJobSchedulePtr(), 8, jobHandle); - } - - // トライアングルがある場合はトライアングル接続情報から最終的な姿勢を求める - if (TriangleCount > 0) - { - // トライアングルの法線・接線を求める - // (ローカル座標空間) - var triangleNormalTangentJob = new CalcTriangleNormalTangentJob() - { - jobTriangleList = sm.processingStepMotionParticle.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - - triangleTeamIdArray = triangleTeamIdArray.GetNativeArray(), - triangles = triangles.GetNativeArray(), - outTriangleNormals = triangleNormals.GetNativeArray(), - outTriangleTangents = triangleTangents.GetNativeArray(), - - positions = positions.GetNativeArray(), - uv = uv.GetNativeArray(), - }; - jobHandle = triangleNormalTangentJob.Schedule(sm.processingStepMotionParticle.GetJobSchedulePtr(), 16, jobHandle); - - // トライアングルの法線接線から頂点法線接線を平均化して求める - // (ローカル座標空間) - var vertexNormalTangentFromTriangleJob = new CalcVertexNormalTangentFromTriangleJob() - { - jobVertexIndexList = sm.processingStepParticle.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - - teamIds = teamIds.GetNativeArray(), - triangleNormals = triangleNormals.GetNativeArray(), - triangleTangents = triangleTangents.GetNativeArray(), - vertexToTriangles = vertexToTriangles.GetNativeArray(), - normalAdjustmentRotations = normalAdjustmentRotations.GetNativeArray(), - outRotations = rotations.GetNativeArray(), - }; - jobHandle = vertexNormalTangentFromTriangleJob.Schedule(sm.processingStepParticle.GetJobSchedulePtr(), 32, jobHandle); - } - - // Transformパーティクルの場合はvertexToTransform回転を乗算してTransformDataに情報を書き戻す - var writeTransformDataJob = new WriteTransformDataJob() - { - jobVertexIndexList = sm.processingStepTriangleBending.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - - transformPositionArray = bm.positionArray.GetNativeArray(), - transformRotationArray = bm.rotationArray.GetNativeArray(), - - teamIds = teamIds.GetNativeArray(), - positions = positions.GetNativeArray(), - rotations = rotations.GetNativeArray(), - vertexToTransformRotations = vertexToTransformRotations.GetNativeArray(), - }; - jobHandle = writeTransformDataJob.Schedule(sm.processingStepTriangleBending.GetJobSchedulePtr(), 32, jobHandle); - - // Transformパーティクルは親からのローカル姿勢を計算してTransformData情報に書き込む - var writeLocalTransformDataJob = new WriteTransformLocalDataJob() - { - jobVertexIndexList = sm.processingStepTriangleBending.Buffer, - - teamDataArray = tm.teamDataArray.GetNativeArray(), - - teamIds = teamIds.GetNativeArray(), - attributes = attributes.GetNativeArray(), - vertexParentIndices = vertexParentIndices.GetNativeArray(), - - transformPositionArray = bm.positionArray.GetNativeArray(), - transformRotationArray = bm.rotationArray.GetNativeArray(), - transformScaleArray = bm.scaleArray.GetNativeArray(), - transformLocalPositionArray = bm.localPositionArray.GetNativeArray(), - transformLocalRotationArray = bm.localRotationArray.GetNativeArray(), - }; - jobHandle = writeLocalTransformDataJob.Schedule(sm.processingStepTriangleBending.GetJobSchedulePtr(), 32, jobHandle); - - - return jobHandle; - } - - [BurstCompile] - struct CreatePostProxyMeshUpdateListJob : IJobParallelFor - { - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - - // triangle vertex update - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference processingCounter0; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray processingList0; - - // transform vertex update - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference processingCounter1; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray processingList1; - - // base line - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference processingCounter2; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray processingList2; - - // triangle - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeReference processingCounter3; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray processingList3; - - public void Execute(int teamId) - { - // [0]はグローバルチームなのでスキップ - if (teamId == 0) - return; - var tdata = teamDataArray[teamId]; - if (tdata.IsEnable == false) - return; - if (tdata.IsCullingInvisible) - return; - - // トライアングル[0] - if (tdata.TriangleCount > 0 && tdata.proxyCommonChunk.IsValid) - { - int start = processingCounter0.InterlockedStartIndex(tdata.proxyCommonChunk.dataLength); - for (int j = 0; j < tdata.proxyCommonChunk.dataLength; j++) - { - int vindex = tdata.proxyCommonChunk.startIndex + j; - processingList0[start + j] = vindex; - } - } - - // トランスフォーム書き込み[1] - if (tdata.proxyMeshType == VirtualMesh.MeshType.ProxyBoneMesh) - { - int start = processingCounter1.InterlockedStartIndex(tdata.proxyCommonChunk.dataLength); - for (int j = 0; j < tdata.proxyCommonChunk.dataLength; j++) - { - int vindex = tdata.proxyCommonChunk.startIndex + j; - processingList1[start + j] = vindex; - } - } - - // ベースライン[2] - if (tdata.baseLineChunk.IsValid) - { - int start = processingCounter2.InterlockedStartIndex(tdata.baseLineChunk.dataLength); - for (int j = 0; j < tdata.baseLineChunk.dataLength; j++) - { - int bindex = tdata.baseLineChunk.startIndex + j; - processingList2[start + j] = bindex; - } - } - - // トライアングル2 - if (tdata.TriangleCount > 0) - { - int start = processingCounter3.InterlockedStartIndex(tdata.proxyTriangleChunk.dataLength); - for (int j = 0; j < tdata.proxyTriangleChunk.dataLength; j++) - { - int tindex = tdata.proxyTriangleChunk.startIndex + j; - processingList3[start + j] = tindex; - } - } - - //Debug.Log($"BaseLine:{jobBaseLineList.Length}, Triangle Vertex:{jobVertexIndexList1.Length}, Transform Vertex:{jobVertexIndexList2.Length}"); - } - } - - /// - /// ベースラインの法線接線を求める - /// - [BurstCompile] - struct CalcBaseLineNormalTangentJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray jobBaseLineList; - + internal static void SimulationPostProxyMeshUpdateLine( + DataChunk chunk, // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - [Unity.Collections.ReadOnly] - public NativeArray parameterArray; - + ref TeamManager.TeamData tdata, + ref ClothParameters param, // vmesh - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [Unity.Collections.ReadOnly] - public NativeArray positions; - [NativeDisableParallelForRestriction] - public NativeArray rotations; - [Unity.Collections.ReadOnly] - public NativeArray vertexLocalPositions; - [Unity.Collections.ReadOnly] - public NativeArray vertexLocalRotations; - [Unity.Collections.ReadOnly] - public NativeArray parentIndices; - [Unity.Collections.ReadOnly] - public NativeArray childIndexArray; - [Unity.Collections.ReadOnly] - public NativeArray childDataArray; - - [Unity.Collections.ReadOnly] - public NativeArray baseLineFlags; - [Unity.Collections.ReadOnly] - public NativeArray baseLineTeamIds; - [Unity.Collections.ReadOnly] - public NativeArray baseLineStartIndices; - [Unity.Collections.ReadOnly] - public NativeArray baseLineCounts; - [Unity.Collections.ReadOnly] - public NativeArray baseLineIndices; - - // ベースラインごと - public void Execute(int index) + ref NativeArray attributes, + ref NativeArray positions, + ref NativeArray rotations, + ref NativeArray vertexLocalPositions, + ref NativeArray vertexLocalRotations, + ref NativeArray childIndexArray, + ref NativeArray childDataArray, + ref NativeArray baseLineFlags, + ref NativeArray baseLineStartIndices, + ref NativeArray baseLineDataCounts, + ref NativeArray baseLineData + ) + { + // ラインがある場合はベースラインごとに姿勢を整える + if (tdata.baseLineChunk.IsValid) { - int bindex = jobBaseLineList[index]; - - // ラインを含む場合のみ実行する - var bflag = baseLineFlags[bindex]; - if (bflag.IsSet(VirtualMesh.BaseLineFlag_IncludeLine) == false) - return; - - // team - int teamId = baseLineTeamIds[bindex]; - if (teamId == 0) - return; - var tdata = teamDataArray[teamId]; - if (tdata.IsEnable == false) - return; - if (tdata.IsCullingInvisible) - return; - // parameter - var param = parameterArray[teamId]; float averageRate = param.rotationalInterpolation; // 回転平均化割合 float rootInterpolation = param.rootRotation; @@ -1308,491 +813,445 @@ namespace MagicaCloth2 int s_dataIndex = tdata.baseLineDataChunk.startIndex; int s_childDataIndex = tdata.proxyVertexChildDataChunk.startIndex; - // ベースラインをルートから走査する - int dataIndex = baseLineStartIndices[bindex] + s_dataIndex; - int dataCnt = baseLineCounts[bindex]; - for (int i = 0; i < dataCnt; i++, dataIndex++) + //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 vindex = baseLineIndices[dataIndex] + s_vindex; - var pos = positions[vindex]; - var rot = rotations[vindex]; - var attr = attributes[vindex]; + // ラインを含む場合のみ実行する + var bflag = baseLineFlags[bindex]; + if (bflag.IsSet(VirtualMesh.BaseLineFlag_IncludeLine) == false) + continue; - // 子の情報 - var pack = childIndexArray[vindex]; - int cstart = DataUtility.Unpack12_20Low(pack); - int ccnt = DataUtility.Unpack12_20Hi(pack); - - int movecnt = 0; - if (ccnt > 0) + // ベースラインをルートから走査する + int dataIndex = baseLineStartIndices[bindex] + s_dataIndex; + int dataCnt = baseLineDataCounts[bindex]; + for (int i = 0; i < dataCnt; i++, dataIndex++) { - // 子への平均ベクトル - float3 ctv = 0; - float3 cv = 0; + // 自身を親とする + int vindex = baseLineData[dataIndex] + s_vindex; + var pos = positions[vindex]; + var rot = rotations[vindex]; + var attr = attributes[vindex]; - // 自身を基準に子の回転を求める、また子への平均ベクトルを加算する - for (int j = 0; j < ccnt; j++) + //Debug.Log($"p:[{vindex}] rot:[{rot}] wn:{MathUtility.ToNormal(rot)}, wt:{MathUtility.ToTangent(rot)}"); + + // 子の情報 + var pack = childIndexArray[vindex]; + int cstart = DataUtility.Unpack12_20Low(pack); + int ccnt = DataUtility.Unpack12_20Hi(pack); +#if true + int movecnt = 0; + if (ccnt > 0) { - int cvindex = childDataArray[s_childDataIndex + cstart + j] + s_vindex; + // 子への平均ベクトル + float3 ctv = 0; + float3 cv = 0; - // 子の属性 - var cattr = attributes[cvindex]; - - // 子の座標 - var cpos = positions[cvindex]; - - // 子の本来のベクトル - float3 tv = math.mul(rot, vertexLocalPositions[cvindex]); - ctv += tv; - - if (cattr.IsMove()) + // 自身を基準に子の回転を求める、また子への平均ベクトルを加算する + for (int j = 0; j < ccnt; j++) { - // 子の現在ベクトル - float3 v = cpos - pos; - cv += v; + int cvindex = childDataArray[s_childDataIndex + cstart + j] + s_vindex; - // 回転 - var q = MathUtility.FromToRotation(tv, v); + // 子の属性 + var cattr = attributes[cvindex]; - // 子の姿勢を決定 - var crot = math.mul(rot, vertexLocalRotations[cvindex]); - crot = math.mul(q, crot); - rotations[cvindex] = crot; + // 子の座標 + var cpos = positions[cvindex]; - movecnt++; - } - else - { - // 子が固定の場合 - cv += tv; + // 子の本来のベクトル + // マイナススケール + float3 tv = math.mul(rot, vertexLocalPositions[cvindex] * tdata.negativeScaleDirection); + //float3 tv = math.mul(rot, vertexLocalPositions[cvindex]); // オリジナル + //Debug.Log($"p:[{vindex}] c:[{cvindex}] tv:{tv}"); + + ctv += tv; + + if (cattr.IsMove()) + { + // 子の現在ベクトル + float3 v = cpos - pos; + cv += v; + + //Debug.Log($"p:[{vindex}] c:[{cvindex}] v:{v}"); + + // 回転 + var q = MathUtility.FromToRotation(tv, v); + + // 子の姿勢を決定 + // マイナススケール + var crot = math.mul(rot, vertexLocalRotations[cvindex].value * tdata.negativeScaleQuaternionValue); + //var crot = math.mul(rot, vertexLocalRotations[cvindex]); // オリジナル + //Debug.Log($"c:[{cvindex}] crot:[{crot}] cwn:{MathUtility.ToNormal(crot)}, cwt:{MathUtility.ToTangent(crot)}"); + + crot = math.mul(q, crot); + rotations[cvindex] = crot; + + movecnt++; + } + else + { + // 子が固定の場合 + cv += tv; + } } + + // 子がすべて固定の場合は回転調整を行わない + if (movecnt == 0) + continue; + + // 子の移動方向変化に伴う回転調整 + float t = attr.IsMove() ? averageRate : rootInterpolation; + var cq = MathUtility.FromToRotation(ctv, cv, t); + + // 自身の姿勢を確定させる + rot = math.mul(cq, rot); + rotations[vindex] = rot; } - - // 子がすべて固定の場合は回転調整を行わない - if (movecnt == 0) - continue; - - // 子の移動方向変化に伴う回転調整 - float t = attr.IsMove() ? averageRate : rootInterpolation; - var cq = MathUtility.FromToRotation(ctv, cv, t); - - // 自身の姿勢を確定させる - rot = math.mul(cq, rot); - rotations[vindex] = rot; +#endif } - else + } + } + } + + /// + /// クロスシミュレーションの結果をProxyMeshへ反映させる + /// トライアングルの法線と接線を求める + /// + internal static void SimulationPostProxyMeshUpdateTriangle( + DataChunk chunk, + // team + ref TeamManager.TeamData tdata, + // vmesh + ref NativeArray positions, + ref NativeArray triangles, + ref NativeArray triangleNormals, + ref NativeArray triangleTangents, + ref NativeArray uvs + ) + { + + // トライアングルがある場合はトライアングル接続情報から最終的な姿勢を求める + if (tdata.TriangleCount > 0) + { + // トライアングルの法線と接線を求める + // 座標系の変換は行わない + //int tindex = tdata.proxyTriangleChunk.startIndex; + int tindex = tdata.proxyTriangleChunk.startIndex + chunk.startIndex; + //for (int k = 0; k < tdata.proxyTriangleChunk.dataLength; k++, tindex++) + for (int k = 0; k < chunk.dataLength; k++, tindex++) + { + int3 tri = triangles[tindex]; + + // トライアングル法線を求める + int start = tdata.proxyCommonChunk.startIndex; + var pos1 = positions[start + tri.x]; + var pos2 = positions[start + tri.y]; + var pos3 = positions[start + tri.z]; + float3 cross = math.cross(pos2 - pos1, pos3 - pos1); + float len = math.length(cross); + if (len > Define.System.Epsilon) { -#if false - // 末端 - if (param.boneParameters.leafRotation) + float3 nor = cross / len; + + // マイナススケール + nor *= tdata.negativeScaleTriangleSign.x; + + triangleNormals[tindex] = nor; + } +#if MC2_DEBUG + else + Debug.LogWarning("CalcTriangleNormalTangentJob.normal = 0!"); +#endif + + // トライアングル接線を求める + var uv1 = uvs[start + tri.x]; + var uv2 = uvs[start + tri.y]; + var uv3 = uvs[start + tri.z]; + var tan = MathUtility.TriangleTangent(pos1, pos2, pos3, uv1, uv2, uv3); + if (math.lengthsq(tan) > 0.0f) + { + // マイナススケール + tan *= tdata.negativeScaleTriangleSign.y; + + triangleTangents[tindex] = tan; + } +#if MC2_DEBUG + else + Debug.LogWarning("CalcTriangleNormalTangentJob.tangent = 0!"); +#endif + } + } + } + + /// + /// クロスシミュレーションの結果をProxyMeshへ反映させる + /// トライアングルの法線接線から頂点法線接線を平均化して求める + /// + internal static void SimulationPostProxyMeshUpdateTriangleSum( + DataChunk chunk, + // team + ref TeamManager.TeamData tdata, + // vmesh + ref NativeArray rotations, + ref NativeArray triangleNormals, + ref NativeArray triangleTangents, + ref NativeArray> vertexToTriangles, + ref NativeArray normalAdjustmentRotations + ) + { + // トライアングルがある場合はトライアングル接続情報から最終的な姿勢を求める + if (tdata.TriangleCount > 0) + { + // トライアングルの法線接線から頂点法線接線を平均化して求める + // (ワールド座標空間) + //int vindex = tdata.proxyCommonChunk.startIndex; + int vindex = tdata.proxyCommonChunk.startIndex + chunk.startIndex; + //for (int k = 0; k < tdata.proxyCommonChunk.dataLength; k++, vindex++) + for (int k = 0; k < chunk.dataLength; k++, vindex++) + { + var tlist = vertexToTriangles[vindex]; + if (tlist.Length > 0) + { + float3 nor = 0; + float3 tan = 0; + for (int i = 0; i < tlist.Length; i++) { - // 親からの角度分さらに曲げる(この方が見た目が良くなる) - int pvindex = parentIndices[vindex] + s_vindex; - if (pvindex >= 0) + // 12-20bitのパックで格納されている + // 12(hi) = 法線と接線のフリップフラグ + // 20(low) = トライアングルインデックス + uint data = tlist[i]; + int flipFlag = DataUtility.Unpack12_20Hi(data); + int tindex = DataUtility.Unpack12_20Low(data); + + tindex += tdata.proxyTriangleChunk.startIndex; + nor += triangleNormals[tindex] * ((flipFlag & 0x1) == 0 ? 1 : -1); + tan += triangleTangents[tindex] * ((flipFlag & 0x2) == 0 ? 1 : -1); + } + //Debug.Log($"Vertex:{vindex} nor:{nor}, tan:{tan}"); + + // 法線0を考慮する。法線を0にするとポリゴンが欠けるため + float ln = math.length(nor); + float lt = math.length(tan); + if (ln > 1e-06f && lt > 1e-06f) + { + nor = nor / ln; + tan = tan / lt; + + float dot = math.dot(nor, tan); + if (dot != 1.0f && dot != -1.0f) { - var ppos = positions[pvindex]; - var prot = rotations[pvindex]; + // トライアングル回転は従法線から算出するように変更(v2.1.7) + float3 binor = math.normalize(math.cross(nor, tan)); + var rot = quaternion.LookRotation(binor, nor); - // 本来のベクトル - float3 tv = math.mul(prot, vertexLocalPositions[vindex]); + // 法線調整用回転を乗算する(不要な場合は単位回転が入っている) + // マイナススケール + rot = math.mul(rot, normalAdjustmentRotations[vindex].value * tdata.negativeScaleQuaternionValue); + //rot = math.mul(rot, normalAdjustmentRotations[vindex]); // オリジナル - // 現在のベクトル - float3 v = pos - ppos; - - // 回転 - var q = MathUtility.FromToRotation(tv, v, averageRate); - - // 親からの角度分さらに回転させる - rot = math.mul(q, rot); rotations[vindex] = rot; } } -#endif } } } } /// - /// トライアングルの法線と接線を求める - /// 座標系の変換は行わない + /// クロスシミュレーションの結果をProxyMeshへ反映させる + /// BoneClothの場合は頂点姿勢から連動するトランスフォームのワールド姿勢を計算する /// - [BurstCompile] - struct CalcTriangleNormalTangentJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray jobTriangleList; - + internal static void SimulationPostProxyMeshUpdateWorldTransform( + DataChunk chunk, // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - - // triangle - [Unity.Collections.ReadOnly] - public NativeArray triangleTeamIdArray; - [Unity.Collections.ReadOnly] - public NativeArray triangles; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray outTriangleNormals; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray outTriangleTangents; - + ref TeamManager.TeamData tdata, // vmesh - [Unity.Collections.ReadOnly] - public NativeArray positions; - [Unity.Collections.ReadOnly] - public NativeArray uv; - - - // トライアングルごと - public void Execute(int index) - { - int tindex = jobTriangleList[index]; - - int teamId = triangleTeamIdArray[tindex]; - if (teamId == 0) - return; - var tdata = teamDataArray[teamId]; - if (tdata.IsEnable == false) - return; - if (tdata.IsCullingInvisible) - return; - - int3 tri = triangles[tindex]; - - // トライアングル法線を求める - int start = tdata.proxyCommonChunk.startIndex; - var pos1 = positions[start + tri.x]; - var pos2 = positions[start + tri.y]; - var pos3 = positions[start + tri.z]; - float3 cross = math.cross(pos2 - pos1, pos3 - pos1); - float len = math.length(cross); - if (len > Define.System.Epsilon) - outTriangleNormals[tindex] = cross / len; -#if MC2_DEBUG - else - Debug.LogWarning("CalcTriangleNormalTangentJob.normal = 0!"); -#endif - - // トライアングル接線を求める - var uv1 = uv[start + tri.x]; - var uv2 = uv[start + tri.y]; - var uv3 = uv[start + tri.z]; - var tan = MathUtility.TriangleTangent(pos1, pos2, pos3, uv1, uv2, uv3); - if (math.lengthsq(tan) > 0.0f) - outTriangleTangents[tindex] = tan; -#if MC2_DEBUG - else - Debug.LogWarning("CalcTriangleNormalTangentJob.tangent = 0!"); -#endif - // len = math.length(tan); - // if (len > 1e-06f) - // outTriangleTangents[tindex] = tan / len; - //#if MC2_DEBUG - // else - // Debug.LogWarning("CalcTriangleNormalTangentJob.tangent = 0!"); - //#endif - - } - } - - /// - /// 接続するトライアングルの法線接線を平均化して頂点法線接線を求める - /// - [BurstCompile] - struct CalcVertexNormalTangentFromTriangleJob : IJobParallelForDefer + ref NativeArray positions, + ref NativeArray rotations, + ref NativeArray vertexToTransformRotations, + // transform + ref NativeArray transformPositionArray, + ref NativeArray transformRotationArray + ) { - [Unity.Collections.ReadOnly] - public NativeArray jobVertexIndexList; - - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - - // vmesh - [Unity.Collections.ReadOnly] - public NativeArray teamIds; - [Unity.Collections.ReadOnly] - public NativeArray triangleNormals; - [Unity.Collections.ReadOnly] - public NativeArray triangleTangents; - [Unity.Collections.ReadOnly] - public NativeArray> vertexToTriangles; - [Unity.Collections.ReadOnly] - public NativeArray normalAdjustmentRotations; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray outRotations; - - // 頂点ごと - public void Execute(int index) + // Transformパーティクル + if (tdata.proxyMeshType == VirtualMesh.MeshType.ProxyBoneMesh) { - int vindex = jobVertexIndexList[index]; - int teamId = teamIds[vindex]; - if (teamId == 0) - return; - var tdata = teamDataArray[teamId]; - - var tlist = vertexToTriangles[vindex]; - if (tlist.Length > 0) + // Transformパーティクルの場合はvertexToTransform回転を乗算してTransformDataに情報を書き戻す + //int vindex = tdata.proxyCommonChunk.startIndex; + int vindex = tdata.proxyCommonChunk.startIndex + chunk.startIndex; + //for (int k = 0; k < tdata.proxyCommonChunk.dataLength; k++, vindex++) + for (int k = 0; k < chunk.dataLength; k++, vindex++) { - float3 nor = 0; - float3 tan = 0; - for (int i = 0; i < tlist.Length; i++) - { - // 12-20bitのパックで格納されている - // 12(hi) = 法線と接線のフリップフラグ - // 20(low) = トライアングルインデックス - uint data = tlist[i]; - int flipFlag = DataUtility.Unpack12_20Hi(data); - int tindex = DataUtility.Unpack12_20Low(data); + // pos/rotはワールド空間 + var pos = positions[vindex]; + var rot = rotations[vindex]; - tindex += tdata.proxyTriangleChunk.startIndex; - nor += triangleNormals[tindex] * ((flipFlag & 0x1) == 0 ? 1 : -1); - tan += triangleTangents[tindex] * ((flipFlag & 0x2) == 0 ? 1 : -1); + // 本来のTransformの姿勢を求める回転を掛ける + //int boneIndex = tdata.proxyBoneChunk.startIndex + k; + int boneIndex = tdata.proxyBoneChunk.startIndex + chunk.startIndex + k; + quaternion v2t = vertexToTransformRotations[boneIndex]; - /* - // トライアングルインデックスが負の値ならば法線をフリップさせる - // トライアングルインデックスは+1の値が格納されているので注意! - int tindex = tlist[i]; - float flip = math.sign(tindex); - tindex = math.abs(tindex) - 1; - tindex += tdata.proxyTriangleChunk.startIndex; + // マイナススケール + rot = math.mul(rot, v2t.value * tdata.negativeScaleQuaternionValue); + //rot = math.mul(rot, v2t); // オリジナル - nor += triangleNormals[tindex] * flip; - tan += triangleTangents[tindex]; // 接線はフリップさせては駄目! - */ - } - - //Debug.Log($"Vertex:{vindex} nor:{nor}, tan:{tan}"); - - - // 法線0を考慮する。法線を0にするとポリゴンが欠けるため - float ln = math.length(nor); - float lt = math.length(tan); - if (ln > 1e-06f && lt > 1e-06f) - { - nor = nor / ln; - tan = tan / lt; - float dot = math.dot(nor, tan); - if (dot != 1.0f && dot != -1.0f) - { - // トライアングル回転は従法線から算出するように変更(v2.1.7) - //var rot = quaternion.LookRotation(tan, nor); - float3 binor = math.normalize(math.cross(nor, tan)); - var rot = quaternion.LookRotation(binor, nor); - - // 法線調整用回転を乗算する(不要な場合は単位回転が入っている) - rot = math.mul(rot, normalAdjustmentRotations[vindex]); - - outRotations[vindex] = rot; - } - } + // ワールド姿勢 + //int tindex = tdata.proxyTransformChunk.startIndex + k; + int tindex = tdata.proxyTransformChunk.startIndex + chunk.startIndex + k; + transformPositionArray[tindex] = pos; + transformRotationArray[tindex] = rot; } } } /// - /// パーティクルの姿勢をTransformDataに書き込む + /// BoneClothの場合はTransformのローカル姿勢を計算する /// - [BurstCompile] - struct WriteTransformDataJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray jobVertexIndexList; - + internal static void SimulationPostProxyMeshUpdateLocalTransform( // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - - // transform - [NativeDisableParallelForRestriction] - public NativeArray transformPositionArray; - [NativeDisableParallelForRestriction] - public NativeArray transformRotationArray; - + ref TeamManager.TeamData tdata, // vmesh - [Unity.Collections.ReadOnly] - public NativeArray teamIds; - [Unity.Collections.ReadOnly] - public NativeArray positions; - [Unity.Collections.ReadOnly] - public NativeArray rotations; - [Unity.Collections.ReadOnly] - public NativeArray vertexToTransformRotations; - - // トランスフォームパーティクルごと - public void Execute(int index) - { - int vindex = jobVertexIndexList[index]; - int teamId = teamIds[vindex]; - if (teamId == 0) - return; - var tdata = teamDataArray[teamId]; - - int l_vindex = vindex - tdata.proxyCommonChunk.startIndex; - - var pos = positions[vindex]; - var rot = rotations[vindex]; - - // 本来のTransformの姿勢を求める回転を掛ける - int boneIndex = tdata.proxyBoneChunk.startIndex + l_vindex; - rot = math.mul(rot, vertexToTransformRotations[boneIndex]); - - // ワールド姿勢 - int tindex = tdata.proxyTransformChunk.startIndex + l_vindex; - transformPositionArray[tindex] = pos; - transformRotationArray[tindex] = rot; - - //Debug.Log($"[{teamId}] vindex:{vindex}, l_vlindex:{l_vindex}, tindex:{tindex}"); - } - } - - /// - /// TransformパーティクルのTransformについて親からのローカル姿勢を計算する - /// - [BurstCompile] - struct WriteTransformLocalDataJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray jobVertexIndexList; - - // team - [Unity.Collections.ReadOnly] - public NativeArray teamDataArray; - - // vmeah - [Unity.Collections.ReadOnly] - public NativeArray teamIds; - [Unity.Collections.ReadOnly] - public NativeArray attributes; - [NativeDisableParallelForRestriction] - public NativeArray vertexParentIndices; - + ref NativeArray attributes, + ref NativeArray parentIndices, // transform - [Unity.Collections.ReadOnly] - public NativeArray transformPositionArray; - [Unity.Collections.ReadOnly] - public NativeArray transformRotationArray; - [Unity.Collections.ReadOnly] - public NativeArray transformScaleArray; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray transformLocalPositionArray; - [NativeDisableParallelForRestriction] - [Unity.Collections.WriteOnly] - public NativeArray transformLocalRotationArray; - - // Transformパーティクルごと - public void Execute(int index) + ref NativeArray transformPositionArray, + ref NativeArray transformRotationArray, + ref NativeArray transformScaleArray, + ref NativeArray transformLocalPositionArray, + ref NativeArray transformLocalRotationArray + ) + { + // Transformパーティクル + if (tdata.proxyMeshType == VirtualMesh.MeshType.ProxyBoneMesh) { - int vindex = jobVertexIndexList[index]; - int teamId = teamIds[vindex]; - if (teamId == 0) - return; - var tdata = teamDataArray[teamId]; + // Transformパーティクルは親からのローカル姿勢を計算してTransformData情報に書き込む + int vindex = tdata.proxyCommonChunk.startIndex; + //vindex = tdata.proxyCommonChunk.startIndex + chunk.startIndex; + for (int k = 0; k < tdata.proxyCommonChunk.dataLength; k++, vindex++) + //for (int k = 0; k < chunk.dataLength; k++, vindex++) + { + int parentIndex = parentIndices[vindex]; + if (parentIndex < 0) + continue; - int l_vindex = vindex - tdata.proxyCommonChunk.startIndex; + var attr = attributes[vindex]; + if (attr.IsMove() == false) + continue; - int parentIndex = vertexParentIndices[vindex]; - if (parentIndex < 0) - return; + // 親からのローカル姿勢を計算しトランスフォーム情報に書き込む + int tindex = tdata.proxyTransformChunk.startIndex + k; + //int tindex = tdata.proxyTransformChunk.startIndex + chunk.startIndex + k; + int ptindex = tdata.proxyTransformChunk.startIndex + parentIndex; + var ppos = transformPositionArray[ptindex]; + var prot = transformRotationArray[ptindex]; + var pscl = transformScaleArray[ptindex]; + var pos = transformPositionArray[tindex]; + var rot = transformRotationArray[tindex]; - var attr = attributes[vindex]; - if (attr.IsMove() == false) - return; +#if true + var iprot = math.inverse(prot); + var v = pos - ppos; + var lpos = math.mul(iprot, v); - // 親からのローカル姿勢を計算しトランスフォーム情報に書き込む - int tindex = tdata.proxyTransformChunk.startIndex + l_vindex; - int ptindex = tdata.proxyTransformChunk.startIndex + parentIndex; - var ppos = transformPositionArray[ptindex]; - var prot = transformRotationArray[ptindex]; - var pscl = transformScaleArray[ptindex]; - var pos = transformPositionArray[tindex]; - var rot = transformRotationArray[tindex]; + //Develop.Assert(pscl.x > 0.0f && pscl.y > 0.0f && pscl.z > 0.0f); + lpos /= pscl; + var lrot = math.mul(iprot, rot); +#endif - var iprot = math.inverse(prot); - var v = pos - ppos; - var lpos = math.mul(iprot, v); + // マイナススケール + lrot = lrot.value * tdata.negativeScaleQuaternionValue; - Develop.Assert(pscl.x > 0.0f && pscl.y > 0.0f && pscl.z > 0.0f); - lpos /= pscl; - var lrot = math.mul(iprot, rot); - - // todo:マイナススケール対応 - - transformLocalPositionArray[tindex] = lpos; - transformLocalRotationArray[tindex] = lrot; + transformLocalPositionArray[tindex] = lpos; + transformLocalRotationArray[tindex] = lrot; + } } } - //========================================================================================= /// - /// マッピングメッシュの頂点姿勢を連動するプロキシメッシュから頂点スキニングして求める + /// マッピングメッシュの頂点姿勢を連動するプロキシメッシュからスキニングして求める /// - /// - /// - internal JobHandle PostMappingMeshUpdate(JobHandle jobHandle) + internal JobHandle PostMappingMeshUpdateBatchSchedule(JobHandle jobHandle, int workerCount) { if (MagicaManager.Team.MappingCount == 0) return jobHandle; var tm = MagicaManager.Team; var bm = MagicaManager.Bone; + var rm = MagicaManager.Render; - // マッピングメッシュとプロキシメッシュの座標変換マトリックスを求める - var calcMeshConvertJob = new CalcMeshConvertMatrixJob() + // マッピングメッシュの変換マトリックスを求める + var calcMeshConvert_A_Job = new CalcMeshConvert_A_Job() { - mappingDataArray = tm.mappingDataArray.GetNativeArray(), - + // team teamDataArray = tm.teamDataArray.GetNativeArray(), - + // transform transformPositionArray = bm.positionArray.GetNativeArray(), transformRotationArray = bm.rotationArray.GetNativeArray(), transformScaleArray = bm.scaleArray.GetNativeArray(), - transformInverseRotationArray = bm.inverseRotationArray.GetNativeArray(), - }; - jobHandle = calcMeshConvertJob.Schedule(tm.MappingCount, 1, jobHandle); - - // プロキシスキニングの実行 - // (マッピングメッシュのローカル座標空間) - // todo:カリングを考えてバッファにすべきかも - var calcProxySkinningJob = new CalcProxySkinningJob() - { - teamDataArray = tm.teamDataArray.GetNativeArray(), - + // mapping mappingDataArray = tm.mappingDataArray.GetNativeArray(), + // render mesh + renderDataWorkArray = rm.renderDataWorkArray.GetNativeArray(), + }; + jobHandle = calcMeshConvert_A_Job.Schedule(tm.MappingCount, 1, jobHandle); - mappingIdArray = mappingIdArray.GetNativeArray(), + // マッピングメッシュの頂点姿勢をプロキシメッシュから逆スキニングして求める + // マッピングメッシュの頂点姿勢を書き込み用バッファに書き込む + // 必要があればボーンウエイトも書き込む + var calcMeshConvert_B_Job = new CalcMeshConvert_B_Job() + { + workerCount = workerCount, + // team + teamDataArray = tm.teamDataArray.GetNativeArray(), + // mapping + mappingDataArray = tm.mappingDataArray.GetNativeArray(), + //mappingIdArray = mappingIdArray.GetNativeArray(), mappingAttributes = mappingAttributes.GetNativeArray(), mappingLocalPositions = mappingLocalPositins.GetNativeArray(), mappingLocalNormals = mappingLocalNormals.GetNativeArray(), - //mappingLocalTangents = mappingLocalTangents.GetNativeArray(), + mappingLocalTangents = mappingLocalTangents.GetNativeArray(), mappingBoneWeights = mappingBoneWeights.GetNativeArray(), +#if MC2_DEBUG mappingPositions = mappingPositions.GetNativeArray(), - mappingNormals = mappingNormals.GetNativeArray(), - + //mappingNormals = mappingNormals.GetNativeArray(), + //mappingTangents = mappingTangents.GetNativeArray(), +#endif + mappingReferenceIndices = mappingReferenceIndices.GetNativeArray(), + // proxy proxyPositions = positions.GetNativeArray(), proxyRotations = rotations.GetNativeArray(), proxyVertexBindPosePositions = vertexBindPosePositions.GetNativeArray(), proxyVertexBindPoseRotations = vertexBindPoseRotations.GetNativeArray(), + // render mesh + renderDataWorkArray = rm.renderDataWorkArray.GetNativeArray(), + renderMeshPositions = rm.renderMeshPositions.GetNativeArray(), + renderMeshNormals = rm.renderMeshNormals.GetNativeArray(), + renderMeshTangents = rm.renderMeshTangents.GetNativeArray(), + renderMeshBoneWeights = rm.renderMeshBoneWeights.GetNativeArray(), }; - jobHandle = calcProxySkinningJob.Schedule(MappingVertexCount, 32, jobHandle); + jobHandle = calcMeshConvert_B_Job.Schedule(tm.MappingCount * workerCount, 1, jobHandle); + + // レンダーメッシュデータの後処理 + var postRenderDataJob = new PostRenderMeshWorkDataBatchJob() + { + // render mesh + renderDataWorkArray = rm.renderDataWorkArray.GetNativeArray(), + // mapping data + mappingDataArray = tm.mappingDataArray.GetNativeArray(), + }; + jobHandle = postRenderDataJob.Schedule(rm.RenderDataWorkCount, 8, jobHandle); return jobHandle; } /// - /// // マッピングメッシュとプロキシメッシュの座標変換マトリックスを求める + /// プロキシメッシュからマッピングメッシュへの変換マトリックスを求める /// [BurstCompile] - struct CalcMeshConvertMatrixJob : IJobParallelFor + struct CalcMeshConvert_A_Job : IJobParallelFor { - public NativeArray mappingDataArray; - // team [Unity.Collections.ReadOnly] public NativeArray teamDataArray; @@ -1804,8 +1263,13 @@ namespace MagicaCloth2 public NativeArray transformRotationArray; [Unity.Collections.ReadOnly] public NativeArray transformScaleArray; + + // mapping + public NativeArray mappingDataArray; + + // render mesh [Unity.Collections.ReadOnly] - public NativeArray transformInverseRotationArray; + public NativeArray renderDataWorkArray; // マッピングメッシュごと public void Execute(int index) @@ -1815,74 +1279,94 @@ namespace MagicaCloth2 return; var tdata = teamDataArray[mdata.teamId]; - if (tdata.IsEnable == false) - return; - if (tdata.IsCullingInvisible) + if (tdata.IsProcess == false) return; - // mapping - var pos = transformPositionArray[mdata.centerTransformIndex]; - var rot = transformRotationArray[mdata.centerTransformIndex]; - var scl = transformScaleArray[mdata.centerTransformIndex]; - var irot = transformInverseRotationArray[mdata.centerTransformIndex]; + // RenderMeshWorkData + var wdata = renderDataWorkArray[mdata.renderDataWorkIndex]; + if (wdata.UseCustomMesh == false) + return; - // proxy - var ppos = transformPositionArray[tdata.centerTransformIndex]; - var prot = transformRotationArray[tdata.centerTransformIndex]; - var pscl = transformScaleArray[tdata.centerTransformIndex]; + //======================================================================= + // ■マッピングメッシュとプロキシメッシュの座標変換マトリックスを求める + { + // mapping + var pos = transformPositionArray[mdata.centerTransformIndex]; + var rot = transformRotationArray[mdata.centerTransformIndex]; + var scl = transformScaleArray[mdata.centerTransformIndex]; + var irot = math.inverse(rot); - // プロキシメッシュとマッピングメッシュの座標空間が等しいか判定 - bool sameSpace = MathUtility.CompareTransform(pos, rot, scl, ppos, prot, pscl); - mdata.sameSpace = sameSpace; - //Debug.Log($"sameSpace:{sameSpace}, scl:{scl}, pscl:{pscl}"); + // proxy + var ppos = transformPositionArray[tdata.centerTransformIndex]; + var prot = transformRotationArray[tdata.centerTransformIndex]; + var pscl = transformScaleArray[tdata.centerTransformIndex]; - // ワールド空間からマッピングメッシュへの座標空間変換 - mdata.toMappingMatrix = math.inverse(MathUtility.LocalToWorldMatrix(pos, rot, scl)); - mdata.toMappingRotation = irot; + // プロキシメッシュとマッピングメッシュの座標空間が等しいか判定 + bool sameSpace = MathUtility.CompareTransform(pos, rot, scl, ppos, prot, pscl); + mdata.sameSpace = sameSpace; + //Debug.Log($"sameSpace:{sameSpace}, scl:{scl}, pscl:{pscl}"); - // マッピングメッシュ用のスケール比率 - // チームのステップ実行とは無関係に毎フレーム適用する必要があるためチームスケール比率と分離する - var initScaleLength = math.length(tdata.initScale); - Develop.Assert(initScaleLength > 0.0f); - mdata.scaleRatio = math.length(pscl) / initScaleLength; + // ワールド空間からマッピングメッシュへの座標空間変換 + mdata.toMappingMatrix = math.inverse(MathUtility.LocalToWorldMatrix(pos, rot, scl)); + mdata.toMappingRotation = irot; + // マッピングメッシュ用のスケール比率 + // チームのステップ実行とは無関係に毎フレーム適用する必要があるためチームスケール比率と分離する + var initScaleLength = math.length(tdata.initScale); + Develop.Assert(initScaleLength > 0.0f); + mdata.scaleRatio = math.length(pscl) / initScaleLength; + } + + //======================================================================= + // ■マッピングメッシュメッシュ頂点姿勢をプロキシメッシュから逆スキニングして求める + // 接線の有無 + bool useTangent = tdata.IsTangent; + // ボーンウエイトの書き込み + bool modifyBoneWeight = wdata.HasBoneWeight && mdata.flag.IsSet(TeamManager.MappingDataFlag_ModifyBoneWeight); + + //======================================================================= + // ■結果格納 + mdata.flag.SetBits(TeamManager.MappingDataFlag_ChangePositionNormal, true); + mdata.flag.SetBits(TeamManager.MappingDataFlag_ChangeTangent, useTangent); + mdata.flag.SetBits(TeamManager.MappingDataFlag_ChangeBoneWeight, modifyBoneWeight); mappingDataArray[index] = mdata; - - //Debug.Log($"Mapping [{mdata.teamId}] sclRatio:{tdata.scaleRatio}"); } } /// - /// プロキシメッシュからマッピングメッシュの頂点の座標・法線・接線をスキニングして計算する + /// マッピングメッシュの頂点姿勢をプロキシメッシュから逆スキニングして求める + /// マッピングメッシュの頂点姿勢を書き込み用バッファに書き込む + /// 必要があればボーンウエイトも書き込む /// [BurstCompile] - struct CalcProxySkinningJob : IJobParallelFor + struct CalcMeshConvert_B_Job : IJobParallelFor { + public int workerCount; + // team [Unity.Collections.ReadOnly] public NativeArray teamDataArray; - // mapping data + // mapping [Unity.Collections.ReadOnly] public NativeArray mappingDataArray; - - // mapping mesh - [Unity.Collections.ReadOnly] - public NativeArray mappingIdArray; [Unity.Collections.ReadOnly] public NativeArray mappingAttributes; [Unity.Collections.ReadOnly] public NativeArray mappingLocalPositions; [Unity.Collections.ReadOnly] public NativeArray mappingLocalNormals; - //[Unity.Collections.ReadOnly] - //public NativeArray mappingLocalTangents; + [Unity.Collections.ReadOnly] + public NativeArray mappingLocalTangents; [Unity.Collections.ReadOnly] public NativeArray mappingBoneWeights; +#if MC2_DEBUG + [NativeDisableParallelForRestriction] [Unity.Collections.WriteOnly] public NativeArray mappingPositions; - [Unity.Collections.WriteOnly] - public NativeArray mappingNormals; +#endif + [Unity.Collections.ReadOnly] + public NativeArray mappingReferenceIndices; // proxy mesh [Unity.Collections.ReadOnly] @@ -1894,98 +1378,227 @@ namespace MagicaCloth2 [Unity.Collections.ReadOnly] public NativeArray proxyVertexBindPoseRotations; - // マッピングメッシュ頂点ごと - public void Execute(int mvindex) + // render mesh + [Unity.Collections.ReadOnly] + public NativeArray renderDataWorkArray; + [NativeDisableParallelForRestriction] + [Unity.Collections.WriteOnly] + public NativeArray renderMeshPositions; + [NativeDisableParallelForRestriction] + [Unity.Collections.WriteOnly] + public NativeArray renderMeshNormals; + [NativeDisableParallelForRestriction] + public NativeArray renderMeshTangents; + [NativeDisableParallelForRestriction] + [Unity.Collections.WriteOnly] + public NativeArray renderMeshBoneWeights; + + // マッピングメッシュごと + public void Execute(int dataIndex) { - int mindex = mappingIdArray[mvindex]; - if (mindex == 0) - return; + // チームIDとワーカーID + int localIndex = dataIndex / workerCount; + int workerIndex = dataIndex % workerCount; - // (+1)されているので1引く - mindex--; - - var mdata = mappingDataArray[mindex]; + var mdata = mappingDataArray[localIndex]; if (mdata.IsValid() == false) return; - // team var tdata = teamDataArray[mdata.teamId]; - if (tdata.IsEnable == false) - return; - if (tdata.IsCullingInvisible) + if (tdata.IsProcess == false) return; - // 無効頂点は無視する - var attr = mappingAttributes[mvindex]; - if (attr.IsInvalid()) + // RenderMeshWorkData + var wdata = renderDataWorkArray[mdata.renderDataWorkIndex]; + if (wdata.UseCustomMesh == false) return; - // 固定も無視する(todo:一旦こうする) - if (attr.IsFixed()) + // 範囲 + var chunk = MathUtility.GetWorkerChunk(mdata.mappingCommonChunk.dataLength, workerCount, workerIndex); + if (chunk.IsValid == false) return; - // マッピングメッシュ姿勢 - float3 lpos = mappingLocalPositions[mvindex]; - float3 lnor = mappingLocalNormals[mvindex]; - //float3 ltan = mappingLocalTangents[mvindex]; - - // プロキシメッシュの座標空間に変換する - if (mdata.sameSpace == false) - { - // 現在の姿勢ではなくマッピング時の姿勢で変換を行う - lpos = math.transform(mdata.toProxyMatrix, lpos); - lnor = math.mul(mdata.toProxyRotation, lnor); - //ltan = math.mul(mdata.toProxyRotation, ltan); - } - - // 以降計算はすべてプロキシメッシュのローカル空間で行う - var bw = mappingBoneWeights[mvindex]; - int wcnt = bw.Count; - float3 opos = 0; - float3 onor = 0; - //float3 otan = 0; + //======================================================================= + // ■マッピングメッシュメッシュ頂点姿勢をプロキシメッシュから逆スキニングして求める + // 接線の有無 + bool useTangent = tdata.IsTangent; + // マイナススケール + float4 negativeScl = new float4(tdata.negativeScaleDirection, 1); // ProxyMeshスケール - float3 pscl = tdata.initScale * mdata.scaleRatio; // 初期スケール x 現在のスケール比率 - for (int i = 0; i < wcnt; i++) + float3 proxyScl = tdata.initScale * mdata.scaleRatio; // 初期スケール x 現在のスケール比率 + // ボーンウエイトの書き込み + bool modifyBoneWeight = wdata.HasBoneWeight && mdata.flag.IsSet(TeamManager.MappingDataFlag_ModifyBoneWeight); + + //int mvindex = mdata.mappingCommonChunk.startIndex; + int mvindex = mdata.mappingCommonChunk.startIndex + chunk.startIndex; + //for (int k = 0; k < mdata.mappingCommonChunk.dataLength; k++, mvindex++) + for (int k = 0; k < chunk.dataLength; k++, mvindex++) { - float w = bw.weights[i]; + // 無効頂点は無視する + var attr = mappingAttributes[mvindex]; + if (attr.IsInvalid()) + continue; - int tvindex = bw.boneIndices[i] + tdata.proxyCommonChunk.startIndex; + // 固定も書き込まない + if (attr.IsFixed()) + continue; - // バインドポーズの逆座標と逆回転 - float3 bipos = proxyVertexBindPosePositions[tvindex]; - quaternion birot = proxyVertexBindPoseRotations[tvindex]; + // マッピングメッシュ姿勢 + float4x3 _pose = 0; + _pose.c0 = new float4(mappingLocalPositions[mvindex], 1); + _pose.c1 = new float4(mappingLocalNormals[mvindex], 0); + _pose.c2 = math.select(0, new float4(mappingLocalTangents[mvindex], 0), useTangent); - float3 pos = math.mul(birot, lpos + bipos); - float3 nor = math.mul(birot, lnor); - //float3 tan = math.mul(birot, ltan); + // プロキシメッシュの座標空間に変換する + if (mdata.sameSpace == false) + { + // 現在の姿勢ではなくマッピング時の姿勢で変換を行う + _pose = math.mul(mdata.toProxyMatrix, _pose); + } - float3 ppos = proxyPositions[tvindex]; - quaternion prot = proxyRotations[tvindex]; + // マイナススケール + _pose *= new float4x3(negativeScl, negativeScl, negativeScl); - // ワールド変換 - pos = math.mul(prot, pos * pscl) + ppos; - nor = math.mul(prot, nor); - //tan = math.mul(prot, tan); + // 以降計算はすべてプロキシメッシュのローカル空間で行う + var bw = mappingBoneWeights[mvindex]; + int wcnt = bw.Count; + float4x3 _opose = 0; + // ProxyMeshスケール + for (int i = 0; i < wcnt; i++) + { + float w = bw.weights[i]; - opos += pos.xyz * w; - onor += nor.xyz * w; - //otan += tan.xyz * w; + int tvindex = bw.boneIndices[i] + tdata.proxyCommonChunk.startIndex; + + // バインドポーズの逆座標と逆回転 + float3 bipos = proxyVertexBindPosePositions[tvindex]; + quaternion birot = proxyVertexBindPoseRotations[tvindex]; + + // マイナススケール + bipos *= tdata.negativeScaleDirection; + birot = birot.value * tdata.negativeScaleQuaternionValue; + + // quaternionからmatrixへの変換が重いのでここはそのまま + float3 pos = math.mul(birot, _pose.c0.xyz + bipos); + float3 nor = math.mul(birot, _pose.c1.xyz); + float3 tan = math.mul(birot, _pose.c2.xyz); + + float3 ppos = proxyPositions[tvindex]; + quaternion prot = proxyRotations[tvindex]; + + // ワールド変換 + // quaternionからmatrixへの変換が重いのでここはそのまま + pos = math.mul(prot, pos * proxyScl) + ppos; + nor = math.mul(prot, nor); + tan = math.mul(prot, tan); + + // ウエイト + _opose.c0.xyz += pos * w; + _opose.c1.xyz += nor * w; + _opose.c2.xyz += tan * w; + } + + // ここまでのopos/orotはワールド空間 + // マッピングメッシュのローカル空間に変換する + _opose.c0.w = 1; + _opose = math.mul(mdata.toMappingMatrix, _opose); + +#if MC2_DEBUG + + // 結果格納 + mappingPositions[mvindex] = _opose.c0.xyz; + //mappingNormals[mvindex] = math.normalize(_opose.c1.xyz); + //if (useTangent) + // mappingTangents[mvindex] = math.normalize(_opose.c2.xyz); +#endif +#if true + // ■結果格納 + // 書き込む頂点インデックス + int buffIndex = mappingReferenceIndices[mvindex]; + + // positoins / normals + int windex = wdata.renderMeshPositionAndNormalChunk.startIndex + buffIndex; + renderMeshPositions[windex] = _opose.c0.xyz; + renderMeshNormals[windex] = math.normalize(_opose.c1.xyz); + + // tangents + if (useTangent) + { + windex = wdata.renderMeshTangentChunk.startIndex + buffIndex; + float4 tan = renderMeshTangents[windex]; + renderMeshTangents[windex] = new float4(math.normalize(_opose.c2.xyz), tan.w); + } +#endif + // bone weights + if (modifyBoneWeight) + { + // 使用頂点のウエイトはcenterTransform100%で書き込む + windex = wdata.renderMeshBoneWeightChunk.startIndex + buffIndex; + renderMeshBoneWeights[windex] = wdata.centerBoneWeight; + } + } + //Debug.Log($"[{index}] renderMeshPositions:start={mdata.renderMeshPositionAndNormalChunk.startIndex}, length={mdata.renderMeshPositionAndNormalChunk.dataLength}"); + } + } + + /// + /// レンダーメッシュデータの後処理 + /// + [BurstCompile] + struct PostRenderMeshWorkDataBatchJob : IJobParallelFor + { + // render mesh + public NativeArray renderDataWorkArray; + + // mapping + [NativeDisableParallelForRestriction] + public NativeArray mappingDataArray; + + // RenderDataWorkごと + public void Execute(int windex) + { + var wdata = renderDataWorkArray[windex]; + if (wdata.IsValid() == false) + return; + if (wdata.UseCustomMesh == false) + return; + + // 各種書き込みフラグを設定する + bool changePositionNormal = false; + bool changeTangent = false; + bool changeBoneWeight = false; + int mcnt = wdata.mappingDataIndexList.Length; + for (int k = 0; k < mcnt; k++) + { + int mindex = wdata.mappingDataIndexList[k]; + var mdata = mappingDataArray[mindex]; + + if (mdata.flag.IsSet(TeamManager.MappingDataFlag_ChangePositionNormal)) + { + changePositionNormal = true; + mdata.flag.SetBits(TeamManager.MappingDataFlag_ChangePositionNormal, false); + } + if (mdata.flag.IsSet(TeamManager.MappingDataFlag_ChangeTangent)) + { + changeTangent = true; + mdata.flag.SetBits(TeamManager.MappingDataFlag_ChangeTangent, false); + } + if (mdata.flag.IsSet(TeamManager.MappingDataFlag_ChangeBoneWeight)) + { + changeBoneWeight = true; + mdata.flag.SetBits(TeamManager.MappingDataFlag_ChangeBoneWeight, false); + mdata.flag.SetBits(TeamManager.MappingDataFlag_ModifyBoneWeight, false); // Modifyフラグも消す + } + + mappingDataArray[mindex] = mdata; } - // 単位化しないと駄目な状況が発生。仕方なし。 - //onor = math.normalize(onor); - //otan = math.normalize(otan); + // 書き込みフラグ設定 + wdata.flag.SetBits(RenderManager.RenderDataFlag_WritePositionNormal, changePositionNormal); + wdata.flag.SetBits(RenderManager.RenderDataFlag_WriteTangent, changeTangent); + wdata.flag.SetBits(RenderManager.RenderDataFlag_WriteBoneWeight, changeBoneWeight); - // ここまでのopos/orotはワールド空間 - // マッピングメッシュのローカル空間に変換する - opos = math.transform(mdata.toMappingMatrix, opos); - //onor = MathUtility.TransformDirection(onor, mdata.toMappingMatrix); - onor = math.normalize(MathUtility.TransformVector(onor, mdata.toMappingMatrix)); - - // 格納 - mappingPositions[mvindex] = opos; - mappingNormals[mvindex] = onor; + renderDataWorkArray[windex] = wdata; } } @@ -2001,11 +1614,11 @@ namespace MagicaCloth2 else { sb.AppendLine($"VirtualMesh Manager."); - sb.AppendLine($" -VertexCount:{VertexCount}"); - sb.AppendLine($" -EdgeCount:{EdgeCount}"); - sb.AppendLine($" -TriangleCount:{TriangleCount}"); - sb.AppendLine($" -BaseLineCount:{BaseLineCount}"); - sb.AppendLine($" -MeshClothVertexCount:{MeshClothVertexCount}"); + sb.AppendLine($" -ProxyVertexCount:{ProxyVertexCount}"); + sb.AppendLine($" -ProxyEdgeCount:{ProxyEdgeCount}"); + sb.AppendLine($" -ProxyTriangleCount:{ProxyTriangleCount}"); + sb.AppendLine($" -ProxyBaseLineCount:{ProxyBaseLineCount}"); + sb.AppendLine($" -ProxyLocalPositionCount:{ProxyLocalPositionCount}"); sb.AppendLine($" [ProxyMesh]"); sb.AppendLine($" -teamIds:{teamIds.ToSummary()}"); @@ -2058,8 +1671,13 @@ namespace MagicaCloth2 sb.AppendLine($" -mappingLocalPositins:{mappingLocalPositins.ToSummary()}"); sb.AppendLine($" -mappingLocalNormals:{mappingLocalNormals.ToSummary()}"); sb.AppendLine($" -mappingBoneWeights:{mappingBoneWeights.ToSummary()}"); - sb.AppendLine($" -mappingPositions:{mappingPositions.ToSummary()}"); - sb.AppendLine($" -mappingNormals:{mappingNormals.ToSummary()}"); + //sb.AppendLine($" -mappingPositions:{mappingPositions.ToSummary()}"); + //sb.AppendLine($" -mappingNormals:{mappingNormals.ToSummary()}"); + + //sb.AppendLine($" [RenderMeshBuffer]"); + //sb.AppendLine($" -renderMeshPositions:{renderMeshPositions.ToSummary()}"); + //sb.AppendLine($" -renderMeshNormals:{renderMeshNormals.ToSummary()}"); + //sb.AppendLine($" -renderMeshTangents:{renderMeshTangents.ToSummary()}"); } sb.AppendLine(); Debug.Log(sb.ToString()); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Manager/VirtualMesh/VirtualMeshManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Manager/VirtualMesh/VirtualMeshManager.cs.meta index eaebf426..2138e314 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Manager/VirtualMesh/VirtualMeshManager.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Manager/VirtualMesh/VirtualMeshManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Manager/VirtualMesh/VirtualMeshManager.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild.meta b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild.meta new file mode 100644 index 00000000..d9315f58 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1f85ba9270154ec4ea99adc777266a0f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs new file mode 100644 index 00000000..99c105ca --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs @@ -0,0 +1,64 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System.Collections.Generic; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// PreBuildの保存アセットデータ + /// + [CreateAssetMenu(fileName = "Data", menuName = "MagicaCloth2/PreBuildScriptableObject")] + public class PreBuildScriptableObject : ScriptableObject + { + /// + /// 複数のPreBuildデータを格納可能 + /// + public List sharePreBuildDataList = new List(); + + //========================================================================================= + public bool HasPreBuildData(string buildId) + { + return GetPreBuildData(buildId) != null; + } + + public SharePreBuildData GetPreBuildData(string buildId) + { + foreach (var sdata in sharePreBuildDataList) + { + if (sdata.CheckBuildId(buildId)) + return sdata; + } + + return null; + } + + public void AddPreBuildData(SharePreBuildData sdata) + { + int index = sharePreBuildDataList.FindIndex(x => x.buildId == sdata.buildId); + if (index >= 0) + sharePreBuildDataList[index] = sdata; + else + sharePreBuildDataList.Add(sdata); + } + + //========================================================================================= + /// + /// すべてのPreBuildデータをデシリアライズしてマネージャに登録します + /// この処理は負荷が高いため事前に実行しておくことでクロスデータ利用時の負荷を軽減できます + /// Deserialize all PreBuild data and register it with the manager. + /// This process requires a high load, so running it in advance can reduce the load when using cross data. + /// + public void Warmup() + { + if (Application.isPlaying == false) + return; + + sharePreBuildDataList.ForEach(sdata => + { + MagicaManager.PreBuild.RegisterPreBuildData(sdata, false); + }); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs.meta new file mode 100644 index 00000000..086982be --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 45b12b58fd27b9a4bae4f50db55b4459 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildScriptableObject.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs new file mode 100644 index 00000000..78f76562 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs @@ -0,0 +1,101 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// PreBuildの保存データ + /// + [System.Serializable] + public class PreBuildSerializeData : ITransform + { + /// + /// 有効状態 + /// Valid state. + /// + public bool enabled = false; + + /// + /// ビルド識別ID + /// + public string buildId; + + /// + /// ビルドデータの共有部分 + /// このデータは複数のインスタンスで共有されるためScriptableObjectとして外部アセットとして保存される + /// + public PreBuildScriptableObject preBuildScriptableObject = null; + + /// + /// ビルドデータの固有部分 + /// このデータはインスタンスごとに固有となる + /// + public UniquePreBuildData uniquePreBuildData; + + //========================================================================================= + /// + /// PreBuild利用の有無 + /// + /// + public bool UsePreBuild() => enabled; + + /// + /// PreBuildデータの検証 + /// + /// + public ResultCode DataValidate() + { + if (uniquePreBuildData == null) + return new ResultCode(Define.Result.PreBuildData_Empty); + + var preBuildData = GetSharePreBuildData(); + if (preBuildData == null) + return new ResultCode(Define.Result.PreBuildData_Empty); + + var result = preBuildData.DataValidate(); + if (result.IsFaild()) + return result; + + result = uniquePreBuildData.DataValidate(); + if (result.IsFaild()) + return result; + + return ResultCode.Success; + } + + public SharePreBuildData GetSharePreBuildData() + { + if (preBuildScriptableObject == null) + return null; + + if (string.IsNullOrEmpty(buildId)) + return null; + + return preBuildScriptableObject.GetPreBuildData(buildId); ; + } + + /// + /// ビルドIDを生成する(英数字8文字) + /// + /// + public static string GenerateBuildID() + { + Guid g = Guid.NewGuid(); + return g.ToString().Substring(0, 8); + } + + public void GetUsedTransform(HashSet transformSet) + { + uniquePreBuildData.GetUsedTransform(transformSet); + } + + public void ReplaceTransform(Dictionary replaceDict) + { + uniquePreBuildData.ReplaceTransform(replaceDict); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs.meta new file mode 100644 index 00000000..3ca0db55 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 5c7522d5a2a34f84c9588683c5574fa9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/PreBuild/PreBuildSerializeData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs new file mode 100644 index 00000000..c8cc0326 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs @@ -0,0 +1,69 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System.Collections.Generic; +using System.Text; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// PreBuildデータの共有部分 + /// + [System.Serializable] + public class SharePreBuildData + { + public int version; + public string buildId; + public ResultCode buildResult; + public Vector3 buildScale; + + public List renderSetupDataList = new List(); + + public VirtualMesh.ShareSerializationData proxyMesh; + public List renderMeshList = new List(); + + public DistanceConstraint.ConstraintData distanceConstraintData; + public TriangleBendingConstraint.ConstraintData bendingConstraintData; + public InertiaConstraint.ConstraintData inertiaConstraintData; + + //========================================================================================= + public ResultCode DataValidate() + { + if (version != Define.System.LatestPreBuildVersion) + return new ResultCode(Define.Result.PreBuildData_VersionMismatch); + + if (buildScale.x < Define.System.Epsilon) + return new ResultCode(Define.Result.PreBuildData_InvalidScale); + + if (buildResult.IsFaild()) + return buildResult; + + return ResultCode.Success; + } + + public bool CheckBuildId(string buildId) + { + if (string.IsNullOrEmpty(buildId)) + return false; + + return this.buildId == buildId; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(1024); + + sb.AppendLine("<<<<< PreBuildData >>>>>"); + sb.AppendLine($"Version:{version}"); + sb.AppendLine($"BuildID:{buildId}"); + sb.AppendLine($"BuildResult:{buildResult.GetResultString()}"); + sb.AppendLine($"BuildScale:{buildScale}"); + sb.AppendLine(proxyMesh.ToString()); + sb.AppendLine($"renderMeshList:{renderMeshList.Count}"); + sb.AppendLine($"renderSetupDataList:{renderSetupDataList.Count}"); + + return sb.ToString(); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs.meta new file mode 100644 index 00000000..cd541ad0 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 280185e34f035f44d999fc83fffe8ab9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/PreBuild/SharePreBuildData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs new file mode 100644 index 00000000..af90e07c --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs @@ -0,0 +1,49 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System.Collections.Generic; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// PreBuildデータの固有部分 + /// + [System.Serializable] + public class UniquePreBuildData : ITransform + { + public int version; + public ResultCode buildResult; + + public List renderSetupDataList = new List(); + + public VirtualMesh.UniqueSerializationData proxyMesh; + public List renderMeshList = new List(); + + //========================================================================================= + public ResultCode DataValidate() + { + if (version != Define.System.LatestPreBuildVersion) + return new ResultCode(Define.Result.PreBuildData_VersionMismatch); + + if (buildResult.IsFaild()) + return buildResult; + + return ResultCode.Success; + } + + public void GetUsedTransform(HashSet transformSet) + { + renderSetupDataList.ForEach(x => x?.GetUsedTransform(transformSet)); + proxyMesh?.GetUsedTransform(transformSet); + renderMeshList.ForEach(x => x?.GetUsedTransform(transformSet)); + } + + public void ReplaceTransform(Dictionary replaceDict) + { + renderSetupDataList.ForEach(x => x?.ReplaceTransform(replaceDict)); + proxyMesh?.ReplaceTransform(replaceDict); + renderMeshList.ForEach(x => x?.ReplaceTransform(replaceDict)); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs.meta new file mode 100644 index 00000000..83f0af1a --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 0cee094d81395864ba3ef342016a8de6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/PreBuild/UniquePreBuildData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/ReductionSettings.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/ReductionSettings.cs.meta index 3178778c..357c0aa2 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/ReductionSettings.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/ReductionSettings.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Reduction/ReductionSettings.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/ReductionWorkData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/ReductionWorkData.cs.meta index f8c2f0c7..45ffd984 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/ReductionWorkData.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/ReductionWorkData.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Reduction/ReductionWorkData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/SameDistanceReduction.cs b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/SameDistanceReduction.cs index e035d3ff..81bb4ad1 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/SameDistanceReduction.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/SameDistanceReduction.cs @@ -26,7 +26,8 @@ namespace MagicaCloth2 //========================================================================================= GridMap gridMap; - NativeParallelHashSet joinPairSet; + //NativeParallelHashSet joinPairSet; + NativeParallelMultiHashMap joinPairMap; NativeReference resultRef; //========================================================================================= @@ -48,8 +49,10 @@ namespace MagicaCloth2 public virtual void Dispose() { - if (joinPairSet.IsCreated) - joinPairSet.Dispose(); + //if (joinPairSet.IsCreated) + // joinPairSet.Dispose(); + if (joinPairMap.IsCreated) + joinPairMap.Dispose(); if (resultRef.IsCreated) resultRef.Dispose(); gridMap?.Dispose(); @@ -77,7 +80,8 @@ namespace MagicaCloth2 // 頂点ごとの接続マップ // インデックスが若い方が記録する - joinPairSet = new NativeParallelHashSet(vmesh.VertexCount / 4, Allocator.Persistent); + //joinPairSet = new NativeParallelHashSet(vmesh.VertexCount / 4, Allocator.Persistent); + joinPairMap = new NativeParallelMultiHashMap(vmesh.VertexCount, Allocator.Persistent); resultRef = new NativeReference(Allocator.Persistent); // ポイントをグリッドに登録 @@ -100,14 +104,18 @@ namespace MagicaCloth2 localPositions = vmesh.localPositions.GetNativeArray(), joinIndices = workData.vertexJoinIndices, gridMap = gridMap.GetMultiHashMap(), - joinPairSet = joinPairSet, + //joinPairSet = joinPairSet, + joinPairMap = joinPairMap, }; searchJoinJob.Run(); // 結合する +#if false var joinJob = new JoinJob() { - joinPairSet = joinPairSet, + vertexCount = vmesh.VertexCount, + //joinPairSet = joinPairSet, + joinPairMap = joinPairMap, joinIndices = workData.vertexJoinIndices, vertexToVertexMap = workData.vertexToVertexMap, boneWeights = vmesh.boneWeights.GetNativeArray(), @@ -115,6 +123,25 @@ namespace MagicaCloth2 result = resultRef, }; joinJob.Run(); +#endif +#if true + // 高速化および詳細メッシュがある場合に1つの頂点に大量に結合しオーバーフローが発生する問題を回避したもの + // 以前はA->B->C結合時にA->C間が接続距離以上でもA->Cが結合されてしまったが、この改良版ではそれがおこならない + // そのため以前とは結果がことなることに注意! + using var tempList = new NativeList(2048, Allocator.Persistent); + var joinJob2 = new JoinJob2() + { + vertexCount = vmesh.VertexCount, + joinPairMap = joinPairMap, + joinIndices = workData.vertexJoinIndices, + vertexToVertexMap = workData.vertexToVertexMap, + boneWeights = vmesh.boneWeights.GetNativeArray(), + attributes = vmesh.attributes.GetNativeArray(), + result = resultRef, + tempList = tempList, + }; + joinJob2.Run(); +#endif // 頂点の接続状態を最新に更新する。すべて最新の生存ポイントを指すように変更する UpdateJoinAndLink(); @@ -191,7 +218,8 @@ namespace MagicaCloth2 [Unity.Collections.ReadOnly] public NativeParallelMultiHashMap gridMap; - public NativeParallelHashSet joinPairSet; + //public NativeParallelHashSet joinPairSet; + public NativeParallelMultiHashMap joinPairMap; public void Execute() { @@ -222,14 +250,91 @@ namespace MagicaCloth2 continue; // 結合登録 - int2 ehash = DataUtility.PackInt2(vindex, tvindex); - joinPairSet.Add(ehash); + //int2 ehash = DataUtility.PackInt2(vindex, tvindex); + //joinPairSet.Add(ehash); + joinPairMap.Add((ushort)vindex, (ushort)tvindex); } } } } } + [BurstCompile] + struct JoinJob2 : IJob + { + public int vertexCount; + + [Unity.Collections.ReadOnly] + public NativeParallelMultiHashMap joinPairMap; + + public NativeArray joinIndices; + public NativeParallelMultiHashMap vertexToVertexMap; + public NativeArray boneWeights; + public NativeArray attributes; + public NativeReference result; + + public NativeList tempList; + + public void Execute() + { + int cnt = 0; + + for (ushort vindexLive = 0; vindexLive < vertexCount; vindexLive++) + { + // すでに結合済みならスキップ + if (joinIndices[vindexLive] >= 0) + continue; + + // 対象ループ + foreach (ushort vindexDead in joinPairMap.GetValuesForKey(vindexLive)) + { + // 対象がすでに結合ずみならスキップ + if (joinIndices[vindexDead] >= 0) + continue; + + // 結合(vertexDead -> vertexLive) + joinIndices[vindexDead] = vindexLive; + cnt++; + + vertexToVertexMap.MC2RemoveValue(vindexLive, vindexDead); + + tempList.Clear(); + foreach (ushort i in vertexToVertexMap.GetValuesForKey(vindexDead)) + { + tempList.Add(i); + } + foreach (ushort i in tempList) + { + if (joinIndices[i] >= 0) + continue; + if (i == vindexLive || i == vindexDead) + continue; + + vertexToVertexMap.MC2RemoveValue(i, vindexDead); + + vertexToVertexMap.MC2UniqueAdd(vindexLive, i); + vertexToVertexMap.MC2UniqueAdd(i, vindexLive); + + // p2にBoneWeightを結合 + var bw = boneWeights[vindexLive]; + bw.AddWeight(boneWeights[vindexDead]); + boneWeights[vindexLive] = bw; + + // 属性 + var attr1 = attributes[vindexDead]; + var attr2 = attributes[vindexLive]; + attributes[vindexLive] = VertexAttribute.JoinAttribute(attr1, attr2); + attributes[vindexDead] = VertexAttribute.Invalid; // 削除頂点は無効にする + } + } + } + + // 削除頂点数記録 + result.Value = cnt; + } + } + +#if false // old [BurstCompile] struct JoinJob : IJob { @@ -245,32 +350,31 @@ namespace MagicaCloth2 public void Execute() { var workSet = new FixedList512Bytes(); - int cnt = 0; + foreach (var ehash in joinPairSet) { - int vindex2 = ehash[0]; // 生存側 - int vindex1 = ehash[1]; // 削除側 + int vindexLive = ehash[0]; // 生存側 + int vindexDead = ehash[1]; // 削除側 - // 両方とも生存インデックスに変換する - while (joinIndices[vindex1] >= 0) + while (joinIndices[vindexDead] >= 0) { - vindex1 = joinIndices[vindex1]; + vindexDead = joinIndices[vindexDead]; } - while (joinIndices[vindex2] >= 0) + while (joinIndices[vindexLive] >= 0) { - vindex2 = joinIndices[vindex2]; + vindexLive = joinIndices[vindexLive]; } - if (vindex1 == vindex2) + if (vindexDead == vindexLive) continue; // 結合(vertex1 -> vertex2) - joinIndices[vindex1] = vindex2; + joinIndices[vindexDead] = vindexLive; cnt++; // 接続数を結合する(重複は弾かれる) workSet.Clear(); - foreach (ushort i in vertexToVertexMap.GetValuesForKey((ushort)vindex1)) + foreach (ushort i in vertexToVertexMap.GetValuesForKey((ushort)vindexDead)) { int index = i; // 生存インデックス @@ -278,10 +382,10 @@ namespace MagicaCloth2 { index = joinIndices[index]; } - if (index != vindex1 && index != vindex2) - workSet.Set((ushort)index); + if (index != vindexDead && index != vindexLive) + workSet.MC2Set((ushort)index); } - foreach (ushort i in vertexToVertexMap.GetValuesForKey((ushort)vindex2)) + foreach (ushort i in vertexToVertexMap.GetValuesForKey((ushort)vindexLive)) { int index = i; // 生存インデックス @@ -289,32 +393,33 @@ namespace MagicaCloth2 { index = joinIndices[index]; } - if (index != vindex1 && index != vindex2) - workSet.Set((ushort)index); + if (index != vindexDead && index != vindexLive) + workSet.MC2Set((ushort)index); } - vertexToVertexMap.Remove((ushort)vindex2); + vertexToVertexMap.Remove((ushort)vindexLive); for (int i = 0; i < workSet.Length; i++) { - vertexToVertexMap.Add((ushort)vindex2, workSet[i]); + vertexToVertexMap.Add((ushort)vindexLive, workSet[i]); } //Debug.Assert(workSet.Length > 0); // p2にBoneWeightを結合 - var bw = boneWeights[vindex2]; - bw.AddWeight(boneWeights[vindex1]); - boneWeights[vindex2] = bw; + var bw = boneWeights[vindexLive]; + bw.AddWeight(boneWeights[vindexDead]); + boneWeights[vindexLive] = bw; // 属性 - var attr1 = attributes[vindex1]; - var attr2 = attributes[vindex2]; - attributes[vindex2] = VertexAttribute.JoinAttribute(attr1, attr2); - attributes[vindex1] = VertexAttribute.Invalid; // 削除頂点は無効にする + var attr1 = attributes[vindexDead]; + var attr2 = attributes[vindexLive]; + attributes[vindexLive] = VertexAttribute.JoinAttribute(attr1, attr2); + attributes[vindexDead] = VertexAttribute.Invalid; // 削除頂点は無効にする } // 削除頂点数記録 result.Value = cnt; } } +#endif //========================================================================================= /// @@ -395,7 +500,7 @@ namespace MagicaCloth2 if (tvindex == vindex) continue; - newLinkSet.Set((ushort)tvindex); + newLinkSet.MC2Set((ushort)tvindex); } // 生存のみの新しいセットに入れ替え vertexToVertexMap.Remove((ushort)vindex); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/SameDistanceReduction.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/SameDistanceReduction.cs.meta index 2b49937a..ffea9b4f 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/SameDistanceReduction.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/SameDistanceReduction.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Reduction/SameDistanceReduction.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/ShapeDistanceReduction.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/ShapeDistanceReduction.cs.meta index 71f3f6bb..5c52e2ce 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/ShapeDistanceReduction.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/ShapeDistanceReduction.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Reduction/ShapeDistanceReduction.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/SimpleDistanceReduction.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/SimpleDistanceReduction.cs.meta index fc94dd0c..732b96e7 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/SimpleDistanceReduction.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/SimpleDistanceReduction.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Reduction/SimpleDistanceReduction.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/StepReductionBase.cs b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/StepReductionBase.cs index 77f0ffb8..b4e09a24 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/StepReductionBase.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/StepReductionBase.cs @@ -450,12 +450,12 @@ namespace MagicaCloth2 foreach (ushort nindex in vertexToVertexMap.GetValuesForKey((ushort)vindex1)) { if (nindex != vindex1 && nindex != vindex2) - newLink.Set(nindex); + newLink.MC2Set(nindex); } foreach (ushort nindex in vertexToVertexMap.GetValuesForKey((ushort)vindex2)) { if (nindex != vindex1 && nindex != vindex2) - newLink.Set(nindex); + newLink.MC2Set(nindex); } vertexToVertexMap.Remove((ushort)vindex2); for (int i = 0; i < newLink.Length; i++) @@ -558,7 +558,7 @@ namespace MagicaCloth2 if (tvindex == vindex) continue; - newLinkSet.Set((ushort)tvindex); + newLinkSet.MC2Set((ushort)tvindex); } // 生存のみの新しいセットに入れ替え vertexToVertexMap.Remove((ushort)vindex); @@ -640,12 +640,12 @@ namespace MagicaCloth2 foreach (ushort index in vertexToVertexMap.GetValuesForKey((ushort)vindex)) { if (index != vindex && index != tvindex) - joinVlink.Set(index); + joinVlink.MC2Set(index); } foreach (ushort index in vertexToVertexMap.GetValuesForKey((ushort)tvindex)) { if (index != vindex && index != tvindex) - joinVlink.Set(index); + joinVlink.MC2Set(index); } // 点になるのはNG @@ -662,20 +662,20 @@ namespace MagicaCloth2 // 結合後のトライアングルの外周をひと筆書きし、すべての外周頂点が使われているならOK! // 外周頂点が一筆書きできない場合は2つ以上のグループに分かれいる(X型になる) var stack = new FixedList512Bytes(); - stack.Push(joinVlink[0]); + stack.MC2Push(joinVlink[0]); while (stack.Length > 0) { - ushort index = stack.Pop(); + ushort index = stack.MC2Pop(); if (joinVlink.Contains(index) == false) continue; - joinVlink.RemoveItemAtSwapBack(index); + joinVlink.MC2RemoveItemAtSwapBack(index); foreach (ushort nindex in vertexToVertexMap.GetValuesForKey((ushort)index)) { if (joinVlink.Contains(nindex)) { // next - stack.Push(nindex); + stack.MC2Push(nindex); } } } @@ -716,13 +716,13 @@ namespace MagicaCloth2 { int index = vlist[i]; if (index != vindex && index != tvindex) - joinVlink.SetLimit((ushort)index); + joinVlink.MC2SetLimit((ushort)index); } for (int i = 0; i < tvlist.Length; i++) { int index = tvlist[i]; if (index != vindex && index != tvindex) - joinVlink.SetLimit((ushort)index); + joinVlink.MC2SetLimit((ushort)index); } // 点になるのはNG @@ -739,13 +739,13 @@ namespace MagicaCloth2 // 結合後のトライアングルの外周をひと筆書きし、すべての外周頂点が使われているならOK! // 外周頂点が一筆書きできない場合は2つ以上のグループに分かれいる(X型になる) var stack = new FixedList512Bytes(); - stack.Push(joinVlink[0]); + stack.MC2Push(joinVlink[0]); while (stack.Length > 0) { - ushort index = stack.Pop(); + ushort index = stack.MC2Pop(); if (joinVlink.Contains(index) == false) continue; - joinVlink.RemoveItemAtSwapBack(index); + joinVlink.MC2RemoveItemAtSwapBack(index); var link = vertexToVertexArray[index]; for (int i = 0; i < link.Length; i++) @@ -754,7 +754,7 @@ namespace MagicaCloth2 if (joinVlink.Contains(nindex)) { // next - stack.Push(nindex); + stack.MC2Push(nindex); } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/StepReductionBase.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/StepReductionBase.cs.meta index bf37dc7e..c65100de 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Reduction/StepReductionBase.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Reduction/StepReductionBase.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Reduction/StepReductionBase.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Settings/ClothDebugSettings.cs b/Assets/External/MagicaCloth2/Scripts/Core/Settings/ClothDebugSettings.cs index 785dc3cc..c133b74b 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Settings/ClothDebugSettings.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Settings/ClothDebugSettings.cs @@ -35,9 +35,7 @@ namespace MagicaCloth2 public DebugAxis animatedAxis = DebugAxis.None; public bool animatedShape = false; public bool inertiaCenter = true; - //public bool basicPosition = false; - //public DebugAxis basicAxis = DebugAxis.None; - //public bool basicShape = false; + public bool customSkinningBone = true; //===================================================================== // ■デバッグ用 @@ -60,6 +58,7 @@ namespace MagicaCloth2 //public bool horizontalDistanceConstraint = false; public bool collisionNormal = false; public bool cellCube = false; + public bool baseLinePos = false; public int vertexMinIndex = 0; public int vertexMaxIndex = 100000; public int triangleMinIndex = 0; @@ -103,16 +102,11 @@ namespace MagicaCloth2 #endif } - public float GetLineSize() - { - //return 0.03f; // 固定 - return 0.05f; // 固定 - } + public float GetLineSize() => 0.05f; // 固定 - public float GetInertiaCenterRadius() - { - return 0.01f; // 固定 - } + public float GetInertiaCenterRadius() => 0.01f; // 固定 + + public float GetCustomSkinningRadius() => 0.02f; // 固定 public bool IsReferOldPos() { diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Settings/ClothDebugSettings.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Settings/ClothDebugSettings.cs.meta index c0573936..ca7b3e3e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Settings/ClothDebugSettings.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Settings/ClothDebugSettings.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Settings/ClothDebugSettings.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Settings/VirtualMeshDebugSettings.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Settings/VirtualMeshDebugSettings.cs.meta index e4088ab7..b70dfb80 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Settings/VirtualMeshDebugSettings.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Settings/VirtualMeshDebugSettings.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Settings/VirtualMeshDebugSettings.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/DataUtility.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/DataUtility.cs index 15033b82..20053116 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/DataUtility.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/DataUtility.cs @@ -1,6 +1,7 @@ // Magica Cloth 2. // Copyright (c) 2023 MagicaSoft. // https://magicasoft.jp +using System; using System.Runtime.CompilerServices; using Unity.Mathematics; using UnityEngine; @@ -428,7 +429,7 @@ namespace MagicaCloth2 { float time = i / 15.0f; float val = curve.Evaluate(time); - m.SetValue(i, val); + m.MC2SetValue(i, val); } return m; @@ -447,32 +448,81 @@ namespace MagicaCloth2 int index = (int)(math.saturate(time) * 15); time -= index * interval; float t = time / interval; - return math.lerp(curve.GetValue(index), curve.GetValue(index + 1), t); + return math.lerp(curve.MC2GetValue(index), curve.MC2GetValue(index + 1), t); } //========================================================================================= /// - /// 8bitフラグからコライダータイプを取得する - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ColliderManager.ColliderType GetColliderType(in ExBitFlag8 flag) - { - return (ColliderManager.ColliderType)(flag.Value & 0x0f); - } - - /// - /// 8bitフラグにコライダータイプを設定する + /// 16bitフラグにコライダータイプを設定する /// /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ExBitFlag8 SetColliderType(ExBitFlag8 flag, ColliderManager.ColliderType ctype) + public static ExBitFlag16 SetColliderType(ExBitFlag16 flag, ColliderManager.ColliderType ctype) { - flag.Value = (byte)(flag.Value & 0xf0 | (byte)ctype); + flag.Value = (ushort)((flag.Value & 0xfff0) | (ushort)ctype); return flag; } + + /// + /// 16bitフラグからコライダータイプを取得する + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ColliderManager.ColliderType GetColliderType(in ExBitFlag16 flag) + { + return (ColliderManager.ColliderType)(flag.Value & 0x000f); + } + + /// + /// 16bitフラグにシンメトリータイプを設定する + /// + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ExBitFlag16 SetSymmetryType(ExBitFlag16 flag, ColliderManager.SymmetryType stype) + { + flag.Value = (ushort)((flag.Value & 0xff0f) | (((ushort)stype) << 4)); + return flag; + } + + /// + /// 16bitフラグからシンメトリータイプを取得する + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ColliderManager.SymmetryType GetSymmetryType(in ExBitFlag16 flag) + { + return (ColliderManager.SymmetryType)((flag.Value & 0x00f0) >> 4); + } + + //========================================================================================= + /// + /// 配列をDeepコピーする + /// + /// + /// + /// + public static void ArrayCopy(T[] src, ref T[] dst) + { + if (src == null) + { + dst = null; + return; + } + if (src.Length == 0) + { + dst = new T[0]; + } + else + { + dst = new T[src.Length]; + Array.Copy(src, dst, src.Length); + } + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/DataUtility.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/DataUtility.cs.meta index 4b90085d..f709a0b1 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/DataUtility.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/DataUtility.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/DataUtility.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/MultiDataBuilder.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/MultiDataBuilder.cs.meta index 530cb949..dc089fe4 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/MultiDataBuilder.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/MultiDataBuilder.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Data/MultiDataBuilder.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Grid/GridMap.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Grid/GridMap.cs index 760b163f..08cceaee 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Grid/GridMap.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Grid/GridMap.cs @@ -17,7 +17,7 @@ namespace MagicaCloth2 /// GridSize>0である必要あり! /// /// - public class GridMap : IDisposable where T : unmanaged, IEquatable + public class GridMap : IDisposable where T : unmanaged // , IEquatable { private NativeParallelMultiHashMap gridMap; diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Grid/GridMap.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Grid/GridMap.cs.meta index 7d88a3e1..5e97bfdd 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Grid/GridMap.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Grid/GridMap.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Grid/GridMap.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/InterlockUtility.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/InterlockUtility.cs index c7b132d2..cec2405e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/InterlockUtility.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/InterlockUtility.cs @@ -3,10 +3,6 @@ // https://magicasoft.jp using System.Runtime.CompilerServices; using System.Threading; -using Unity.Burst; -using Unity.Collections; -using Unity.Collections.LowLevel.Unsafe; -using Unity.Jobs; using Unity.Mathematics; namespace MagicaCloth2 @@ -19,13 +15,12 @@ namespace MagicaCloth2 /// /// 固定小数点への変換倍率 /// - const int ToFixed = 100000; + internal const int ToFixed = 1000000; /// /// 少数への復元倍率 /// - const float ToFloat = 0.00001f; - + internal const float ToFloat = 0.000001f; //========================================================================================= /// @@ -65,17 +60,6 @@ namespace MagicaCloth2 } } - /// - /// 集計バッファのカウンタのみインクリメントする - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - unsafe internal static void Increment(int index, int* cntPt) - { - Interlocked.Increment(ref cntPt[index]); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] unsafe internal static void Max(int index, float value, int* pt) { @@ -91,16 +75,16 @@ namespace MagicaCloth2 } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static float3 ReadAverageFloat3(int index, in NativeArray countArray, in NativeArray sumArray) + unsafe internal static float3 ReadAverageFloat3(int index, int* cntPt, int* sumPt) { - int count = countArray[index]; + int count = cntPt[index]; if (count == 0) return 0; int dataIndex = index * 3; // 集計 - float3 add = new float3(sumArray[dataIndex], sumArray[dataIndex + 1], sumArray[dataIndex + 2]); + float3 add = new float3(sumPt[dataIndex], sumPt[dataIndex + 1], sumPt[dataIndex + 2]); add /= count; // データは固定小数点なので戻す @@ -110,10 +94,10 @@ namespace MagicaCloth2 } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static float3 ReadFloat3(int index, in NativeArray bufferArray) + unsafe internal static float3 ReadFloat3(int index, int* vecPt) { int dataIndex = index * 3; - float3 v = new float3(bufferArray[dataIndex], bufferArray[dataIndex + 1], bufferArray[dataIndex + 2]); + float3 v = new float3(vecPt[dataIndex], vecPt[dataIndex + 1], vecPt[dataIndex + 2]); // データは固定小数点なので戻す v *= ToFloat; @@ -122,351 +106,9 @@ namespace MagicaCloth2 } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static float ReadFloat(int index, in NativeArray bufferArray) + unsafe internal static float ReadFloat(int index, int* floatPt) { - return bufferArray[index] * ToFloat; - } - -#if false - /// - /// 指定アドレスにfloat値を加算する - /// - /// - /// - /// - unsafe public static void AddFloat(int* pt, int index, float value) - { - float current = UnsafeUtility.ReadArrayElement(pt, index); - int currenti = math.asint(current); - while (true) - { - float next = current + value; - int nexti = math.asint(next); - int prev = Interlocked.CompareExchange(ref pt[index], nexti, currenti); - if (prev == currenti) - return; - else - { - currenti = prev; - current = math.asfloat(prev); - } - } - } -#endif - - //========================================================================================= - /// - /// 加算集計バッファを平均化してnextPosに加算する - /// - /// - /// - /// - internal static JobHandle SolveAggregateBufferAndClear(in NativeList particleList, float velocityAttenuation, JobHandle jobHandle) - { - var sm = MagicaManager.Simulation; - - if (velocityAttenuation > 1e-06f) - { - // 速度影響あり - var job = new AggregateWithVelocityJob() - { - jobParticleIndexList = particleList, - - nextPosArray = sm.nextPosArray.GetNativeArray(), - velocityPosArray = sm.velocityPosArray.GetNativeArray(), - - velocityAttenuation = velocityAttenuation, - countArray = sm.countArray, - sumArray = sm.sumArray, - }; - jobHandle = job.Schedule(particleList, 16, jobHandle); - } - else - { - // 速度影響なし - var job = new AggregateJob() - { - //velocityLimit = velocityLimit, - jobParticleIndexList = particleList, - - nextPosArray = sm.nextPosArray.GetNativeArray(), - - countArray = sm.countArray, - sumArray = sm.sumArray, - }; - jobHandle = job.Schedule(particleList, 16, jobHandle); - } - - return jobHandle; - } - - [BurstCompile] - struct AggregateJob : IJobParallelForDefer - { - // 速度制限 - //public float velocityLimit; - - [Unity.Collections.ReadOnly] - public NativeList jobParticleIndexList; - - // particle - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - - // aggregate - - [NativeDisableParallelForRestriction] - public NativeArray countArray; - [NativeDisableParallelForRestriction] - public NativeArray sumArray; - - // 集計パーティクルごと - public void Execute(int index) - { - int pindex = jobParticleIndexList[index]; - - int count = countArray[pindex]; - if (count == 0) - return; - - int dataIndex = pindex * 3; - - // 集計 - float3 add = new float3(sumArray[dataIndex], sumArray[dataIndex + 1], sumArray[dataIndex + 2]); - add /= count; - - // データは固定小数点なので戻す - add *= ToFloat; - - // 速度制限 - //add = MathUtility.ClampVector(add, velocityLimit); - - // 書き出し - nextPosArray[pindex] = nextPosArray[pindex] + add; - - // 集計バッファクリア - countArray[pindex] = 0; - sumArray[dataIndex] = 0; - sumArray[dataIndex + 1] = 0; - sumArray[dataIndex + 2] = 0; - } - } - - /// - /// 速度影響あり - /// - [BurstCompile] - struct AggregateWithVelocityJob : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeList jobParticleIndexList; - - // particle - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - [NativeDisableParallelForRestriction] - public NativeArray velocityPosArray; - - // aggregate - public float velocityAttenuation; - [NativeDisableParallelForRestriction] - public NativeArray countArray; - [NativeDisableParallelForRestriction] - public NativeArray sumArray; - - // 集計パーティクルごと - public void Execute(int index) - { - int pindex = jobParticleIndexList[index]; - - int count = countArray[pindex]; - if (count == 0) - return; - - int dataIndex = pindex * 3; - - // 集計 - float3 add = new float3(sumArray[dataIndex], sumArray[dataIndex + 1], sumArray[dataIndex + 2]); - add /= count; - - // データは固定小数点なので戻す - add *= ToFloat; - - // 書き出し - nextPosArray[pindex] = nextPosArray[pindex] + add; - - // 速度影響 - velocityPosArray[pindex] = velocityPosArray[pindex] + add * velocityAttenuation; - - // 集計バッファクリア - countArray[pindex] = 0; - sumArray[dataIndex] = 0; - sumArray[dataIndex + 1] = 0; - sumArray[dataIndex + 2] = 0; - } - } - - internal static JobHandle SolveAggregateBufferAndClear(in ExProcessingList processingList, float velocityAttenuation, JobHandle jobHandle) - { - return SolveAggregateBufferAndClear(processingList.Buffer, processingList.Counter, velocityAttenuation, jobHandle); - } - - unsafe internal static JobHandle SolveAggregateBufferAndClear(in NativeArray particleArray, in NativeReference counter, float velocityAttenuation, JobHandle jobHandle) - { - var sm = MagicaManager.Simulation; - - if (velocityAttenuation > 1e-06f) - { - // 速度影響あり - var job = new AggregateWithVelocityJob2() - { - particleIndexArray = particleArray, - - nextPosArray = sm.nextPosArray.GetNativeArray(), - velocityPosArray = sm.velocityPosArray.GetNativeArray(), - - velocityAttenuation = velocityAttenuation, - countArray = sm.countArray, - sumArray = sm.sumArray, - }; - jobHandle = job.Schedule((int*)counter.GetUnsafePtrWithoutChecks(), 16, jobHandle); - } - else - { - // 速度影響なし - var job = new AggregateJob2() - { - //velocityLimit = velocityLimit, - particleIndexArray = particleArray, - - nextPosArray = sm.nextPosArray.GetNativeArray(), - - countArray = sm.countArray, - sumArray = sm.sumArray, - }; - jobHandle = job.Schedule((int*)counter.GetUnsafePtrWithoutChecks(), 16, jobHandle); - } - - return jobHandle; - } - - [BurstCompile] - struct AggregateJob2 : IJobParallelForDefer - { - // 速度制限 - //public float velocityLimit; - - [Unity.Collections.ReadOnly] - public NativeArray particleIndexArray; - - // particle - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - - // aggregate - - [NativeDisableParallelForRestriction] - public NativeArray countArray; - [NativeDisableParallelForRestriction] - public NativeArray sumArray; - - // 集計パーティクルごと - public void Execute(int index) - { - int pindex = particleIndexArray[index]; - - int count = countArray[pindex]; - if (count == 0) - return; - - int dataIndex = pindex * 3; - - // 集計 - float3 add = new float3(sumArray[dataIndex], sumArray[dataIndex + 1], sumArray[dataIndex + 2]); - add /= count; - - // データは固定小数点なので戻す - add *= ToFloat; - - // 速度制限 - //add = MathUtility.ClampVector(add, velocityLimit); - - // 書き出し - nextPosArray[pindex] = nextPosArray[pindex] + add; - - // 集計バッファクリア - countArray[pindex] = 0; - sumArray[dataIndex] = 0; - sumArray[dataIndex + 1] = 0; - sumArray[dataIndex + 2] = 0; - } - } - - /// - /// 速度影響あり - /// - [BurstCompile] - struct AggregateWithVelocityJob2 : IJobParallelForDefer - { - [Unity.Collections.ReadOnly] - public NativeArray particleIndexArray; - - // particle - [NativeDisableParallelForRestriction] - public NativeArray nextPosArray; - [NativeDisableParallelForRestriction] - public NativeArray velocityPosArray; - - // aggregate - public float velocityAttenuation; - [NativeDisableParallelForRestriction] - public NativeArray countArray; - [NativeDisableParallelForRestriction] - public NativeArray sumArray; - - // 集計パーティクルごと - public void Execute(int index) - { - int pindex = particleIndexArray[index]; - - int count = countArray[pindex]; - if (count == 0) - return; - - int dataIndex = pindex * 3; - - // 集計 - float3 add = new float3(sumArray[dataIndex], sumArray[dataIndex + 1], sumArray[dataIndex + 2]); - add /= count; - - // データは固定小数点なので戻す - add *= ToFloat; - - // 書き出し - nextPosArray[pindex] = nextPosArray[pindex] + add; - - // 速度影響 - velocityPosArray[pindex] = velocityPosArray[pindex] + add * velocityAttenuation; - - // 集計バッファクリア - countArray[pindex] = 0; - sumArray[dataIndex] = 0; - sumArray[dataIndex + 1] = 0; - sumArray[dataIndex + 2] = 0; - } - } - - - /// - /// 集計バッファのカウンタのみゼロクリアする - /// - /// - /// - internal static JobHandle ClearCountArray(JobHandle jobHandle) - { - var sm = MagicaManager.Simulation; - - return JobUtility.Fill(sm.countArray, sm.countArray.Length, 0, jobHandle); + return floatPt[index] * ToFloat; } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/InterlockUtility.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/InterlockUtility.cs.meta index eca954b0..535d5ce3 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/InterlockUtility.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/InterlockUtility.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/InterlockUtility.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/JobUtility.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/JobUtility.cs.meta index 53019355..324b57e9 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/JobUtility.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/JobUtility.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Jobs/JobUtility.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/AABB.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/AABB.cs.meta index 9e4d5438..e222eeea 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/AABB.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/AABB.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/AABB.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/IntAABB.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/IntAABB.cs.meta index af390b53..2b2351f4 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/IntAABB.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/IntAABB.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/IntAABB.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathExtensions.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathExtensions.cs index 961cf8f1..c328dc43 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathExtensions.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathExtensions.cs @@ -15,7 +15,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float GetValue(in this float4x4 m, int index) + public static float MC2GetValue(in this float4x4 m, int index) { index = math.clamp(index, 0, 15); return m[index / 4][index % 4]; @@ -28,7 +28,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void SetValue(ref this float4x4 m, int index, float value) + public static void MC2SetValue(ref this float4x4 m, int index, float value) { index = math.clamp(index, 0, 15); m[index / 4][index % 4] = value; @@ -41,7 +41,7 @@ namespace MagicaCloth2 /// 0.0 ~ 1.0 /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float EvaluateCurveClamp01(in this float4x4 m, float time) + public static float MC2EvaluateCurveClamp01(in this float4x4 m, float time) { return math.saturate(DataUtility.EvaluateCurve(m, time)); } @@ -53,7 +53,7 @@ namespace MagicaCloth2 /// 0.0 ~ 1.0 /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float EvaluateCurve(in this float4x4 m, float time) + public static float MC2EvaluateCurve(in this float4x4 m, float time) { return DataUtility.EvaluateCurve(m, time); } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathExtensions.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathExtensions.cs.meta index da067818..e154e16a 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathExtensions.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathExtensions.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathExtensions.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathUtility.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathUtility.cs index ec70d536..1a7a7d1a 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathUtility.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathUtility.cs @@ -223,6 +223,45 @@ namespace MagicaCloth2 return quaternion.AxisAngle(math.normalize(axis), angle * t); } + /// + /// fromからtoへ回転させるクォータニオンを返します(単位化なし) + /// + /// + /// + /// 補間率(0.0-1.0) + /// + public static quaternion FromToRotationWithoutNormalize(in float3 v1, in float3 v2, float t = 1.0f) + { + //float3 v1 = math.normalize(from); + //float3 v2 = math.normalize(to); + + float c = Clamp1(math.dot(v1, v2)); + float angle = math.acos(c); + float3 axis = math.cross(v1, v2); + + if (math.abs(1.0f + c) < 1e-06f) + { + angle = (float)math.PI; + + if (v1.x > v1.y && v1.x > v1.z) + { + axis = math.cross(v1, new float3(0, 1, 0)); + } + else + { + axis = math.cross(v1, new float3(1, 0, 0)); + } + } + else if (math.abs(1.0f - c) < 1e-06f) + { + //angle = 0.0f; + //axis = new float3(1, 0, 0); + return quaternion.identity; + } + + return quaternion.AxisAngle(math.normalize(axis), angle * t); + } + /// /// fromからtoへ回転させるクォータニオンを返します /// @@ -287,13 +326,15 @@ namespace MagicaCloth2 public static quaternion ToRotation(in float3 nor, in float3 tan) { #if MC2_DEBUG + // 安全性確認 float ln = math.length(nor); float lt = math.length(tan); - Develop.Assert(ln > 0.0f); - Develop.Assert(lt > 0.0f); + Develop.Assert(ln > 0.99f && ln < 1.01f); + Develop.Assert(lt > 0.99f && lt < 1.01f); float dot = math.dot(nor / ln, tan / lt); Develop.Assert(dot != 1.0f && dot != -1.0f); #endif + // 2 つの入力ベクトルは単位長であり、同一直線上にないことが前提となります。 return quaternion.LookRotation(tan, nor); } @@ -402,6 +443,45 @@ namespace MagicaCloth2 axis = q.value.xyz / s; } + /// + /// クォータニオンからオイラー角度を計算して返す + /// + /// + /// (Deg)角度 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float3 ToEuler(in quaternion q) + { + float3 angles = 0; + + // クォータニオンの成分 + float qx = q.value.x; + float qy = q.value.y; + float qz = q.value.z; + float qw = q.value.w; + + // ピッチ (x軸回転) + float sinX = 2f * (qw * qx - qz * qy); + if (math.abs(sinX) >= 0.99999f) // ジンバルロックの検出 + { + angles.x = math.sign(sinX) * 90f; // ±90度(deg) + angles.y = math.atan2(2f * (qw * qy + qx * qz), 1f - 2f * (qx * qx + qy * qy)); + angles.y = math.degrees(angles.y); + angles.z = 0f; // ジンバルロックでロールは不定 + } + else + { + angles.x = math.asin(sinX); + // ヨー (y軸回転) + angles.y = math.atan2(2f * (qw * qy + qx * qz), 1f - 2f * (qx * qx + qy * qy)); + // ロール (z軸回転) + //angles.z = math.atan2(2f * (qw * qz + qx * qy), 1f - 2f * (qy * qy + qz * qz)); + angles.z = math.atan2(2f * (qw * qz + qx * qy), 1f - 2f * (qx * qx + qz * qz)); // どうやらこれっぽい + angles = math.degrees(angles); + } + + return angles; + } + /// /// 与えられた線分abおよび点cに対して、ab上の最近接点t(0.0-1.0)を計算して返す /// @@ -570,6 +650,82 @@ namespace MagicaCloth2 return math.dot(c1 - c2, c1 - c2); } + /// + /// 2つの線分(p1-q1)(p2-q2)の最近接点(s, t)を計算する + /// この関数ではs/tのみで接点と距離は計算しない + /// + /// 線分1の始点 + /// 線分1の終点 + /// 線分2の始点 + /// 線分2の終点 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ClosestPtSegmentSegment2(in float3 p1, in float3 q1, in float3 p2, in float3 q2, out float s, out float t) + { + //s = 0.0f; + //t = 0.0f; + float3 d1 = q1 - p1; // 線分s1の方向ベクトル + float3 d2 = q2 - p2; // 線分s2の方向ベクトル + float3 r = p1 - p2; + float a = math.dot(d1, d1); // 線分s1の距離の平方、常に正 + float e = math.dot(d2, d2); // 線分s2の距離の平方、常に正 + float f = math.dot(d2, r); + // 片方あるいは両方の線分が点に縮退しているかどうかチェック + if (a <= 1e-8f && e <= 1e-8f) + { + // 両方の線分が点に縮退 + s = t = 0.0f; + } + else if (a <= 1e-8f) + { + // 最初の線分が点に縮退 + s = 0.0f; + t = math.saturate(f / e); + } + else + { + float c = math.dot(d1, r); + if (e <= 1e-8f) + { + // 2番目の線分が点に縮退 + t = 0.0f; + s = math.saturate(-c / a); + } + else + { + // ここから一般的な縮退の場合を開始 + float b = math.dot(d1, d2); + float denom = a * e - b * b; // 常に正 + // 線分が平行でない場合、L1上のL2に対する最近接点を計算、そして + // 線分s1に対してクランプ。そうでない場合は任意s(ここでは0)を選択 + if (denom != 0.0f) + { + s = math.saturate((b * f - c * e) / denom); + } + else + { + s = 0.0f; + } + // L2上のs1(s)に対する最近接点を以下を用いて計算 + // t = dot((p1 + d1 * s) - p2, d2) / dot(d2, d2) = (b * s + f) / e + t = (b * s + f) / e; + // tが[0,1]の中にあれば終了。 + // そうでなければtをクランプ、sをtの新しい値に対して以下を用いて再計算 + // s = dot((p2 + d2 * t) - p1, d1) / dot(d1, d1) = (t * b - c) / a + // そしてsを[0,1]にクランプ + if (t < 0.0f) + { + t = 0.0f; + s = math.saturate(-c / a); + } + else if (t > 1.0f) + { + t = 1.0f; + s = math.saturate((b - c) / a); + } + } + } + } + /// /// 三角形(abc)から点(p)への最近接点とその重心座標uvwを返す /// @@ -780,6 +936,7 @@ namespace MagicaCloth2 return tan; } +#if false /// /// トライアングルの回転姿勢を返す /// 法線と(重心-p0)の軸からなるクォータニオン @@ -815,6 +972,7 @@ namespace MagicaCloth2 var tan = math.normalize(p3 - p2); return quaternion.LookRotation(tan, n); } +#endif /// /// トライアングルペアのなす角を返す(ラジアン) @@ -1064,30 +1222,45 @@ namespace MagicaCloth2 } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float3 TransformPoint(in float3 pos, in float4x4 localToWorldMatrix) + public static float3 TransformPoint(in float3 pos, in float3 wpos, in quaternion wrot, in float3 wscl) { - return math.transform(localToWorldMatrix, pos); + return math.transform(Matrix4x4.TRS(wpos, wrot, wscl), pos); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float3 TransformVector(in float3 vec, in float4x4 localToWorldMatrix) + public static float3 TransformPoint(in float3 pos, in float4x4 m) { - return math.mul(localToWorldMatrix, new float4(vec, 0)).xyz; + return math.transform(m, pos); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float3 TransformDirection(in float3 dir, in float4x4 localToWorldMatrix) + public static float3 TransformVector(in float3 vec, in float4x4 m) + { + return math.mul(m, new float4(vec, 0)).xyz; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float3 TransformDirection(in float3 dir, in float4x4 m) { float len = math.length(dir); if (len > 0.0f) - return math.normalize(TransformVector(dir, localToWorldMatrix)) * len; + return math.normalize(TransformVector(dir, m)) * len; else return dir; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static quaternion TransformRotation(in quaternion rot, in float4x4 m, in float3 normalTangentFlip) + { + ToNormalTangent(rot, out float3 nor, out float3 tan); + nor = math.mul(m, new float4(nor, 0)).xyz * normalTangentFlip.y; + tan = math.mul(m, new float4(tan, 0)).xyz * normalTangentFlip.z; + return quaternion.LookRotation(tan, nor); + } + /// /// 距離を空間変換する - /// 不均等スケールを考慮して各軸の平均値を返す + /// 非一様スケールを考慮して各軸の平均値を返す /// /// /// @@ -1139,6 +1312,12 @@ namespace MagicaCloth2 return math.transform(worldToLocalMatrix, pos); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float3 InverseTransformPoint(in float3 pos, in float3 wpos, in quaternion wrot, in float3 wscl) + { + return math.transform(math.inverse(Matrix4x4.TRS(wpos, wrot, wscl)), pos); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float3 InverseTransformVector(in float3 vec, in float4x4 worldToLocalMatrix) { @@ -1364,6 +1543,7 @@ namespace MagicaCloth2 if (math.dot(planeDir, v) < 0.0f) { + // 押し出し発生 // 押出し座標 outPos = pos - gv; @@ -1373,9 +1553,10 @@ namespace MagicaCloth2 } else { + // 押し出し不要。何もしない outPos = pos; - // 面までの距離を返す + // 面までの距離を返す(+) return len; } } @@ -1554,5 +1735,57 @@ namespace MagicaCloth2 Develop.Assert(mass > 0.0f); return 1.0f / mass; } + + /// + /// 数をn分割して、指定インデックスの範囲を返します。 + /// 数は整数のみ。 + /// 例:100(dataLength)を5(divCount)分割した結果 + /// divIndex(0):0~20 + /// divIndex(1):20~40 + /// divIndex(2):40~60 + /// divIndex(3):60~80 + /// divIndex(4):80~100 + /// + /// ただし、数が分割数を下回る場合は範囲外のインデックスは-1となる + /// 例:3(dataLength)を5(divCount)分割した結果 + /// divIndex(0):0~1 + /// divIndex(1):1~2 + /// divIndex(2):2~3 + /// divIndex(3):-1~-1 + /// divIndex(4):-1~-1 + /// + /// + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int2 CalcSplitRange(int dataLength, int divCount, int divIndex) + { + if (dataLength <= 0) + return -1; + + if (dataLength < divCount) + { + if (divIndex < dataLength) + return new int2(divIndex, divIndex + 1); + else + return -1; + } + + float segment = (float)dataLength / divCount; + int start = (int)(segment * divIndex); + int end = (divIndex == divCount - 1) ? dataLength : (int)(segment * (divIndex + 1)); + return new int2(start, end); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static DataChunk GetWorkerChunk(int dataLenght, int workerCount, int workerIndex) + { + int2 range = CalcSplitRange(dataLenght, workerCount, workerIndex); + if (range.x < 0) + return DataChunk.Empty; + else + return new DataChunk(range.x, range.y - range.x); + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathUtility.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathUtility.cs.meta index 71c8ccf0..094e2f40 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathUtility.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathUtility.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MathUtility.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MinimumData.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MinimumData.cs.meta index ae2c5b76..b1e3eb65 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MinimumData.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MinimumData.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Math/MinimumData.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Mesh/MeshUtility.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Mesh/MeshUtility.cs.meta index 4bf34377..b7b851e0 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Mesh/MeshUtility.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Mesh/MeshUtility.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Mesh/MeshUtility.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Misc/Develop.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Misc/Develop.cs.meta index 5f3f3e52..d5d71119 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Misc/Develop.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Misc/Develop.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Misc/Develop.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Misc/StaticStringBuilder.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Misc/StaticStringBuilder.cs.meta index 656d5931..463294d4 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Misc/StaticStringBuilder.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Misc/StaticStringBuilder.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Misc/StaticStringBuilder.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/DataChunk.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/DataChunk.cs.meta index 1ed85605..0c600d55 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/DataChunk.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/DataChunk.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/DataChunk.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExBitFlag16.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExBitFlag16.cs.meta index 550dab88..45c3beef 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExBitFlag16.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExBitFlag16.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExBitFlag16.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExBitFlag8.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExBitFlag8.cs.meta index 463e18fc..8f43f0d1 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExBitFlag8.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExBitFlag8.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExBitFlag8.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExCostSortedList1.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExCostSortedList1.cs.meta index 23ec4095..28fda3dc 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExCostSortedList1.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExCostSortedList1.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExCostSortedList1.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExCostSortedList4.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExCostSortedList4.cs.meta index a6646a11..fb0cac01 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExCostSortedList4.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExCostSortedList4.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExCostSortedList4.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExNativeArray.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExNativeArray.cs index 23f6338d..7ada7e3d 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExNativeArray.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExNativeArray.cs @@ -7,6 +7,7 @@ using System.Text; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using Unity.Mathematics; +using UnityEngine; namespace MagicaCloth2 { @@ -389,6 +390,12 @@ namespace MagicaCloth2 NativeArray.Copy(nativeArray, array); } + public void CopyTo(T[] array, int startIndex) + { + Debug.Assert(array != null); + NativeArray.Copy(nativeArray, startIndex, array, 0, array.Length); + } + public void CopyTo(U[] array) where U : struct { NativeArray.Copy(nativeArray.Reinterpret(), array); @@ -399,11 +406,22 @@ namespace MagicaCloth2 NativeArray.Copy(array, nativeArray); } + public void CopyFrom(T[] array, int startIndex) + { + Debug.Assert(array != null); + NativeArray.Copy(array, 0, nativeArray, startIndex, array.Length); + } + public void CopyFrom(NativeArray array) where U : struct { NativeArray.Copy(array.Reinterpret(), nativeArray); } + public void CopyFrom(NativeArray array, int dstIndex, int length) where U : struct + { + NativeArray.Copy(array.Reinterpret(), 0, nativeArray, dstIndex, length); + } + /// /// 型もサイズも異なる配列にデータをコピーする。 /// int3 -> int[]など @@ -474,6 +492,11 @@ namespace MagicaCloth2 } } + public void Remove(int index) + { + Remove(new DataChunk(index)); + } + public void RemoveAndFill(DataChunk chunk, T clearData = default(T)) { Remove(chunk); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExNativeArray.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExNativeArray.cs.meta index 9518bd4b..d8420ba3 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExNativeArray.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExNativeArray.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExNativeArray.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExProcessingList.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExProcessingList.cs.meta index 53ae693c..ec021d62 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExProcessingList.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExProcessingList.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExProcessingList.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExSimpleNativeArray.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExSimpleNativeArray.cs index f7f259a4..c675310e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExSimpleNativeArray.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExSimpleNativeArray.cs @@ -67,6 +67,11 @@ namespace MagicaCloth2 count = length; } + public ExSimpleNativeArray(SerializationData sdata) + { + Deserialize(sdata); + } + public void Dispose() { if (nativeArray.IsCreated) @@ -108,11 +113,13 @@ namespace MagicaCloth2 //========================================================================================= /// /// 領域のみ拡張する + /// すでにその長さの領域が確保されている場合は何もしない /// - /// - public void AddCapacity(int capacity) + /// + public void SetLength(int newLength) { - Expand(capacity, true); + if (newLength > length) + Expand(newLength - length, force: true, copy: true); } /// @@ -216,6 +223,16 @@ namespace MagicaCloth2 } } + public void AddRange(NativeArray narray, int start, int length) + { + if (length > 0) + { + Expand(length); + NativeArray.Copy(narray, start, nativeArray, count, length); + count += length; + } + } + public void AddRange(NativeList nlist) { Debug.Assert(nlist.IsCreated); @@ -481,7 +498,8 @@ namespace MagicaCloth2 /// /// /// 強制的に領域を追加 - void Expand(int dataLength, bool force = false) + /// 古いデータをコピーするかどうか + void Expand(int dataLength, bool force = false, bool copy = true) { int newlength = force ? length + dataLength : count + dataLength; @@ -499,8 +517,11 @@ namespace MagicaCloth2 var newNativeArray = new NativeArray(newlength, Allocator.Persistent); // copy - // コピーは使用分だけ - NativeArray.Copy(nativeArray, newNativeArray, count); + if (copy) + { + // コピーは使用分だけ + NativeArray.Copy(nativeArray, newNativeArray, count); + } nativeArray.Dispose(); nativeArray = newNativeArray; @@ -512,8 +533,8 @@ namespace MagicaCloth2 { StringBuilder sb = new StringBuilder(); - sb.AppendLine($"ExNativeArray Length:{Length} Count:{Count} IsValid:{IsValid}"); - sb.AppendLine("---- Datas[100] ----"); + sb.AppendLine($"ExSimpleNativeArray Length:{Length} Count:{Count} IsValid:{IsValid}"); + sb.AppendLine("---- Datas[~100] ----"); if (IsValid) { for (int i = 0; i < Length && i < 100; i++) @@ -524,5 +545,59 @@ namespace MagicaCloth2 return sb.ToString(); } + + //========================================================================================= + /// + /// シリアライズデータ + /// + [System.Serializable] + public class SerializationData + { + public int count; + public int length; + public byte[] arrayBytes; + } + + /// + /// シリアライズする + /// + /// + public SerializationData Serialize() + { + var data = new SerializationData(); + data.count = count; + data.length = length; + if (nativeArray.IsCreated && nativeArray.Length > 0) + { + data.arrayBytes = nativeArray.MC2ToRawBytes(); + } + + return data; + } + + /// + /// デシリアライズする + /// + /// + /// + public bool Deserialize(SerializationData data) + { + try + { + Dispose(); + count = data.count; + length = data.length; + if (data.length > 0 && data.arrayBytes != null) + { + nativeArray = NativeArrayExtensions.MC2FromRawBytes(data.arrayBytes, Allocator.Persistent); + } + return true; + } + catch (Exception exception) + { + Debug.LogException(exception); + return false; + } + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExSimpleNativeArray.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExSimpleNativeArray.cs.meta index 48f0b66a..dbaee99b 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExSimpleNativeArray.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExSimpleNativeArray.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExSimpleNativeArray.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExTransformAccessArray.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExTransformAccessArray.cs.meta index d4531d98..efa3d89a 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExTransformAccessArray.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExTransformAccessArray.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/ExTransformAccessArray.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList128BytesExtensions.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList128BytesExtensions.cs index da2f0589..5faa7ec6 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList128BytesExtensions.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList128BytesExtensions.cs @@ -15,7 +15,7 @@ namespace MagicaCloth2 // Common //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsCapacity(ref this FixedList128Bytes fixedList) where T : unmanaged, IEquatable + public static bool MC2IsCapacity(ref this FixedList128Bytes fixedList) where T : unmanaged, IEquatable { return fixedList.Length >= fixedList.Capacity; } @@ -30,7 +30,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Set(ref this FixedList128Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Set(ref this FixedList128Bytes fixedList, T item) where T : unmanaged, IEquatable { if (fixedList.Contains(item) == false) { @@ -46,7 +46,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void SetLimit(ref this FixedList128Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2SetLimit(ref this FixedList128Bytes fixedList, T item) where T : unmanaged, IEquatable { if (fixedList.Length >= fixedList.Capacity) { @@ -67,7 +67,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveItemAtSwapBack(ref this FixedList128Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2RemoveItemAtSwapBack(ref this FixedList128Bytes fixedList, T item) where T : unmanaged, IEquatable { for (int i = 0; i < fixedList.Length; i++) { @@ -83,13 +83,13 @@ namespace MagicaCloth2 // Stack //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Push(ref this FixedList128Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Push(ref this FixedList128Bytes fixedList, T item) where T : unmanaged, IEquatable { fixedList.Add(item); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Pop(ref this FixedList128Bytes fixedList) where T : unmanaged, IEquatable + public static T MC2Pop(ref this FixedList128Bytes fixedList) where T : unmanaged, IEquatable { int index = fixedList.Length - 1; T item = fixedList[index]; @@ -101,13 +101,13 @@ namespace MagicaCloth2 // Queue //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Enqueue(ref this FixedList128Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Enqueue(ref this FixedList128Bytes fixedList, T item) where T : unmanaged, IEquatable { fixedList.Add(item); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Dequque(ref this FixedList128Bytes fixedList) where T : unmanaged, IEquatable + public static T MC2Dequque(ref this FixedList128Bytes fixedList) where T : unmanaged, IEquatable { T item = fixedList[0]; fixedList.RemoveAt(0); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList128BytesExtensions.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList128BytesExtensions.cs.meta index 6d65c8c2..c26e7ee1 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList128BytesExtensions.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList128BytesExtensions.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList128BytesExtensions.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList32BytesExtensions.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList32BytesExtensions.cs index adb33b33..43707fcb 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList32BytesExtensions.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList32BytesExtensions.cs @@ -8,14 +8,13 @@ using UnityEngine; namespace MagicaCloth2 { - //[BurstCompatible] public static class FixedList32BytesExtensions { //===================================================================== // Common //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsCapacity(ref this FixedList32Bytes fixedList) where T : unmanaged, IEquatable + public static bool MC2IsCapacity(ref this FixedList32Bytes fixedList) where T : unmanaged, IEquatable { return fixedList.Length >= fixedList.Capacity; } @@ -31,7 +30,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Set(ref this FixedList32Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Set(ref this FixedList32Bytes fixedList, T item) where T : unmanaged, IEquatable { if (fixedList.Contains(item) == false) { @@ -47,7 +46,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void SetLimit(ref this FixedList32Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2SetLimit(ref this FixedList32Bytes fixedList, T item) where T : unmanaged, IEquatable { if (fixedList.Length >= fixedList.Capacity) { @@ -68,7 +67,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveItemAtSwapBack(ref this FixedList32Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2RemoveItemAtSwapBack(ref this FixedList32Bytes fixedList, T item) where T : unmanaged, IEquatable { for (int i = 0; i < fixedList.Length; i++) { @@ -84,13 +83,13 @@ namespace MagicaCloth2 // Stack //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Push(ref this FixedList32Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Push(ref this FixedList32Bytes fixedList, T item) where T : unmanaged, IEquatable { fixedList.Add(item); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Pop(ref this FixedList32Bytes fixedList) where T : unmanaged, IEquatable + public static T MC2Pop(ref this FixedList32Bytes fixedList) where T : unmanaged, IEquatable { int index = fixedList.Length - 1; T item = fixedList[index]; @@ -102,13 +101,13 @@ namespace MagicaCloth2 // Queue //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Enqueue(ref this FixedList32Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Enqueue(ref this FixedList32Bytes fixedList, T item) where T : unmanaged, IEquatable { fixedList.Add(item); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Dequque(ref this FixedList32Bytes fixedList) where T : unmanaged, IEquatable + public static T MC2Dequque(ref this FixedList32Bytes fixedList) where T : unmanaged, IEquatable { T item = fixedList[0]; fixedList.RemoveAt(0); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList32BytesExtensions.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList32BytesExtensions.cs.meta index 728a3aa4..6697acc9 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList32BytesExtensions.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList32BytesExtensions.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList32BytesExtensions.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList4096BytesExtensions.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList4096BytesExtensions.cs index 05b01e01..8e327769 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList4096BytesExtensions.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList4096BytesExtensions.cs @@ -15,7 +15,7 @@ namespace MagicaCloth2 // Common //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsCapacity(ref this FixedList4096Bytes fixedList) where T : unmanaged, IEquatable + public static bool MC2IsCapacity(ref this FixedList4096Bytes fixedList) where T : unmanaged, IEquatable { return fixedList.Length >= fixedList.Capacity; } @@ -30,7 +30,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Set(ref this FixedList4096Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Set(ref this FixedList4096Bytes fixedList, T item) where T : unmanaged, IEquatable { if (fixedList.Contains(item) == false) { @@ -46,7 +46,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void SetLimit(ref this FixedList4096Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2SetLimit(ref this FixedList4096Bytes fixedList, T item) where T : unmanaged, IEquatable { if (fixedList.Length >= fixedList.Capacity) { @@ -67,7 +67,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveItemAtSwapBack(ref this FixedList4096Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2RemoveItemAtSwapBack(ref this FixedList4096Bytes fixedList, T item) where T : unmanaged, IEquatable { for (int i = 0; i < fixedList.Length; i++) { @@ -83,13 +83,13 @@ namespace MagicaCloth2 // Stack //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Push(ref this FixedList4096Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Push(ref this FixedList4096Bytes fixedList, T item) where T : unmanaged, IEquatable { fixedList.Add(item); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Pop(ref this FixedList4096Bytes fixedList) where T : unmanaged, IEquatable + public static T MC2Pop(ref this FixedList4096Bytes fixedList) where T : unmanaged, IEquatable { int index = fixedList.Length - 1; T item = fixedList[index]; @@ -101,13 +101,13 @@ namespace MagicaCloth2 // Queue //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Enqueue(ref this FixedList4096Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Enqueue(ref this FixedList4096Bytes fixedList, T item) where T : unmanaged, IEquatable { fixedList.Add(item); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Dequque(ref this FixedList4096Bytes fixedList) where T : unmanaged, IEquatable + public static T MC2Dequque(ref this FixedList4096Bytes fixedList) where T : unmanaged, IEquatable { T item = fixedList[0]; fixedList.RemoveAt(0); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList4096BytesExtensions.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList4096BytesExtensions.cs.meta index 6bfe50e8..328a2b24 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList4096BytesExtensions.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList4096BytesExtensions.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList4096BytesExtensions.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList512BytesExtensions.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList512BytesExtensions.cs index 31c6a170..e7123739 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList512BytesExtensions.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList512BytesExtensions.cs @@ -15,7 +15,7 @@ namespace MagicaCloth2 // Common //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsCapacity(ref this FixedList512Bytes fixedList) where T : unmanaged, IEquatable + public static bool MC2IsCapacity(ref this FixedList512Bytes fixedList) where T : unmanaged, IEquatable { return fixedList.Length >= fixedList.Capacity; } @@ -30,7 +30,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Set(ref this FixedList512Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Set(ref this FixedList512Bytes fixedList, T item) where T : unmanaged, IEquatable { if (fixedList.Contains(item) == false) { @@ -46,7 +46,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void SetLimit(ref this FixedList512Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2SetLimit(ref this FixedList512Bytes fixedList, T item) where T : unmanaged, IEquatable { if (fixedList.Length >= fixedList.Capacity) { @@ -67,7 +67,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveItemAtSwapBack(ref this FixedList512Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2RemoveItemAtSwapBack(ref this FixedList512Bytes fixedList, T item) where T : unmanaged, IEquatable { for (int i = 0; i < fixedList.Length; i++) { @@ -83,13 +83,13 @@ namespace MagicaCloth2 // Stack //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Push(ref this FixedList512Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Push(ref this FixedList512Bytes fixedList, T item) where T : unmanaged, IEquatable { fixedList.Add(item); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Pop(ref this FixedList512Bytes fixedList) where T : unmanaged, IEquatable + public static T MC2Pop(ref this FixedList512Bytes fixedList) where T : unmanaged, IEquatable { int index = fixedList.Length - 1; T item = fixedList[index]; @@ -101,13 +101,13 @@ namespace MagicaCloth2 // Queue //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Enqueue(ref this FixedList512Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Enqueue(ref this FixedList512Bytes fixedList, T item) where T : unmanaged, IEquatable { fixedList.Add(item); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Dequque(ref this FixedList512Bytes fixedList) where T : unmanaged, IEquatable + public static T MC2Dequque(ref this FixedList512Bytes fixedList) where T : unmanaged, IEquatable { T item = fixedList[0]; fixedList.RemoveAt(0); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList512BytesExtensions.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList512BytesExtensions.cs.meta index 6137758c..cd057d45 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList512BytesExtensions.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList512BytesExtensions.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList512BytesExtensions.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList64BytesExtensions.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList64BytesExtensions.cs index 69543bc2..7aad0bce 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList64BytesExtensions.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList64BytesExtensions.cs @@ -15,7 +15,7 @@ namespace MagicaCloth2 // Common //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsCapacity(ref this FixedList64Bytes fixedList) where T : unmanaged, IEquatable + public static bool MC2IsCapacity(ref this FixedList64Bytes fixedList) where T : unmanaged, IEquatable { return fixedList.Length >= fixedList.Capacity; } @@ -30,7 +30,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Set(ref this FixedList64Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Set(ref this FixedList64Bytes fixedList, T item) where T : unmanaged, IEquatable { if (fixedList.Contains(item) == false) { @@ -46,7 +46,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void SetLimit(ref this FixedList64Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2SetLimit(ref this FixedList64Bytes fixedList, T item) where T : unmanaged, IEquatable { if (fixedList.Length >= fixedList.Capacity) { @@ -67,7 +67,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveItemAtSwapBack(ref this FixedList64Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2RemoveItemAtSwapBack(ref this FixedList64Bytes fixedList, T item) where T : unmanaged, IEquatable { for (int i = 0; i < fixedList.Length; i++) { @@ -83,13 +83,13 @@ namespace MagicaCloth2 // Stack //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Push(ref this FixedList64Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Push(ref this FixedList64Bytes fixedList, T item) where T : unmanaged, IEquatable { fixedList.Add(item); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Pop(ref this FixedList64Bytes fixedList) where T : unmanaged, IEquatable + public static T MC2Pop(ref this FixedList64Bytes fixedList) where T : unmanaged, IEquatable { int index = fixedList.Length - 1; T item = fixedList[index]; @@ -101,13 +101,13 @@ namespace MagicaCloth2 // Queue //===================================================================== [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Enqueue(ref this FixedList64Bytes fixedList, T item) where T : unmanaged, IEquatable + public static void MC2Enqueue(ref this FixedList64Bytes fixedList, T item) where T : unmanaged, IEquatable { fixedList.Add(item); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Dequque(ref this FixedList64Bytes fixedList) where T : unmanaged, IEquatable + public static T MC2Dequque(ref this FixedList64Bytes fixedList) where T : unmanaged, IEquatable { T item = fixedList[0]; fixedList.RemoveAt(0); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList64BytesExtensions.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList64BytesExtensions.cs.meta index e57832de..47a38d90 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList64BytesExtensions.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList64BytesExtensions.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/FixedList64BytesExtensions.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeArrayExtensions.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeArrayExtensions.cs index 1a01f283..2abce8c1 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeArrayExtensions.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeArrayExtensions.cs @@ -8,14 +8,14 @@ namespace MagicaCloth2 /// /// NativeArrayの拡張メソッド /// - static class NativeArrayExtensions + public static class NativeArrayExtensions { /// /// NativeArrayが確保されている場合のみDispose()する /// /// /// - public static void DisposeSafe(ref this NativeArray array) where T : unmanaged + public static void MC2DisposeSafe(ref this NativeArray array) where T : unmanaged { if (array.IsCreated) array.Dispose(); @@ -31,13 +31,55 @@ namespace MagicaCloth2 /// /// /// - public static void Resize(ref this NativeArray array, int size, Allocator allocator = Allocator.Persistent, NativeArrayOptions options = NativeArrayOptions.ClearMemory) where T : unmanaged + public static void MC2Resize(ref this NativeArray array, int size, Allocator allocator = Allocator.Persistent, NativeArrayOptions options = NativeArrayOptions.ClearMemory) where T : unmanaged { if (array.IsCreated == false || array.Length < size) { - array.DisposeSafe(); + array.MC2DisposeSafe(); array = new NativeArray(size, allocator, options); } } + + /// + /// NativeArrayをbyte[]に変換する + /// + /// + /// + /// + public static byte[] MC2ToRawBytes(ref this NativeArray array) where T : unmanaged + { + if (array.IsCreated == false || array.Length == 0) + return null; + var slice = new NativeSlice(array).SliceConvert(); + var bytes = new byte[slice.Length]; + slice.CopyTo(bytes); + return bytes; + } + + /// + /// byte[]からNativeArrayを作成する + /// + /// + /// + /// + /// + public static NativeArray MC2FromRawBytes(byte[] bytes, Allocator allocator = Allocator.Persistent) where T : unmanaged + { + if (bytes == null) + return new NativeArray(); + + int structSize = Unity.Collections.LowLevel.Unsafe.UnsafeUtility.SizeOf(); + + int length = bytes.Length / structSize; + var array = new NativeArray(length, allocator); + if (length > 0) + { + using var byteArray = new NativeArray(bytes, Allocator.Temp); + //using var byteArray = new NativeArray(bytes, Allocator.Persistent); + var slice = new NativeSlice(byteArray).SliceConvert(); + slice.CopyTo(array); + } + return array; + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeArrayExtensions.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeArrayExtensions.cs.meta index 22842ef3..8e56dee8 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeArrayExtensions.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeArrayExtensions.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeArrayExtensions.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeMultiHashMapExtensions.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeMultiHashMapExtensions.cs index 5f577af4..c78fd383 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeMultiHashMapExtensions.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeMultiHashMapExtensions.cs @@ -2,17 +2,21 @@ // Copyright (c) 2023 MagicaSoft. // https://magicasoft.jp using System; +using Unity.Burst; using Unity.Collections; +using Unity.Jobs; +using Unity.Mathematics; +using UnityEngine; namespace MagicaCloth2 { /// /// NativeMultiHashMapの拡張メソッド /// - static class NativeMultiHashMapExtensions + public static class NativeMultiHashMapExtensions { /// - /// NativeMultiHashMapのキーに指定データが存在するか判定する + /// NativeParallelMultiHashMapのキーに指定データが存在するか判定する /// /// /// @@ -21,9 +25,9 @@ namespace MagicaCloth2 /// /// #if MC2_COLLECTIONS_200 - public static bool Contains(ref this NativeParallelMultiHashMap map, TKey key, TValue value) where TKey : unmanaged, IEquatable where TValue : unmanaged, IEquatable + public static bool MC2Contains(ref this NativeParallelMultiHashMap map, TKey key, TValue value) where TKey : unmanaged, IEquatable where TValue : unmanaged, IEquatable #else - public static bool Contains(ref this NativeParallelMultiHashMap map, TKey key, TValue value) where TKey : struct, IEquatable where TValue : struct, IEquatable + public static bool MC2Contains(ref this NativeParallelMultiHashMap map, TKey key, TValue value) where TKey : struct, IEquatable where TValue : struct, IEquatable #endif { foreach (TValue val in map.GetValuesForKey(key)) @@ -35,7 +39,7 @@ namespace MagicaCloth2 } /// - /// NativeMultiHashMapのキーに対して重複なしのデータを追加する + /// NativeParallelMultiHashMapキーに対して重複なしのデータを追加する /// すでにキーに同じデータが存在する場合は追加しない。 /// /// @@ -44,26 +48,59 @@ namespace MagicaCloth2 /// /// #if MC2_COLLECTIONS_200 - public static void UniqueAdd(ref this NativeParallelMultiHashMap map, TKey key, TValue value) where TKey : unmanaged, IEquatable where TValue : unmanaged, IEquatable + public static void MC2UniqueAdd(ref this NativeParallelMultiHashMap map, TKey key, TValue value) where TKey : unmanaged, IEquatable where TValue : unmanaged, IEquatable #else - public static void UniqueAdd(ref this NativeParallelMultiHashMap map, TKey key, TValue value) where TKey : struct, IEquatable where TValue : struct, IEquatable + public static void MC2UniqueAdd(ref this NativeParallelMultiHashMap map, TKey key, TValue value) where TKey : struct, IEquatable where TValue : struct, IEquatable #endif { - if (map.Contains(key, value) == false) + if (map.MC2Contains(key, value) == false) { map.Add(key, value); } } + /// + /// NativeMultiHashMapのキーに存在するデータを削除する + /// + /// + /// + /// + /// + /// + /// +#if MC2_COLLECTIONS_200 + public static bool MC2RemoveValue(ref this NativeParallelMultiHashMap map, TKey key, TValue value) where TKey : unmanaged, IEquatable where TValue : unmanaged, IEquatable +#else + public static bool MC2RemoveValue(ref this NativeParallelMultiHashMap map, TKey key, TValue value) where TKey : struct, IEquatable where TValue : struct, IEquatable +#endif + { + NativeParallelMultiHashMapIterator it; + TValue item; + if (map.TryGetFirstValue(key, out item, out it)) + { + do + { + if (item.Equals(value)) + { + map.Remove(it); + return true; + } + } + while (map.TryGetNextValue(out item, ref it)); + } + + return false; + } + /// /// 現在のキーのデータをFixedList512Bytesに変換して返す /// /// /// #if MC2_COLLECTIONS_200 - public static FixedList512Bytes ToFixedList512Bytes(ref this NativeParallelMultiHashMap map, TKey key) where TKey : unmanaged, IEquatable where TValue : unmanaged, IEquatable + public static FixedList512Bytes MC2ToFixedList512Bytes(ref this NativeParallelMultiHashMap map, TKey key) where TKey : unmanaged, IEquatable where TValue : unmanaged, IEquatable #else - public static FixedList512Bytes ToFixedList512Bytes(ref this NativeParallelMultiHashMap map, TKey key) where TKey : struct, IEquatable where TValue : unmanaged, IEquatable + public static FixedList512Bytes MC2ToFixedList512Bytes(ref this NativeParallelMultiHashMap map, TKey key) where TKey : struct, IEquatable where TValue : unmanaged, IEquatable #endif { var fixlist = new FixedList512Bytes(); @@ -84,9 +121,9 @@ namespace MagicaCloth2 /// /// #if MC2_COLLECTIONS_200 - public static FixedList128Bytes ToFixedList128Bytes(ref this NativeParallelMultiHashMap map, TKey key) where TKey : unmanaged, IEquatable where TValue : unmanaged, IEquatable + public static FixedList128Bytes MC2ToFixedList128Bytes(ref this NativeParallelMultiHashMap map, TKey key) where TKey : unmanaged, IEquatable where TValue : unmanaged, IEquatable #else - public static FixedList128Bytes ToFixedList128Bytes(ref this NativeParallelMultiHashMap map, TKey key) where TKey : struct, IEquatable where TValue : unmanaged, IEquatable + public static FixedList128Bytes MC2ToFixedList128Bytes(ref this NativeParallelMultiHashMap map, TKey key) where TKey : struct, IEquatable where TValue : unmanaged, IEquatable #endif { var fixlist = new FixedList128Bytes(); @@ -100,5 +137,91 @@ namespace MagicaCloth2 return fixlist; } + + /// + /// NativeParallelMultiHashMapをKeyとValueの配列に変換します + /// + /// + /// + /// + /// +#if MC2_COLLECTIONS_200 + public static (TKey[], TValue[]) MC2Serialize(ref this NativeParallelMultiHashMap map) where TKey : unmanaged, IEquatable where TValue : unmanaged +#else + public static (TKey[], TValue[]) MC2Serialize(ref this NativeParallelMultiHashMap map) where TKey : struct, IEquatable where TValue : struct +#endif + { + if (map.IsCreated == false || map.Count() == 0 || map.IsEmpty) + return (null, null); + + using var keyNativeArray = map.GetKeyArray(Allocator.Persistent); + using var valueNativeArray = map.GetValueArray(Allocator.Persistent); + + return (keyNativeArray.ToArray(), valueNativeArray.ToArray()); + } + + /// + /// KeyとValueの配列からNativeParallelMultiHashMapを復元します + /// 高速化のためBurstを利用 + /// ジェネリック型ジョブは明示的に型を指定する必要があるため型ごとに関数が発生します + /// + /// + /// + /// + public static NativeParallelMultiHashMap MC2Deserialize(int2[] keyArray, ushort[] valueArray) + { + int keyCount = keyArray?.Length ?? 0; + int valueCount = valueArray?.Length ?? 0; + Debug.Assert(keyCount == valueCount); + var map = new NativeParallelMultiHashMap(keyCount, Allocator.Persistent); + if (keyCount > 0 && valueCount > 0) + { + using var keyNativeArray = new NativeArray(keyArray, Allocator.Persistent); + using var valueNativeArray = new NativeArray(valueArray, Allocator.Persistent); + var job = new SetParallelMultiHashMapJob() { map = map, keyArray = keyNativeArray, valueArray = valueNativeArray }; + job.Run(); + } + + return map; + } + + [BurstCompile] +#if MC2_COLLECTIONS_200 + struct SetParallelMultiHashMapJob : IJob where TKey : unmanaged, IEquatable where TValue : unmanaged +#else + struct SetParallelMultiHashMapJob : IJob where TKey : struct, IEquatable where TValue : struct +#endif + { + public NativeParallelMultiHashMap map; + [Unity.Collections.ReadOnly] + public NativeArray keyArray; + [Unity.Collections.ReadOnly] + public NativeArray valueArray; + + public void Execute() + { + int cnt = keyArray.Length; + for (int i = 0; i < cnt; i++) + { + map.Add(keyArray[i], valueArray[i]); + } + } + } + + /// + /// NativeParallelMultiHashMapが確保されている場合のみDispose()する + /// + /// + /// + /// +#if MC2_COLLECTIONS_200 + public static void MC2DisposeSafe(ref this NativeParallelMultiHashMap map) where TKey : unmanaged, IEquatable where TValue : unmanaged, IEquatable +#else + public static void MC2DisposeSafe(ref this NativeParallelMultiHashMap map) where TKey : struct, IEquatable where TValue : struct, IEquatable +#endif + { + if (map.IsCreated) + map.Dispose(); + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeMultiHashMapExtensions.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeMultiHashMapExtensions.cs.meta index 9b82e013..32c275c6 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeMultiHashMapExtensions.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeMultiHashMapExtensions.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeMultiHashMapExtensions.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs new file mode 100644 index 00000000..2ca0e18a --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs @@ -0,0 +1,30 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using Unity.Collections; + +namespace MagicaCloth2 +{ + /// + /// NativeParallelHashMapの拡張メソッド + /// + public static class NativeParallelHashMap + { + /// + /// NativeParallelMultiHashMapが確保されている場合のみDispose()する + /// + /// + /// + /// +#if MC2_COLLECTIONS_200 + public static void MC2DisposeSafe(ref this NativeParallelHashMap map) where TKey : unmanaged, IEquatable where TValue : unmanaged, IEquatable +#else + public static void MC2DisposeSafe(ref this NativeParallelHashMap map) where TKey : struct, IEquatable where TValue : struct, IEquatable +#endif + { + if (map.IsCreated) + map.Dispose(); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs.meta new file mode 100644 index 00000000..b96b1ac3 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f6dcd839c56f63b42af8231ec3cb1841 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeParallelHashMapExtensions.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeReferenceExtensions.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeReferenceExtensions.cs index 29517bc3..34013474 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeReferenceExtensions.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeReferenceExtensions.cs @@ -18,7 +18,7 @@ namespace MagicaCloth2 /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - unsafe public static int InterlockedStartIndex(ref this NativeReference counter, int dataCount) + unsafe public static int MC2InterlockedStartIndex(ref this NativeReference counter, int dataCount) { int* cntPt = (int*)counter.GetUnsafePtr(); int start = Interlocked.Add(ref *cntPt, dataCount) - dataCount; diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeReferenceExtensions.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeReferenceExtensions.cs.meta index 113aa86e..84f39149 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeReferenceExtensions.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeReferenceExtensions.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/NativeCollection/NativeReferenceExtensions.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/Exception.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/Exception.cs.meta index 35577257..3dce33c7 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/Exception.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/Exception.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/Exception.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/ResultCode.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/ResultCode.cs index 38dc5931..71bcac95 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/ResultCode.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/ResultCode.cs @@ -2,25 +2,31 @@ // Copyright (c) 2023 MagicaSoft. // https://magicasoft.jp using System.Diagnostics; +using UnityEngine; namespace MagicaCloth2 { /// /// 様々な処理の結果 /// + [System.Serializable] public struct ResultCode { + [SerializeField] volatile Define.Result result; /// /// 警告:警告は1つのみ保持 /// + [SerializeField] volatile Define.Result warning; public Define.Result Result => result; public static ResultCode None => new ResultCode(Define.Result.None); public static ResultCode Empty => new ResultCode(Define.Result.Empty); + public static ResultCode Success => new ResultCode(Define.Result.Success); + public static ResultCode Error => new ResultCode(Define.Result.Error); public ResultCode(Define.Result initResult) { @@ -119,9 +125,13 @@ namespace MagicaCloth2 case Define.Result.RenderSetup_Unreadable: return "It is necessary to turn on [Read/Write] in the model import settings."; case Define.Result.RenderSetup_Over65535vertices: - return "Original mesh must have no more than 65,535 vertices"; + return "Original mesh must have no more than 65,535 vertices."; case Define.Result.SerializeData_Over31Renderers: return $"There are {Define.System.MaxRendererCount} renderers that can be set."; + case Define.Result.Init_ScaleIsZero: + return "Component scale values is 0."; + case Define.Result.Init_NegativeScale: + return "Component has negative scale."; default: return null; } @@ -133,6 +143,8 @@ namespace MagicaCloth2 { case Define.Result.RenderMesh_VertexWeightIs5BonesOrMore: return "The source renderer mesh contains vertex weights that utilize more than 5 bones.\nA weight of 5 or more is invalid."; + case Define.Result.Init_NonUniformScale: + return "Component scale values ​​should be uniform.\nIf the scale is not uniform, there is a risk that it will not work properly."; default: return null; } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/ResultCode.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/ResultCode.cs.meta index 8860d020..345aaf9a 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/ResultCode.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/ResultCode.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/ResultCode/ResultCode.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/TimeSpan.cs b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/TimeSpan.cs index 272623ca..b2fcd618 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/TimeSpan.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/TimeSpan.cs @@ -13,7 +13,7 @@ namespace MagicaCloth2 string name = string.Empty; DateTime stime; DateTime etime; - //bool isFinish; + bool isFinish; public TimeSpan() { } @@ -21,21 +21,23 @@ namespace MagicaCloth2 { this.name = name; stime = DateTime.Now; + isFinish = false; } public void Start() { stime = DateTime.Now; + isFinish = false; } public void Finish() { - etime = DateTime.Now; - //if (isFinish == false) - //{ - // etime = DateTime.Now; - // isFinish = true; - //} + //etime = DateTime.Now; + if (isFinish == false) + { + etime = DateTime.Now; + isFinish = true; + } } public double TotalSeconds() @@ -60,5 +62,10 @@ namespace MagicaCloth2 { Develop.DebugLog(this); } + + public void Log() + { + Develop.Log(this); + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/TimeSpan.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/TimeSpan.cs.meta index 5879e4fc..8200faa9 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/TimeSpan.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/TimeSpan.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/TimeSpan.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/UnityTimeSpan.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/UnityTimeSpan.cs.meta index 21ad38be..2e8c3456 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/UnityTimeSpan.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/UnityTimeSpan.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/Utility/Time/UnityTimeSpan.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshInputOutput.cs b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshInputOutput.cs index 66a990df..ad6bc231 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshInputOutput.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshInputOutput.cs @@ -19,7 +19,7 @@ namespace MagicaCloth2 /// /// /// - public void ImportFrom(RenderSetupData rsetup) + public void ImportFrom(RenderSetupData rsetup, int uvChannel) { try { @@ -44,7 +44,7 @@ namespace MagicaCloth2 rsetup.transformIdList, rsetup.transformParentIdList, rsetup.rootTransformIdList, - rsetup.transformLocalPositins, + rsetup.transformLocalPositions, rsetup.transformLocalRotations, rsetup.transformPositions, rsetup.transformRotations, @@ -68,7 +68,7 @@ namespace MagicaCloth2 // メッシュタイプ meshType = MeshType.NormalMesh; isBoneCloth = false; - ImportMeshType(rsetup, indices); + ImportMeshType(rsetup, indices, uvChannel); // スキニングメッシュでは1回スキニングを行いクロスローカル空間に姿勢を変換する if (rsetup.hasBoneWeight) @@ -129,7 +129,7 @@ namespace MagicaCloth2 /// /// /// - void ImportMeshType(RenderSetupData rsetup, int[] transformIndices) + void ImportMeshType(RenderSetupData rsetup, int[] transformIndices, int uvChannel) { // root bone skinRootIndex = transformIndices[rsetup.skinRootBoneIndex]; @@ -155,6 +155,7 @@ namespace MagicaCloth2 meshData.GetNormals(localNormals.GetNativeArray()); if (meshData.HasVertexAttribute(UnityEngine.Rendering.VertexAttribute.Tangent)) { + // 接線情報がメッシュに存在する using var tangents = new NativeArray(vcnt, Allocator.TempJob); meshData.GetTangents(tangents); // tangent変換(Vector4->float3) @@ -162,6 +163,7 @@ namespace MagicaCloth2 } else { + // 接線情報がメッシュに存在しない Develop.DebugLogWarning($"[{name}] Tangents not found!"); // tangentを生成する // このtangentは描画用では無く姿勢制御用なのである意味適当でも大丈夫 @@ -174,11 +176,19 @@ namespace MagicaCloth2 } if (meshData.HasVertexAttribute(UnityEngine.Rendering.VertexAttribute.TexCoord0)) { - meshData.GetUVs(0, uv.GetNativeArray()); + uvChannel = Mathf.Clamp(uvChannel, 0, 7); + UnityEngine.Rendering.VertexAttribute useTexCoord = UnityEngine.Rendering.VertexAttribute.TexCoord0 + uvChannel; + if (meshData.HasVertexAttribute(useTexCoord) == false) + { + Develop.LogWarning($"[{name}] UV{uvChannel} not found! => Use UV0."); + uvChannel = 0; + } + //Debug.Log($"Fetch UV:{uvChannel}"); + meshData.GetUVs(uvChannel, uv.GetNativeArray()); } else { - Debug.LogWarning($"[{name}] UV not found!"); + Develop.LogWarning($"[{name}] UV0 not found!"); } // 属性 @@ -439,7 +449,7 @@ namespace MagicaCloth2 skinBoneTransformIndices.AddRange(transformIndices, rsetup.skinBoneCount); skinBoneBindPoses.AddRange(vcnt); - // Transformの情報をローカル空間に変換し頂点情報に割り当てる + // Transformの情報をクロスローカル空間に変換し頂点情報に割り当てる // およびバインドポーズの算出 var WtoL = rsetup.initRenderWorldtoLocal; var LtoW = rsetup.initRenderLocalToWorld; @@ -899,13 +909,17 @@ namespace MagicaCloth2 quaternion rot = transformRotations[vindex]; float3 scl = transformScales[vindex]; - // トランスフォーム姿勢をローカル空間に変換する + // トランスフォーム姿勢をクロスローカル空間に変換する + // オリジナル +#if true float3 lpos = MathUtility.InverseTransformPoint(pos, WtoL); float3 lnor, ltan; lnor = math.mul(rot, math.up()); ltan = math.mul(rot, math.forward()); lnor = MathUtility.InverseTransformDirection(lnor, WtoL); ltan = MathUtility.InverseTransformDirection(ltan, WtoL); +#endif + //Debug.Log($"Import [{vindex}] lpos:{lpos}, lnor:{lnor}, ltan:{ltan}"); localPositions[vindex] = lpos; localNormals[vindex] = lnor; @@ -928,7 +942,7 @@ namespace MagicaCloth2 /// レンダーデータからインポートする /// /// - public void ImportFrom(RenderData renderData) + public void ImportFrom(RenderData renderData, int uvChannel) { try { @@ -938,7 +952,7 @@ namespace MagicaCloth2 throw new MagicaClothProcessingException(); } - ImportFrom(renderData.setupData); + ImportFrom(renderData.setupData, uvChannel); } catch (MagicaClothProcessingException) { @@ -1764,16 +1778,6 @@ namespace MagicaCloth2 return transformData.GetTransformFromIndex(centerTransformIndex); } - public float4x4 GetCenterLocalToWorldMatrix() - { - return transformData.GetLocalToWorldMatrix(centerTransformIndex); - } - - public float4x4 GetCenterWorldToLocalMatrix() - { - return transformData.GetWorldToLocalMatrix(centerTransformIndex); - } - /// /// カスタムスキニング用ボーンを登録する /// @@ -1828,6 +1832,7 @@ namespace MagicaCloth2 } //========================================================================================= +#if false /// /// UnityMeshに出力する(メインスレッドのみ) /// ※ほぼデバッグ用 @@ -1893,93 +1898,6 @@ namespace MagicaCloth2 return mesh; } - - /// - /// メッシュの基準トランスフォームを返す - /// 通常はレンダラーのtransform - /// - /// - public Transform ExportCenterTransform() - { - return transformData.GetTransformFromIndex(centerTransformIndex); - } - - public Transform ExportSkinRootBone() - { - return transformData.GetTransformFromIndex(skinRootIndex); - } - - /// - /// メッシュのスキニング用ボーンリストを返す - /// - /// - public List ExportSkinningBones() - { - var sbones = new List(SkinBoneCount); - for (int i = 0; i < SkinBoneCount; i++) - { - sbones.Add(transformData.GetTransformFromIndex(skinBoneTransformIndices[i])); - } - return sbones; - } - - /// - /// メッシュのバウンディングボックスを返す - /// スキニングの場合はスキニングルートボーンからのバウンディングボックスとなる - /// それ以外はセンターボーンからのバウンディングボックスとなる - /// - /// - /*public Bounds ExportBounds() - { - float3 offset = 0; - if (skinRootIndex >= 0 && centerTransformIndex != skinRootIndex) - { - // スキニングのルートボーンが別の場合 - // ちょっと面倒 - float3 wmin = transformData.TransformPoint(centerTransformIndex, boundingBox.Value.Min); - float3 wmax = transformData.TransformPoint(centerTransformIndex, boundingBox.Value.Max); - float3 lmin = transformData.InverseTransformPoint(skinRootIndex, wmin); - float3 lmax = transformData.InverseTransformPoint(skinRootIndex, wmax); - float3 cen = (lmax + lmin) * 0.5f; - float3 size = math.abs(lmax - lmin); - return new Bounds(cen, size); - } - else - { - return new Bounds(boundingBox.Value.Center, boundingBox.Value.Extents); - } - }*/ - - /// - /// 現在のメッシュをレンダラーに反映させる(主にデバッグ用) - /// - /// - public Mesh ToRenderer(Renderer ren) - { - Mesh mesh = null; - if (IsSuccess == false) - return mesh; - - if (ren is MeshRenderer) - { - mesh = ExportToMesh(); - var filter = ren.GetComponent(); - filter.mesh = mesh; - } - else if (ren is SkinnedMeshRenderer) - { - var sren = ren as SkinnedMeshRenderer; - mesh = ExportToMesh(true); - var rootBone = ExportSkinRootBone(); - var skinBones = ExportSkinningBones().ToArray(); - - sren.rootBone = rootBone; - sren.bones = skinBones; - sren.sharedMesh = mesh; - } - - return mesh; - } - +#endif } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshInputOutput.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshInputOutput.cs.meta index 31bb21bd..c900d9f5 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshInputOutput.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshInputOutput.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshInputOutput.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshMapping.cs b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshMapping.cs index a1740cc8..b6e54fc0 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshMapping.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshMapping.cs @@ -237,6 +237,7 @@ namespace MagicaCloth2 } } + [BurstCompile] struct Mapping_CalcDirectWeightJob : IJob { // data @@ -282,10 +283,10 @@ namespace MagicaCloth2 // ウエイトバッファ var weights = new ExCostSortedList4(-1); - stack.Push(pindex); + stack.MC2Push(pindex); while (stack.IsEmpty == false) { - pindex = stack.Pop(); + pindex = stack.MC2Pop(); if (useSet.Contains(pindex)) continue; @@ -305,7 +306,7 @@ namespace MagicaCloth2 // 次の接続 DataUtility.Unpack12_20(proxyVertexToVertexIndexArray[pindex], out var dcnt, out var dstart); - for (int i = 0; i < dcnt && stack.IsCapacity() == false; i++) + for (int i = 0; i < dcnt && stack.MC2IsCapacity() == false; i++) { ushort tindex = proxyVertexToVertexDataArray[dstart + i]; @@ -317,7 +318,7 @@ namespace MagicaCloth2 if (dist > weightLength) continue; - stack.Push(tindex); + stack.MC2Push(tindex); } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshMapping.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshMapping.cs.meta index 5e76ccff..aba21227 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshMapping.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshMapping.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshMapping.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshOptimization.cs b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshOptimization.cs index 74fc3068..26b879a8 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshOptimization.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshOptimization.cs @@ -94,13 +94,13 @@ namespace MagicaCloth2 if (edgeToTriangleList.ContainsKey(edge)) { var tlist = edgeToTriangleList[edge]; - tlist.Set(i); + tlist.MC2Set(i); edgeToTriangleList[edge] = tlist; } else { var tlist = new FixedList128Bytes(); - tlist.Set(i); + tlist.MC2Set(i); edgeToTriangleList.Add(edge, tlist); } } diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshOptimization.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshOptimization.cs.meta index bc413aad..16e02d1f 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshOptimization.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshOptimization.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshOptimization.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshProxy.cs b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshProxy.cs index b4545261..20654dec 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshProxy.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshProxy.cs @@ -346,9 +346,6 @@ namespace MagicaCloth2 { center = center, localPositions = localPositions.GetNativeArray(), - vertexParentIndices = vertexParentIndices, - vertexChildIndexArray = vertexChildIndexArray, - vertexChildDataArray = vertexChildDataArray, localNormals = localNormals.GetNativeArray(), localTangents = localTangents.GetNativeArray(), @@ -356,109 +353,14 @@ namespace MagicaCloth2 }; job1.Run(vcnt); } -#if false // ★どうもうまくいかないので一旦停止! - // 頂点ウエイトから - else if (mode == NormalAlignmentSettings.AlignmentMode.BoneWeight) - { - var job2 = new ProxyNormalWeightAdjustmentJob() - { - WtoL = initWorldToLocal, - localPositions = localPositions.GetNativeArray(), - boneWeights = boneWeights.GetNativeArray(), - - transformPositionArray = transformData.positionArray.GetNativeArray(), - - localNormals = localNormals.GetNativeArray(), - localTangents = localTangents.GetNativeArray(), - normalAdjustmentRotations = normalAdjustmentRotations, - }; - job2.Run(vcnt); - } -#endif } -#if false - [BurstCompile] - struct ProxyNormalWeightAdjustmentJob : IJobParallelFor - { - public float4x4 WtoL; - [Unity.Collections.ReadOnly] - public NativeArray localPositions; - [Unity.Collections.ReadOnly] - public NativeArray boneWeights; - - // transform - [Unity.Collections.ReadOnly] - public NativeArray transformPositionArray; - - // out - //[Unity.Collections.WriteOnly] - public NativeArray localNormals; - //[Unity.Collections.WriteOnly] - public NativeArray localTangents; - [Unity.Collections.WriteOnly] - public NativeArray normalAdjustmentRotations; - - public void Execute(int vindex) - { - var lpos = localPositions[vindex]; - var bw = boneWeights[vindex]; - - // 現在の回転 - var lrot = MathUtility.ToRotation(localNormals[vindex], localTangents[vindex]); - - // 影響するボーンへの方向をまとめる - float3 bv = 0; - int bcnt = bw.Count; - if (bcnt == 0) - return; - for (int i = 0; i < bcnt; i++) - { - var bonePos = math.transform(WtoL, transformPositionArray[bw.boneIndices[i]]); - //var v = transformPositionArray[bw.boneIndices[i]] - lpos; - var v = lpos - bonePos; - v = math.normalizesafe(v, float3.zero); - v *= bw.weights[i]; - bv += v; - } - if (math.lengthsq(bv) < Define.System.Epsilon) - return; - - // 法線確定 - float3 n = math.normalize(bv); - - // 法線をもとに接線を計算する - var lnor = localNormals[vindex]; - var ltan = localTangents[vindex]; - var dotNormal = math.dot(n, lnor); - var dotTangent = math.dot(n, ltan); - float3 tv = dotNormal < dotTangent ? lnor : ltan; - float3 tan = math.cross(tv, n); - - //localNormals[vindex] = tan; - //localTangents[vindex] = n; - localNormals[vindex] = n; - localTangents[vindex] = tan; - var nrot = MathUtility.ToRotation(n, tan); - - // 補正用回転を算出し格納する - normalAdjustmentRotations[vindex] = math.mul(math.inverse(lrot), nrot); - } - } -#endif - [BurstCompile] struct ProxyNormalRadiationAdjustmentJob : IJobParallelFor { public float3 center; [Unity.Collections.ReadOnly] public NativeArray localPositions; - [Unity.Collections.ReadOnly] - public NativeArray vertexParentIndices; - [Unity.Collections.ReadOnly] - public NativeArray vertexChildIndexArray; - [Unity.Collections.ReadOnly] - public NativeArray vertexChildDataArray; // out public NativeArray localNormals; @@ -472,58 +374,33 @@ namespace MagicaCloth2 var v = lpos - center; if (math.length(v) < Define.System.Epsilon) return; - v = math.normalize(v); + + // 指定されたセンターからの放射方向に法線を変更する + var n = math.normalize(v); // 現在の回転 - var lrot = MathUtility.ToRotation(localNormals[vindex], localTangents[vindex]); + var ln = localNormals[vindex]; + var lt = localTangents[vindex]; + var lrot = MathUtility.ToRotation(ln, lt); - // 子がいる場合は子へのベクトルから算出 - var nrot = lrot; - int pindex = vertexParentIndices[vindex]; - var pack = vertexChildIndexArray[vindex]; - DataUtility.Unpack12_20(pack, out var dcnt, out var dstart); - if (dcnt > 0) + // 接線を補正する + float dot = math.dot(n, lt); + if (dot < 0.99f) { - float3 cv = 0; - for (int i = 0; i < dcnt; i++) - { - int cindex = vertexChildDataArray[dstart + i]; - cv += localPositions[cindex] - lpos; - } - if (math.lengthsq(cv) > Define.System.Epsilon) - { - cv = math.normalize(cv); - float3 n = math.cross(cv, v); - n = math.cross(n, cv); - - if (math.lengthsq(n) > Define.System.Epsilon) - { - n = math.normalize(n); - localNormals[vindex] = n; - localTangents[vindex] = cv; - nrot = MathUtility.ToRotation(n, cv); - } - } + float3 bn = math.normalize(math.cross(n, lt)); + lt = math.normalize(math.cross(bn, n)); } - // 子がいなく親がいる場合は親からのベクトルから算出 - else if (pindex >= 0) + else { - var ppos = localPositions[pindex]; - var w = lpos - ppos; - w = math.normalize(w); - - float3 n = math.cross(w, v); - n = math.cross(n, w); - - if (math.lengthsq(n) > Define.System.Epsilon) - { - n = math.normalize(n); - localNormals[vindex] = n; - localTangents[vindex] = w; - nrot = MathUtility.ToRotation(n, w); - } + // 元の接線と新しい法線が同じベクトルの場合は、従法線から新しい接線を算出する + var lbn = math.normalize(math.cross(ln, lt)); + lt = math.normalize(math.cross(lbn, n)); } + localNormals[vindex] = n; + localTangents[vindex] = lt; + var nrot = MathUtility.ToRotation(n, lt); + // 補正用回転を算出し格納する normalAdjustmentRotations[vindex] = math.mul(math.inverse(lrot), nrot); } @@ -837,11 +714,11 @@ namespace MagicaCloth2 var vset_z = (ptr + tri.z); if (vset_x->Length < 7) - vset_x->Set(tindex); + vset_x->MC2Set(tindex); if (vset_y->Length < 7) - vset_y->Set(tindex); + vset_y->MC2Set(tindex); if (vset_z->Length < 7) - vset_z->Set(tindex); + vset_z->MC2Set(tindex); } } } @@ -1103,7 +980,10 @@ namespace MagicaCloth2 // 頂点のローカル回転 var vrot = MathUtility.ToRotation(localNormals[vindex], localTangents[vindex]); - vertexToTransformRotations[vindex] = math.mul(math.inverse(vrot), trot); + // 頂点ローカル回転をトランスフォームローカル回転に復元する回転を求める + var toRot = math.mul(math.inverse(vrot), trot); + + vertexToTransformRotations[vindex] = toRot; } } @@ -1131,7 +1011,7 @@ namespace MagicaCloth2 for (int j = 0; j < 3; j++) { int2 edge = edges[j]; - edgeToTriangles.UniqueAdd(edge, (ushort)i); + edgeToTriangles.MC2UniqueAdd(edge, (ushort)i); } } } @@ -1157,13 +1037,13 @@ namespace MagicaCloth2 public void Execute(int vindex) { - float3 pos = localPositions[vindex]; - var nor = localNormals[vindex]; - var tan = localTangents[vindex]; + float3 lpos = localPositions[vindex]; + var lnor = localNormals[vindex]; + var ltan = localTangents[vindex]; // マッピング用の頂点バインドポーズを求める - quaternion rot = MathUtility.ToRotation(nor, tan); - vertexBindPosePositions[vindex] = -pos; + quaternion rot = MathUtility.ToRotation(lnor, ltan); + vertexBindPosePositions[vindex] = -lpos; vertexBindPoseRotations[vindex] = math.inverse(rot); } } @@ -1192,12 +1072,12 @@ namespace MagicaCloth2 ushort y = (ushort)tri.y; ushort z = (ushort)tri.z; - vertexToVertexMap.UniqueAdd(tri.x, y); - vertexToVertexMap.UniqueAdd(tri.x, z); - vertexToVertexMap.UniqueAdd(tri.y, x); - vertexToVertexMap.UniqueAdd(tri.y, z); - vertexToVertexMap.UniqueAdd(tri.z, x); - vertexToVertexMap.UniqueAdd(tri.z, y); + vertexToVertexMap.MC2UniqueAdd(tri.x, y); + vertexToVertexMap.MC2UniqueAdd(tri.x, z); + vertexToVertexMap.MC2UniqueAdd(tri.y, x); + vertexToVertexMap.MC2UniqueAdd(tri.y, z); + vertexToVertexMap.MC2UniqueAdd(tri.z, x); + vertexToVertexMap.MC2UniqueAdd(tri.z, y); edgeSet.Add(DataUtility.PackInt2(tri.xy)); edgeSet.Add(DataUtility.PackInt2(tri.yz)); @@ -1226,8 +1106,8 @@ namespace MagicaCloth2 { int2 line = lines[i]; - vertexToVertexMap.UniqueAdd(line.x, (ushort)line.y); - vertexToVertexMap.UniqueAdd(line.y, (ushort)line.x); + vertexToVertexMap.MC2UniqueAdd(line.x, (ushort)line.y); + vertexToVertexMap.MC2UniqueAdd(line.y, (ushort)line.x); edgeSet.Add(DataUtility.PackInt2(line)); } @@ -1268,10 +1148,10 @@ namespace MagicaCloth2 struct SkinningBoneInfo { //public int transformIndex; - public int startTransformIndex; - public float3 startPos; - public int endTransformIndex; - public float3 endPos; + public int parentTransformIndex; + public float3 parentPos; + public int childTransformIndex; + public float3 childPos; } /// @@ -1282,39 +1162,6 @@ namespace MagicaCloth2 if (CustomSkinningBoneCount == 0) return; -#if false - // ボーン情報の構築 - using var boneInfoList = new NativeList(CustomSkinningBoneCount, Allocator.Persistent); - for (int i = 0; i < CustomSkinningBoneCount; i++) - { - int tindex = customSkinningBoneIndices[i]; - if (tindex == -1) - continue; - - // 登録 - var info = new SkinningBoneInfo(); - info.transformIndex = tindex; - info.startPos = bones[i].localPosition; - boneInfoList.Add(info); - Debug.Log($"[{boneInfoList.Length - 1}] {i}, tindex:{tindex}"); - } - if (boneInfoList.Length == 0) - return; - - // 頂点ごとにカスタムスキニングウエイトを算出 - var job = new Proxy_CalcCustomSkinningWeightsJob2() - { - distanceReduction = setting.distanceReduction, - distancePow = setting.distancePow, - - //attributes = attributes.GetNativeArray(), - localPositions = localPositions.GetNativeArray(), - boneInfoList = boneInfoList, - boneWeights = boneWeights.GetNativeArray(), - }; - job.Run(VertexCount); -#endif -#if true // ボーン情報の構築 using var boneInfoList = new NativeList(CustomSkinningBoneCount * 2, Allocator.Persistent); for (int i = 0; i < CustomSkinningBoneCount; i++) @@ -1322,6 +1169,9 @@ namespace MagicaCloth2 int tindex = customSkinningBoneIndices[i]; if (tindex == -1) continue; + +#if MC2_CUSTOM_SKINNING_V1 + // 旧 int pid = bones[i].pid; if (pid == 0) continue; @@ -1330,16 +1180,22 @@ namespace MagicaCloth2 continue; // ボーンライン情報の作成 + // localPositonはクロス空間での座標に変換済み var info = new SkinningBoneInfo(); - //info.transformIndex = customSkinningBoneIndices[pindex]; - info.startTransformIndex = customSkinningBoneIndices[pindex]; - info.startPos = bones[pindex].localPosition; - info.endTransformIndex = tindex; - info.endPos = bones[i].localPosition; + info.parentTransformIndex = customSkinningBoneIndices[pindex]; + info.parentPos = bones[pindex].localPosition; + info.childTransformIndex = tindex; + info.childPos = bones[i].localPosition; // 距離がほぼ0なら無効 - if (math.distance(info.startPos, info.endPos) < Define.System.Epsilon) + if (math.distance(info.parentPos, info.childPos) < Define.System.Epsilon) continue; +#else + // V2 + var info = new SkinningBoneInfo(); + info.childTransformIndex = tindex; + info.childPos = bones[i].localPosition; +#endif // 登録 boneInfoList.Add(info); @@ -1349,12 +1205,11 @@ namespace MagicaCloth2 return; // 頂点ごとにカスタムスキニングウエイトを算出 +#if MC2_CUSTOM_SKINNING_V1 + // 旧 var job = new Proxy_CalcCustomSkinningWeightsJob() { isBoneCloth = isBoneCloth, - //angularAttenuation = setting.angularAttenuation, - //distanceReduction = setting.distanceReduction, - //distancePow = setting.distancePow, angularAttenuation = Define.System.CustomSkinningAngularAttenuation, distanceReduction = Define.System.CustomSkinningDistanceReduction, distancePow = Define.System.CustomSkinningDistancePow, @@ -1364,19 +1219,36 @@ namespace MagicaCloth2 boneInfoList = boneInfoList, boneWeights = boneWeights.GetNativeArray(), }; - job.Run(VertexCount); +#else + // V2 + var job = new Proxy_CalcCustomSkinningWeightsJobV2() + { + isBoneCloth = isBoneCloth, + angularAttenuation = Define.System.CustomSkinningAngularAttenuation, + distanceReduction = Define.System.CustomSkinningDistanceReduction, + distancePow = Define.System.CustomSkinningDistancePow, + + attributes = attributes.GetNativeArray(), + localPositions = localPositions.GetNativeArray(), + boneInfoList = boneInfoList, + boneWeights = boneWeights.GetNativeArray(), + }; #endif + job.Run(VertexCount); } -#if false +#if !MC2_CUSTOM_SKINNING_V1 + // V2 [BurstCompile] - struct Proxy_CalcCustomSkinningWeightsJob2 : IJobParallelFor + struct Proxy_CalcCustomSkinningWeightsJobV2 : IJobParallelFor { + public bool isBoneCloth; + public float angularAttenuation; public float distanceReduction; public float distancePow; - //[Unity.Collections.ReadOnly] - //public NativeArray attributes; + [Unity.Collections.ReadOnly] + public NativeArray attributes; [Unity.Collections.ReadOnly] public NativeArray localPositions; [Unity.Collections.ReadOnly] @@ -1384,12 +1256,12 @@ namespace MagicaCloth2 [Unity.Collections.WriteOnly] public NativeArray boneWeights; + // プロキシメッシュ頂点ごと public void Execute(int vindex) { - // 固定は無効(※この時点ではまだ属性がない!) - //var attr = attributes[vindex]; - //if (attr.IsMove() == false) - // return; + // 移動属性のみ + if (attributes[vindex].IsDontMove()) + return; var lpos = localPositions[vindex]; @@ -1398,12 +1270,14 @@ namespace MagicaCloth2 for (int i = 0; i < bcnt; i++) { var binfo = boneInfoList[i]; + var bpos = binfo.childPos; + int boneIndex = binfo.childTransformIndex; // 距離 - float dist = math.distance(lpos, binfo.startPos); + var v = lpos - bpos; + float dist = math.length(v); // 登録。すでに登録済みならばdistがより小さい場合のみ再登録 - int boneIndex = binfo.transformIndex; int nowIndex = costList.indexOf(boneIndex); if (nowIndex >= 0) { @@ -1417,59 +1291,67 @@ namespace MagicaCloth2 costList.Add(dist, boneIndex); } - // ウエイト算出 - // (0)最小距離のn%を減算する + // (1)最小距離のn%を減算する int cnt = costList.Count; - //const float lengthWeight = 0.8f; - float mindist = costList.MinCost * distanceReduction; - costList.costs -= mindist; - - // (1)distanceをn乗する - //const float pow = 2.0f; - costList.costs = math.pow(costList.costs, distancePow); - - // (2)最小値の逆数にする - float min = math.max(costList.MinCost, 1e-06f); - float sum = 0; + float mindist = costList.MinCost * distanceReduction; // 0.6 for (int i = 0; i < cnt; i++) + costList.costs[i] = costList.costs[i] - mindist; + + // (2)distanceをn乗する + for (int i = 0; i < cnt; i++) + costList.costs[i] = math.pow(costList.costs[i], distancePow); // 2.0 + + // ウエイト算出 + if (costList.MinCost < Define.System.Epsilon) { - costList.costs[i] = min / costList.costs[i]; - sum += costList.costs[i]; + costList.costs = new float4(1, 0, 0, 0); + costList.data = new int4(costList.data[0], 0, 0, 0); } - - // (3)割合を出す - costList.costs /= sum; - - // (4)極小のウエイトは削除する - sum = 0; - for (int i = 0; i < 4; i++) + else { - if (costList.costs[i] < 0.01f || i >= cnt) + // コストの逆数の合計 + cnt = costList.Count; + float sum = 0; + for (int i = 0; i < cnt; i++) { - // 打ち切り - costList.costs[i] = 0.0f; - costList.data[i] = 0; + sum += 1.0f / costList.costs[i]; } - else + + // 1.0fに正規化 + for (int i = 0; i < cnt; i++) { - sum += costList.costs[i]; + costList.costs[i] = (1.0f / costList.costs[i]) / sum; } + + // 極小のウエイトは削除する + const float InvalidWeight = 0.001f; // 0.1% + sum = 0; + for (int i = 0; i < 4; i++) + { + if (costList.costs[i] < InvalidWeight || i >= cnt) + { + // 打ち切り + costList.costs[i] = 0.0f; + costList.data[i] = 0; + } + else + { + sum += costList.costs[i]; + } + } + Debug.Assert(sum > 0); + costList.costs /= sum; // 再度1.0正規化 } - Debug.Assert(sum > 0); - - // (5)再度1.0に平均化 - costList.costs /= sum; - //Debug.Log($"[{vindex}] :{costList}"); - // ウエイト作成 + // ウエイト構造体に変換して格納 var bw = new VirtualMeshBoneWeight(costList.data, costList.costs); boneWeights[vindex] = bw; } } #endif -#if true +#if MC2_CUSTOM_SKINNING_V1 [BurstCompile] struct Proxy_CalcCustomSkinningWeightsJob : IJobParallelFor { @@ -1487,7 +1369,7 @@ namespace MagicaCloth2 [Unity.Collections.WriteOnly] public NativeArray boneWeights; - + // プロキシメッシュ頂点ごと public void Execute(int vindex) { // BoneClothカスタムスキニングでは固定は動かさない @@ -1501,21 +1383,21 @@ namespace MagicaCloth2 for (int i = 0; i < bcnt; i++) { var binfo = boneInfoList[i]; - float3 d = MathUtility.ClosestPtPointSegment(lpos, binfo.startPos, binfo.endPos); + float3 d = MathUtility.ClosestPtPointSegment(lpos, binfo.parentPos, binfo.childPos); //float dist = math.distance(lpos, d); // ボーンラインとの角度により判定距離を調整する // ラインと水平になるほど影響がよわくなる var v = lpos - d; - var bv = binfo.endPos - binfo.startPos; + var bv = binfo.childPos - binfo.parentPos; float dot = math.dot(math.normalize(v), math.normalize(bv)); - float ratio = 1.0f + math.abs(dot) * angularAttenuation; + float ratio = 1.0f + math.abs(dot) * angularAttenuation; // 1.0 // 登録。すでに登録済みならばdistがより小さい場合のみ再登録 for (int j = 0; j < 2; j++) { - int boneIndex = j == 0 ? binfo.startTransformIndex : binfo.endTransformIndex; - float dist = j == 0 ? math.distance(lpos, binfo.startPos) : math.distance(lpos, binfo.endPos); + int boneIndex = j == 0 ? binfo.parentTransformIndex : binfo.childTransformIndex; + float dist = j == 0 ? math.distance(lpos, binfo.parentPos) : math.distance(lpos, binfo.childPos); dist *= ratio; int nowIndex = costList.indexOf(boneIndex); @@ -1535,11 +1417,11 @@ namespace MagicaCloth2 // ウエイト算出 // (0)最小距離のn%を減算する int cnt = costList.Count; - float mindist = costList.MinCost * distanceReduction; + float mindist = costList.MinCost * distanceReduction; // 0.6 costList.costs -= mindist; // (1)distanceをn乗する - costList.costs = math.pow(costList.costs, distancePow); + costList.costs = math.pow(costList.costs, distancePow); // 2.0 // (2)最小値の逆数にする float min = math.max(costList.MinCost, 1e-06f); @@ -1950,7 +1832,7 @@ namespace MagicaCloth2 int pindex = vertexParentIndices[vindex]; if (pindex >= 0) { - vertexChildMap.UniqueAdd(pindex, (ushort)vindex); + vertexChildMap.MC2UniqueAdd(pindex, (ushort)vindex); } } @@ -2261,16 +2143,21 @@ namespace MagicaCloth2 float3 tan = localTangents[vindex]; quaternion rot = MathUtility.ToRotation(nor, tan); - float3 lpos = math.mul(iprot, pos - ppos); quaternion lrot = math.mul(iprot, rot); vertexLocalPositions[vindex] = lpos; vertexLocalRotations[vindex] = lrot; + + //Debug.Log($"vertexLocalPositions [{vindex}] : {lpos}"); + //Debug.Log($"vertexLocalRotations [{vindex}] : {lrot}"); } else { vertexLocalPositions[vindex] = 0; vertexLocalRotations[vindex] = quaternion.identity; + + //Debug.Log($"vertexLocalPositions [{vindex}] : 0"); + //Debug.Log($"vertexLocalRotations [{vindex}] : (0, 0, 0, 1)"); } } } @@ -2379,7 +2266,7 @@ namespace MagicaCloth2 } //========================================================================================= -#if false // pitch/yaw個別制限はv1.0では実装しないので一旦ん停止 +#if false // pitch/yaw個別制限はv1.0では実装しないので一旦停止 /// /// 角度制限計算用ローカル回転の算出 /// diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshProxy.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshProxy.cs.meta index 6a8e2999..03992f3b 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshProxy.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshProxy.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshProxy.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshReduction.cs b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshReduction.cs index 8df45a3d..141e70d5 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshReduction.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshReduction.cs @@ -48,7 +48,7 @@ namespace MagicaCloth2 float sameDistance = maxSideLength * math.saturate(Define.System.ReductionSameDistance); float simpleDistance = maxSideLength * math.saturate(settings.simpleDistance); float shapeDistance = maxSideLength * math.saturate(settings.shapeDistance); - //Develop.DebugLog($"ReductionDista. maxSideLength:{maxSideLength}, same:{sameDistance}, simple:{simpleDistance}, shape:{shapeDistance}"); + Develop.DebugLog($"ReductionDista. maxSideLength:{maxSideLength}, same:{sameDistance}, simple:{simpleDistance}, shape:{shapeDistance}"); // 同一距離リダクション ct.ThrowIfCancellationRequested(); @@ -659,7 +659,7 @@ namespace MagicaCloth2 { int newIndex2 = vertexRemapIndices[oldVertexIndex]; //Debug.Assert(newIndex != newIndex2); - newVertexToVertexMap.UniqueAdd((ushort)newIndex, (ushort)newIndex2); + newVertexToVertexMap.MC2UniqueAdd((ushort)newIndex, (ushort)newIndex2); } //Debug.Log($"[{newIndex}] cnt:{newVertexToVertexMap.CountValuesForKey((ushort)newIndex)}"); @@ -764,7 +764,7 @@ namespace MagicaCloth2 if (vindex == edge.x || vindex == edge.y) continue; - if (newVertexToVertexMap.Contains((ushort)edge.y, vindex)) + if (newVertexToVertexMap.MC2Contains((ushort)edge.y, vindex)) { // トライアングル生成 int3 tri = DataUtility.PackInt3(edge.x, edge.y, vindex); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshReduction.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshReduction.cs.meta index 14d8ec1b..25978a25 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshReduction.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshReduction.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshReduction.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs new file mode 100644 index 00000000..5d775927 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs @@ -0,0 +1,291 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using System.Collections.Generic; +using System.Text; +using Unity.Collections; +using Unity.Mathematics; +using UnityEngine; + +namespace MagicaCloth2 +{ + public partial class VirtualMesh + { + /// + /// PreBuildの共有部分データ + /// + [System.Serializable] + public class ShareSerializationData + { + public string name; + public MeshType meshType; + public bool isBoneCloth; + + // 基本 + public ExSimpleNativeArray.SerializationData referenceIndices; + public ExSimpleNativeArray.SerializationData attributes; + public ExSimpleNativeArray.SerializationData localPositions; + public ExSimpleNativeArray.SerializationData localNormals; + public ExSimpleNativeArray.SerializationData localTangents; + public ExSimpleNativeArray.SerializationData uv; + public ExSimpleNativeArray.SerializationData boneWeights; + public ExSimpleNativeArray.SerializationData triangles; + public ExSimpleNativeArray.SerializationData lines; + public int centerTransformIndex; + public float4x4 initLocalToWorld; + public float4x4 initWorldToLocal; + public quaternion initRotation; + public quaternion initInverseRotation; + public float3 initScale; + public int skinRootIndex; + public ExSimpleNativeArray.SerializationData skinBoneTransformIndices; + public ExSimpleNativeArray.SerializationData skinBoneBindPoses; + public TransformData.ShareSerializationData transformData; + public AABB boundingBox; + public float averageVertexDistance; + public float maxVertexDistance; + + // プロキシメッシュ + public byte[] vertexToTriangles; + public byte[] vertexToVertexIndexArray; + public byte[] vertexToVertexDataArray; + public byte[] edges; + public byte[] edgeFlags; + public int2[] edgeToTrianglesKeys; + public ushort[] edgeToTrianglesValues; + public byte[] vertexBindPosePositions; + public byte[] vertexBindPoseRotations; + public byte[] vertexToTransformRotations; + public byte[] vertexDepths; + public byte[] vertexRootIndices; + public byte[] vertexParentIndices; + public byte[] vertexChildIndexArray; + public byte[] vertexChildDataArray; + public byte[] vertexLocalPositions; + public byte[] vertexLocalRotations; + public byte[] normalAdjustmentRotations; + public byte[] baseLineFlags; + public byte[] baseLineStartDataIndices; + public byte[] baseLineDataCounts; + public byte[] baseLineData; + public int[] customSkinningBoneIndices; + public ushort[] centerFixedList; + public float3 localCenterPosition; + + // マッピングメッシュ + public float3 centerWorldPosition; + public quaternion centerWorldRotation; + public float3 centerWorldScale; + public float4x4 toProxyMatrix; + public quaternion toProxyRotation; + + public override string ToString() + { + StringBuilder sb = new StringBuilder(1024); + + sb.AppendLine("===== VirtualMesh.SerializeData ====="); + sb.AppendLine($"name:{name}"); + sb.AppendLine($"meshType:{meshType}"); + sb.AppendLine($"isBoneCloth:{isBoneCloth}"); + sb.AppendLine($"VertexCount:{attributes.count}"); + sb.AppendLine($"TriangleCount:{triangles.count}"); + sb.AppendLine($"LineCount:{lines.count}"); + + return sb.ToString(); + } + } + + public ShareSerializationData ShareSerialize() + { + var sdata = new ShareSerializationData(); + try + { + sdata.name = name; + sdata.meshType = meshType; + sdata.isBoneCloth = isBoneCloth; + + // 基本 + sdata.referenceIndices = referenceIndices.Serialize(); + sdata.attributes = attributes.Serialize(); + sdata.localPositions = localPositions.Serialize(); + sdata.localNormals = localNormals.Serialize(); + sdata.localTangents = localTangents.Serialize(); + sdata.uv = uv.Serialize(); + sdata.boneWeights = boneWeights.Serialize(); + sdata.triangles = triangles.Serialize(); + sdata.lines = lines.Serialize(); + sdata.centerTransformIndex = centerTransformIndex; + sdata.initLocalToWorld = initLocalToWorld; + sdata.initWorldToLocal = initWorldToLocal; + sdata.initRotation = initRotation; + sdata.initInverseRotation = initInverseRotation; + sdata.initScale = initScale; + sdata.skinRootIndex = skinRootIndex; + sdata.skinBoneTransformIndices = skinBoneTransformIndices.Serialize(); + sdata.skinBoneBindPoses = skinBoneBindPoses.Serialize(); + sdata.transformData = transformData?.ShareSerialize(); + if (boundingBox.IsCreated) + sdata.boundingBox = boundingBox.Value; + if (averageVertexDistance.IsCreated) + sdata.averageVertexDistance = averageVertexDistance.Value; + if (maxVertexDistance.IsCreated) + sdata.maxVertexDistance = maxVertexDistance.Value; + + // プロキシメッシュ + sdata.vertexToTriangles = vertexToTriangles.MC2ToRawBytes(); + sdata.vertexToVertexIndexArray = vertexToVertexIndexArray.MC2ToRawBytes(); + sdata.vertexToVertexDataArray = vertexToVertexDataArray.MC2ToRawBytes(); + sdata.edges = edges.MC2ToRawBytes(); + sdata.edgeFlags = edgeFlags.MC2ToRawBytes(); + (sdata.edgeToTrianglesKeys, sdata.edgeToTrianglesValues) = edgeToTriangles.MC2Serialize(); + sdata.vertexBindPosePositions = vertexBindPosePositions.MC2ToRawBytes(); + sdata.vertexBindPoseRotations = vertexBindPoseRotations.MC2ToRawBytes(); + sdata.vertexToTransformRotations = vertexToTransformRotations.MC2ToRawBytes(); + sdata.vertexDepths = vertexDepths.MC2ToRawBytes(); + sdata.vertexRootIndices = vertexRootIndices.MC2ToRawBytes(); + sdata.vertexParentIndices = vertexParentIndices.MC2ToRawBytes(); + sdata.vertexChildIndexArray = vertexChildIndexArray.MC2ToRawBytes(); + sdata.vertexChildDataArray = vertexChildDataArray.MC2ToRawBytes(); + sdata.vertexLocalPositions = vertexLocalPositions.MC2ToRawBytes(); + sdata.vertexLocalRotations = vertexLocalRotations.MC2ToRawBytes(); + sdata.normalAdjustmentRotations = normalAdjustmentRotations.MC2ToRawBytes(); + sdata.baseLineFlags = baseLineFlags.MC2ToRawBytes(); + sdata.baseLineStartDataIndices = baseLineStartDataIndices.MC2ToRawBytes(); + sdata.baseLineDataCounts = baseLineDataCounts.MC2ToRawBytes(); + sdata.baseLineData = baseLineData.MC2ToRawBytes(); + DataUtility.ArrayCopy(customSkinningBoneIndices, ref sdata.customSkinningBoneIndices); + DataUtility.ArrayCopy(centerFixedList, ref sdata.centerFixedList); + if (localCenterPosition.IsCreated) + sdata.localCenterPosition = localCenterPosition.Value; + + // マッピングメッシュ + sdata.centerWorldPosition = centerWorldPosition; + sdata.centerWorldRotation = centerWorldRotation; + sdata.centerWorldScale = centerWorldScale; + sdata.toProxyMatrix = toProxyMatrix; + sdata.toProxyRotation = toProxyRotation; + } + catch (Exception exception) + { + Debug.LogException(exception); + } + + return sdata; + } + + public static VirtualMesh ShareDeserialize(ShareSerializationData sdata) + { + var vmesh = new VirtualMesh(); + vmesh.isManaged = true; + + try + { + vmesh.name = sdata.name; + vmesh.meshType = sdata.meshType; + vmesh.isBoneCloth = sdata.isBoneCloth; + + // 基本 + vmesh.referenceIndices.Deserialize(sdata.referenceIndices); + vmesh.attributes.Deserialize(sdata.attributes); + vmesh.localPositions.Deserialize(sdata.localPositions); + vmesh.localNormals.Deserialize(sdata.localNormals); + vmesh.localTangents.Deserialize(sdata.localTangents); + vmesh.uv.Deserialize(sdata.uv); + vmesh.boneWeights.Deserialize(sdata.boneWeights); + vmesh.triangles.Deserialize(sdata.triangles); + vmesh.lines.Deserialize(sdata.lines); + vmesh.centerTransformIndex = sdata.centerTransformIndex; + vmesh.initLocalToWorld = sdata.initLocalToWorld; + vmesh.initWorldToLocal = sdata.initWorldToLocal; + vmesh.initRotation = sdata.initRotation; + vmesh.initInverseRotation = sdata.initInverseRotation; + vmesh.initScale = sdata.initScale; + vmesh.skinRootIndex = sdata.skinRootIndex; + vmesh.skinBoneTransformIndices.Deserialize(sdata.skinBoneTransformIndices); + vmesh.skinBoneBindPoses.Deserialize(sdata.skinBoneBindPoses); + vmesh.transformData = TransformData.ShareDeserialize(sdata.transformData); + vmesh.boundingBox = new NativeReference(sdata.boundingBox, Allocator.Persistent); + vmesh.averageVertexDistance = new NativeReference(sdata.averageVertexDistance, Allocator.Persistent); + vmesh.maxVertexDistance = new NativeReference(sdata.maxVertexDistance, Allocator.Persistent); + + // プロキシメッシュ + vmesh.vertexToTriangles = NativeArrayExtensions.MC2FromRawBytes>(sdata.vertexToTriangles); + vmesh.vertexToVertexIndexArray = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexToVertexIndexArray); + vmesh.vertexToVertexDataArray = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexToVertexDataArray); + vmesh.edges = NativeArrayExtensions.MC2FromRawBytes(sdata.edges); + vmesh.edgeFlags = NativeArrayExtensions.MC2FromRawBytes(sdata.edgeFlags); + vmesh.edgeToTriangles = NativeMultiHashMapExtensions.MC2Deserialize(sdata.edgeToTrianglesKeys, sdata.edgeToTrianglesValues); + vmesh.vertexBindPosePositions = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexBindPosePositions); + vmesh.vertexBindPoseRotations = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexBindPoseRotations); + vmesh.vertexToTransformRotations = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexToTransformRotations); + vmesh.vertexDepths = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexDepths); + vmesh.vertexRootIndices = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexRootIndices); + vmesh.vertexParentIndices = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexParentIndices); + vmesh.vertexChildIndexArray = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexChildIndexArray); + vmesh.vertexChildDataArray = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexChildDataArray); + vmesh.vertexLocalPositions = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexLocalPositions); + vmesh.vertexLocalRotations = NativeArrayExtensions.MC2FromRawBytes(sdata.vertexLocalRotations); + vmesh.normalAdjustmentRotations = NativeArrayExtensions.MC2FromRawBytes(sdata.normalAdjustmentRotations); + vmesh.baseLineFlags = NativeArrayExtensions.MC2FromRawBytes(sdata.baseLineFlags); + vmesh.baseLineStartDataIndices = NativeArrayExtensions.MC2FromRawBytes(sdata.baseLineStartDataIndices); + vmesh.baseLineDataCounts = NativeArrayExtensions.MC2FromRawBytes(sdata.baseLineDataCounts); + vmesh.baseLineData = NativeArrayExtensions.MC2FromRawBytes(sdata.baseLineData); + DataUtility.ArrayCopy(sdata.customSkinningBoneIndices, ref vmesh.customSkinningBoneIndices); + DataUtility.ArrayCopy(sdata.centerFixedList, ref vmesh.centerFixedList); + vmesh.localCenterPosition = new NativeReference(sdata.localCenterPosition, Allocator.Persistent); + + // マッピングメッシュ + vmesh.centerWorldPosition = sdata.centerWorldPosition; + vmesh.centerWorldRotation = sdata.centerWorldRotation; + vmesh.centerWorldScale = sdata.centerWorldScale; + vmesh.toProxyMatrix = sdata.toProxyMatrix; + vmesh.toProxyRotation = sdata.toProxyRotation; + + vmesh.result.SetSuccess(); + } + catch (Exception exception) + { + Debug.LogException(exception); + vmesh.result.SetError(Define.Result.PreBuildData_VirtualMeshDeserializationException); + } + + return vmesh; + } + + //========================================================================================= + /// + /// PreBuildの固有部分データ + /// + [System.Serializable] + public class UniqueSerializationData : ITransform + { + public TransformData.UniqueSerializationData transformData; + + public void GetUsedTransform(HashSet transformSet) + { + transformData?.GetUsedTransform(transformSet); + } + + public void ReplaceTransform(Dictionary replaceDict) + { + transformData?.ReplaceTransform(replaceDict); + } + } + + public UniqueSerializationData UniqueSerialize() + { + var sdata = new UniqueSerializationData(); + try + { + sdata.transformData = transformData?.UniqueSerialize(); + } + catch (Exception exception) + { + Debug.LogException(exception); + } + + return sdata; + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs.meta new file mode 100644 index 00000000..4825f2ed --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 0d0b2768c9c7600468b9f1a7b39dd80d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshSerialization.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshWork.cs b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshWork.cs index c5757287..0c0eecb4 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshWork.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshWork.cs @@ -14,7 +14,7 @@ namespace MagicaCloth2 { //========================================================================================= /// - /// 頂点間の平均/最大距離を調べてる(スレッド可) + /// 頂点間の平均/最大距離を調べる(スレッド可) /// 結果はaverageVertexDistance/maxVertexDistanceに格納される /// internal void CalcAverageAndMaxVertexDistanceRun() diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshWork.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshWork.cs.meta index 0473196e..8d64535d 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshWork.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshWork.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/Function/VirtualMeshWork.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VertexAttribute.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VertexAttribute.cs.meta index 3ba5bdac..07024315 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VertexAttribute.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VertexAttribute.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VertexAttribute.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMesh.cs b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMesh.cs index ff0dcf76..bc028ac7 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMesh.cs +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMesh.cs @@ -22,6 +22,8 @@ namespace MagicaCloth2 public ResultCode result = new ResultCode(); + public bool isManaged; // PreBuild DeserializeManager管理 + /// /// メッシュタイプ /// @@ -360,26 +362,34 @@ namespace MagicaCloth2 public int mappingId; //========================================================================================= - public VirtualMesh() + public VirtualMesh() { } + + public VirtualMesh(bool initialize) { - transformData = new TransformData(); + if (initialize) + { + transformData = new TransformData(100); - // 最小限のデータ - averageVertexDistance = new NativeReference(0.0f, Allocator.Persistent); - maxVertexDistance = new NativeReference(0.0f, Allocator.Persistent); + // 最小限のデータ + averageVertexDistance = new NativeReference(0.0f, Allocator.Persistent); + maxVertexDistance = new NativeReference(0.0f, Allocator.Persistent); - - // 作業中にしておく - result.SetProcess(); + // 作業中にしておく + result.SetProcess(); + } } - public VirtualMesh(string name) : this() + public VirtualMesh(string name) : this(true) { this.name = name; } public void Dispose() { + // PreBuild DeserializeManager管理中は破棄させない + if (isManaged) + return; + result.Clear(); referenceIndices.Dispose(); attributes.Dispose(); @@ -471,7 +481,8 @@ namespace MagicaCloth2 return false; // レンダラーが存在する場合はその存在を確認する - if (centerTransformIndex >= 0 && transformData.GetTransformFromIndex(centerTransformIndex) == null) + // ただしPreBuildではtransformListは空なのでスキップする + if (centerTransformIndex >= 0 && transformData.IsEmpty == false && transformData.GetTransformFromIndex(centerTransformIndex) == null) return false; return true; @@ -483,23 +494,38 @@ namespace MagicaCloth2 StringBuilder sb = new StringBuilder(); sb.AppendLine($"===== {name} ====="); - sb.Append($"Result:{result}"); - sb.Append($", Type:{meshType}"); - sb.Append($", Vertex:{VertexCount}"); - sb.Append($", Line:{LineCount}"); - sb.Append($", Triangle:{TriangleCount}"); - sb.Append($", Edge:{EdgeCount}"); - sb.Append($", SkinBone:{SkinBoneCount}"); - sb.Append($", Transform:{transformData?.Count}"); - sb.Append($", BaseLine:{BaseLineCount}"); + sb.AppendLine($"Result:{result.GetResultString()}"); + sb.AppendLine($"Type:{meshType}"); + sb.AppendLine($"Vertex:{VertexCount}"); + sb.AppendLine($"Line:{LineCount}"); + sb.AppendLine($"Triangle:{TriangleCount}"); + sb.AppendLine($"Edge:{EdgeCount}"); + sb.AppendLine($"SkinBone:{SkinBoneCount}"); + sb.AppendLine($"Transform:{TransformCount}"); + if (averageVertexDistance.IsCreated) + sb.AppendLine($"avgDist:{averageVertexDistance.Value}"); + if (maxVertexDistance.IsCreated) + sb.AppendLine($"maxDist:{maxVertexDistance.Value}"); + if (boundingBox.IsCreated) + sb.AppendLine($"AABB:{boundingBox.Value}"); sb.AppendLine(); - if (averageVertexDistance.IsCreated) - sb.Append($"avgDist:{averageVertexDistance.Value}"); - if (maxVertexDistance.IsCreated) - sb.Append($", maxDist:{maxVertexDistance.Value}"); - if (boundingBox.IsCreated) - sb.Append($", AABB:{boundingBox.Value}"); + sb.AppendLine($"<<< Proxy >>>"); + sb.AppendLine($"BaseLine:{BaseLineCount}"); + sb.AppendLine($"EdgeCount:{EdgeCount}"); + int edgeToTrianglesCnt = edgeToTriangles.IsCreated ? edgeToTriangles.Count() : 0; + sb.AppendLine($"edgeToTriangles:{edgeToTrianglesCnt}"); + sb.AppendLine($"CustomSkinningBoneCount:{CustomSkinningBoneCount}"); + sb.AppendLine($"CenterFixedPointCount:{CenterFixedPointCount}"); + sb.AppendLine($"NormalAdjustmentRotationCount:{NormalAdjustmentRotationCount}"); + sb.AppendLine(); + + sb.AppendLine($"<<< Mapping >>>"); + sb.AppendLine($"centerWorldPosition:{centerWorldPosition}"); + sb.AppendLine(); + + //sb.AppendLine($"<<< TransformData >>>"); + sb.AppendLine(transformData?.ToString() ?? "(none)"); sb.AppendLine(); return sb.ToString(); diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMesh.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMesh.cs.meta index 0d376d5a..97d7b527 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMesh.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMesh.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMesh.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshBoneWeight.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshBoneWeight.cs.meta index 30c20947..9615cd5e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshBoneWeight.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshBoneWeight.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshBoneWeight.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs new file mode 100644 index 00000000..2a68af9d --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs @@ -0,0 +1,60 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// VirtualMeshの共有部分と固有部分を1つにまとめた情報 + /// + public class VirtualMeshContainer : IDisposable + { + public VirtualMesh shareVirtualMesh; + public VirtualMesh.UniqueSerializationData uniqueData; + + public VirtualMeshContainer() + { + } + + public VirtualMeshContainer(VirtualMesh vmesh) + { + shareVirtualMesh = vmesh; + uniqueData = null; + } + + public void Dispose() + { + shareVirtualMesh?.Dispose(); + } + + //========================================================================================= + public bool hasUniqueData => uniqueData != null; + + //========================================================================================= + public int GetTransformCount() + { + if (hasUniqueData) + return uniqueData.transformData.transformArray.Length; + else + return shareVirtualMesh.TransformCount; + } + + public Transform GetTransformFromIndex(int index) + { + if (hasUniqueData) + return uniqueData.transformData.transformArray[index]; + else + return shareVirtualMesh.transformData.GetTransformFromIndex(index); + } + + public Transform GetCenterTransform() + { + if (hasUniqueData) + return uniqueData.transformData.transformArray[shareVirtualMesh.centerTransformIndex]; + else + return shareVirtualMesh.GetCenterTransform(); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs.meta new file mode 100644 index 00000000..141956b1 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: bac7915dc7b0bda49baed15536766603 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshContainer.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshPrimitive.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshPrimitive.cs.meta index b68bb27d..d4b3ec29 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshPrimitive.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshPrimitive.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshPrimitive.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshRaycastHit.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshRaycastHit.cs.meta index 1cac8dd4..6fe81373 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshRaycastHit.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshRaycastHit.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshRaycastHit.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshTransform.cs.meta b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshTransform.cs.meta index 51029574..87faff53 100644 --- a/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshTransform.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshTransform.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Core/VirtualMesh/VirtualMeshTransform.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothAssetPostprocessor.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothAssetPostprocessor.cs.meta index bbbf3e6f..58dff95f 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothAssetPostprocessor.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothAssetPostprocessor.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothAssetPostprocessor.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorManager.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorManager.cs index 8b5c3671..b3d24d13 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorManager.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorManager.cs @@ -3,17 +3,15 @@ // https://magicasoft.jp using System; using System.Collections.Generic; +using System.Text; using System.Threading; using System.Threading.Tasks; using Unity.Mathematics; using UnityEditor; using UnityEditor.Callbacks; using UnityEditor.Compilation; -#if UNITY_2020 -using UnityEditor.Experimental.SceneManagement; -#else +using UnityEditor.PackageManager; using UnityEditor.SceneManagement; -#endif using UnityEngine; namespace MagicaCloth2 @@ -34,9 +32,10 @@ namespace MagicaCloth2 public GizmoType gizmoType; public ClothBehaviour component; public int componentHash; - public VirtualMesh editMesh; + public VirtualMeshContainer editMeshContainer; public int nextBuildHash; public int importCount; + public ClothInitSerializeData editInitSerializeData; } static Dictionary editClothDict = new Dictionary(); @@ -139,6 +138,22 @@ namespace MagicaCloth2 ForceUpdateAllComponents(); } + //========================================================================================= + static bool IsActive(GizmoType gizmoType) + { + return gizmoType.HasFlag(GizmoType.Active); + } + + static bool IsActiveOrSelected(GizmoType gizmoType) + { + return IsActive(gizmoType) || gizmoType.HasFlag(GizmoType.Selected); + } + + static bool IsSelectionHierarchy(GizmoType gizmoType) + { + return IsActiveOrSelected(gizmoType) || gizmoType.HasFlag(GizmoType.InSelectionHierarchy); + } + /// /// MagidaClothコンポーネントの登録および編集メッシュの作成/更新 /// @@ -161,39 +176,22 @@ namespace MagicaCloth2 //if (cloth) // Develop.DebugLog($"Register Cloth:{component.name}, gizmoType:{gizmoType}"); - // ギズモ表示判定 - if (gizmoType.HasFlag(GizmoType.Active)) - { - gizmoType = GizmoType.Active; - } +#if true + // Unity2023のみ何故かGizmoTypeの挙動が異なり、実際には選択されてなくても親が選択中だとSelectedフラグが立ってしまう。 + // そのため、Selectedフラグに関してはここで手動で判定することにする。 + if (Selection.Contains(component.gameObject.GetInstanceID())) + gizmoType |= GizmoType.Selected; else - { - // ★何故かGizmoType.InSelectionHierarchyが正常に判定できないので手動で解決する!(2022/10/14) - // ★GizmoType.InSelectionHierarchyがバグっている? - gizmoType = 0; - var t = component.transform.parent; - var activeT = Selection.activeTransform; - if (activeT) - { - while (t) - { - if (t == activeT) - { - gizmoType = GizmoType.Selected; - break; - } - else - t = t.parent; - } - } + gizmoType &= ~GizmoType.Selected; +#endif - // 常に表示 - if (cloth && cloth.GizmoSerializeData.IsAlways()) - gizmoType = GizmoType.Active; - } + // ギズモ表示判定 + // 常に表示 + if (cloth && cloth.GizmoSerializeData.IsAlways()) + gizmoType = GizmoType.Active; // クロス指定のコライダー表示 - if (cloth && cloth.GizmoSerializeData.clothDebugSettings.collider && gizmoType != 0) + if (cloth && cloth.GizmoSerializeData.clothDebugSettings.enable && cloth.GizmoSerializeData.clothDebugSettings.collider && IsSelectionHierarchy(gizmoType)) { foreach (var col in cloth.SerializeData.colliderCollisionConstraint.colliderList) { @@ -210,7 +208,7 @@ namespace MagicaCloth2 info.building = false; info.result = ResultCode.Empty; info.component = component; - info.editMesh = null; + info.editMeshContainer = null; info.gizmoType = gizmoType; info.componentHash = 0; info.nextBuildHash = 0; @@ -219,8 +217,7 @@ namespace MagicaCloth2 } else { - if (gizmoType > editClothDict[id].gizmoType) - editClothDict[id].gizmoType = gizmoType; + editClothDict[id].gizmoType |= gizmoType; } } @@ -228,6 +225,7 @@ namespace MagicaCloth2 if (cloth && EditorApplication.isPlaying == false) { int hash = component.GetMagicaHashCode(); + //Debug.Log($"Hash:{hash}"); lock (editClothDict) { @@ -252,7 +250,7 @@ namespace MagicaCloth2 info.componentHash = hash; info.nextBuildHash = 0; - if (cloth.isActiveAndEnabled) + if (cloth.isActiveAndEnabled || forceUpdate) { // スレッドで作成 info.building = true; @@ -265,19 +263,19 @@ namespace MagicaCloth2 } } - public static VirtualMesh GetEditMesh(ClothBehaviour comp) + public static VirtualMeshContainer GetEditMeshContainer(ClothBehaviour comp) { if (isValid == false) return null; if (comp == null) return null; int id = comp.GetInstanceID(); - VirtualMesh vmesh = null; + VirtualMeshContainer cmesh = null; lock (editClothDict) { - vmesh = editClothDict.ContainsKey(id) ? editClothDict[id].editMesh : null; + cmesh = editClothDict.ContainsKey(id) ? editClothDict[id].editMeshContainer : null; } - return vmesh; + return cmesh; } /// @@ -311,7 +309,7 @@ namespace MagicaCloth2 { foreach (var info in editClothDict.Values) { - info?.editMesh?.Dispose(); + info?.editMeshContainer?.Dispose(); } editClothDict.Clear(); } @@ -335,7 +333,7 @@ namespace MagicaCloth2 foreach (var id in destroyList) { //Debug.Log($"削除"); - editClothDict[id].editMesh?.Dispose(); + editClothDict[id].editMeshContainer?.Dispose(); editClothDict.Remove(id); } destroyList.Clear(); @@ -440,7 +438,8 @@ namespace MagicaCloth2 var sdata = cloth.SerializeData; var sdata2 = cloth.GetSerializeData2(); var setupList = new List(); - VirtualMesh editMesh = null; + VirtualMeshContainer editMeshContainer = null; + ClothInitSerializeData editInitSerializeData = new ClothInitSerializeData(); ResultCode result = new ResultCode(); try @@ -451,11 +450,16 @@ namespace MagicaCloth2 result.SetError(Define.Result.CreateCloth_InvalidCloth); throw new MagicaClothProcessingException(); } + var statusResult = cloth.Process.GenerateStatusCheck(); + result.Merge(statusResult); + if (statusResult.IsError()) + { + throw new MagicaClothProcessingException(); + } // メッシュを構築するための最低限のデータが揃っているか確認 if (sdata.IsValid() == false) { - //result.SetResult(Define.Result.Empty); result.SetResult(sdata.VerificationResult); throw new MagicaClothProcessingException(); } @@ -467,7 +471,7 @@ namespace MagicaCloth2 { if (ren) { - var setup = new RenderSetupData(ren); + var setup = new RenderSetupData(null, ren); result.Merge(setup.result); if (setup.IsFaild()) { @@ -485,13 +489,13 @@ namespace MagicaCloth2 } else if (sdata.clothType == ClothProcess.ClothType.BoneCloth) { - var setup = new RenderSetupData(RenderSetupData.SetupType.BoneCloth, cloth.ClothTransform, sdata.rootBones, null, sdata.connectionMode, cloth.name); + var setup = new RenderSetupData(null, RenderSetupData.SetupType.BoneCloth, cloth.ClothTransform, sdata.rootBones, null, sdata.connectionMode, cloth.name); setupList.Add(setup); } else if (sdata.clothType == ClothProcess.ClothType.BoneSpring) { // BoneSpringではLine接続のみ - var setup = new RenderSetupData(RenderSetupData.SetupType.BoneSpring, cloth.ClothTransform, sdata.rootBones, sdata.colliderCollisionConstraint.collisionBones, RenderSetupData.BoneConnectionMode.Line, cloth.name); + var setup = new RenderSetupData(null, RenderSetupData.SetupType.BoneSpring, cloth.ClothTransform, sdata.rootBones, sdata.colliderCollisionConstraint.collisionBones, RenderSetupData.BoneConnectionMode.Line, cloth.name); setupList.Add(setup); } @@ -502,13 +506,21 @@ namespace MagicaCloth2 } // クロスコンポーネントトランスフォーム情報 - var clothTransformRecord = new TransformRecord(cloth.ClothTransform); + var clothTransformRecord = new TransformRecord(cloth.ClothTransform, read: true); // 法線調整用トランスフォーム var normalAdjustmentTransformRecored = new TransformRecord( sdata.normalAlignmentSetting.adjustmentTransform ? sdata.normalAlignmentSetting.adjustmentTransform : - cloth.ClothTransform + cloth.ClothTransform, read: true + ); + + // 初期化情報収集 + editInitSerializeData.Serialize( + sdata, + clothTransformRecord, + normalAdjustmentTransformRecored, + setupList ); // ペイントマップデータの作成(これはメインスレッドでのみ作成可能) @@ -533,7 +545,8 @@ namespace MagicaCloth2 // エディットメッシュ作成 // メッシュはセンター空間で作成される ct.ThrowIfCancellationRequested(); - editMesh = new VirtualMesh("EditMesh"); + var editMesh = new VirtualMesh("EditMesh"); + editMeshContainer = new VirtualMeshContainer(editMesh); if (sdata.clothType == ClothProcess.ClothType.MeshCloth) { // MeshClothではクロストランスフォームを追加しておく @@ -543,7 +556,6 @@ namespace MagicaCloth2 // セレクションデータ // ペイントマップ指定の場合は空で初期化 - //SelectionData selectionData = usePaintMap ? new SelectionData() : sdata2.selectionData; SelectionData selectionData = usePaintMap ? new SelectionData() : sdata2.selectionData.Clone(); // ■スレッド @@ -564,7 +576,7 @@ namespace MagicaCloth2 renderMesh.result.SetProcess(); // インポート - renderMesh.ImportFrom(setup); + renderMesh.ImportFrom(setup, sdata.GetUvChannel()); //Debug.Log($"(IMPORT) {renderMesh}"); if (renderMesh.IsError) continue; @@ -605,7 +617,7 @@ namespace MagicaCloth2 else if (sdata.clothType == ClothProcess.ClothType.BoneCloth || sdata.clothType == ClothProcess.ClothType.BoneSpring) { // import - editMesh.ImportFrom(setupList[0]); + editMesh.ImportFrom(setupList[0], 0); if (editMesh.IsError) { result.Merge(editMesh.result); @@ -723,8 +735,6 @@ namespace MagicaCloth2 ct.ThrowIfCancellationRequested(); if (cloth == null || isValid == false) { - //result.SetError(Define.Result.CreateCloth_InvalidCloth); - //throw new MagicaClothProcessingException(); // キャンセル扱いにする throw new OperationCanceledException(); } @@ -760,16 +770,22 @@ namespace MagicaCloth2 var info = editClothDict[id]; info.building = false; info.result = result; - info.editMesh?.Dispose(); + info.editMeshContainer?.Dispose(); if (result.IsSuccess()) { - info.editMesh = editMesh; - editMesh = null; + info.editMeshContainer = editMeshContainer; + editMeshContainer = null; + info.editInitSerializeData = editInitSerializeData; Develop.DebugLog($"Registration Complete : {cloth.name}"); + + // 初期化データの保存 + // ここではローカルハッシュのみの比較とする + ApplyInitData(cloth, global: false); } else { - info.editMesh = null; + info.editMeshContainer = null; + info.editInitSerializeData = null; } } } @@ -780,7 +796,7 @@ namespace MagicaCloth2 { setup?.Dispose(); } - editMesh?.Dispose(); + editMeshContainer?.Dispose(); //span.DebugLog(); @@ -821,6 +837,42 @@ namespace MagicaCloth2 } } + /// + /// 初期化データをシリアライズ化する + /// + /// + /// + public static void ApplyInitData(MagicaCloth cloth, bool global) + { + if (cloth == null) + return; + int id = cloth.GetInstanceID(); + if (editClothDict.ContainsKey(id) == false) + return; + + var info = editClothDict[id]; + if (info.editInitSerializeData == null) + return; + + // ハッシュ比較 + var sdata2 = cloth.GetSerializeData2(); + int oldLocalHash = sdata2.initData?.localHash ?? 0; + bool change = oldLocalHash != info.editInitSerializeData.localHash; + if (global && change == false) + { + int oldGlobalHash = sdata2.initData?.globalHash ?? 0; + change = oldGlobalHash != info.editInitSerializeData.globalHash; + } + if (change == false) + return; // 変更なし + + // 初期化データ保存 + // Undoの対象にはしない + sdata2.initData = info.editInitSerializeData; + EditorUtility.SetDirty(cloth); + Develop.DebugLog($"* Apply initData. [{cloth.name}]"); + } + /// /// セレクションデータをシリアライズ化する /// @@ -867,7 +919,7 @@ namespace MagicaCloth2 // BoneSpringではLine接続のみとなる var connectionMode = sdata.clothType == ClothProcess.ClothType.BoneSpring ? RenderSetupData.BoneConnectionMode.Line : sdata.connectionMode; var setupType = sdata.clothType == ClothProcess.ClothType.BoneSpring ? RenderSetupData.SetupType.BoneSpring : RenderSetupData.SetupType.BoneCloth; - using var setup = new RenderSetupData(setupType, cloth.ClothTransform, sdata.rootBones, null, connectionMode, cloth.name); + using var setup = new RenderSetupData(null, setupType, cloth.ClothTransform, sdata.rootBones, null, connectionMode, cloth.name); foreach (int id in setup.rootTransformIdList) { int rootIndex = setup.GetTransformIndexFromId(id); @@ -917,33 +969,33 @@ namespace MagicaCloth2 if (info.component.isActiveAndEnabled == false) continue; + if (info.component.IsGizmoVisible == false) + continue; + // ペイント中は表示しない if (isPainting) continue; - // アクティブ状態 - bool active = info.gizmoType.HasFlag(GizmoType.Active); - // 選択状態 - bool selected = Selection.Contains(info.component.gameObject); + bool selected = IsActiveOrSelected(info.gizmoType); float dist = Vector3.Distance(camPos, info.component.transform.position); // Collider if (info.component is ColliderComponent) { - if (active == false && info.gizmoType.HasFlag(GizmoType.Selected) == false) + // Colliderは親選択時にも表示する + if (IsSelectionHierarchy(info.gizmoType) == false) continue; if (selected == false && dist >= 20.0f) continue; - GizmoUtility.DrawCollider(info.component as ColliderComponent, camRot, true, active); + GizmoUtility.DrawCollider(info.component as ColliderComponent, camRot, selected); } // MagicaCloth else if (info.component is MagicaCloth) { - if (active == false) - continue; - if (selected == false && dist >= 20.0f) + // Clothはアクティブもしくはマルチ選択時のみ表示 + if (IsActiveOrSelected(info.gizmoType) == false) continue; var cloth = info.component as MagicaCloth; @@ -951,11 +1003,10 @@ namespace MagicaCloth2 // Cloth if (cloth.GizmoSerializeData.clothDebugSettings.enable) { - //Debug.Log($"ペイントくろす"); if (isPlaying) - ClothEditorUtility.DrawClothRuntime(cloth.Process, cloth.GizmoSerializeData.clothDebugSettings, active); + ClothEditorUtility.DrawClothRuntime(cloth.Process, cloth.GizmoSerializeData.clothDebugSettings, selected); else - ClothEditorUtility.DrawClothEditor(info.editMesh, cloth.GizmoSerializeData.clothDebugSettings, cloth.SerializeData, active, false, false); + ClothEditorUtility.DrawClothEditor(info.editMeshContainer, cloth.GizmoSerializeData.clothDebugSettings, cloth.SerializeData, selected, false, false); } #if MC2_DEBUG @@ -963,9 +1014,9 @@ namespace MagicaCloth2 if (cloth.GizmoSerializeData.proxyDebugSettings.enable) { if (isPlaying) - VirtualMeshEditorUtility.DrawRuntimeGizmos(cloth.Process, false, cloth.Process.ProxyMesh, cloth.GizmoSerializeData.proxyDebugSettings, active, true); + VirtualMeshEditorUtility.DrawRuntimeGizmos(cloth.Process, false, cloth.Process.ProxyMeshContainer, cloth.GizmoSerializeData.proxyDebugSettings, selected, true); else - VirtualMeshEditorUtility.DrawGizmos(info.editMesh, cloth.GizmoSerializeData.proxyDebugSettings, active, true); + VirtualMeshEditorUtility.DrawGizmos(info.editMeshContainer, cloth.GizmoSerializeData.proxyDebugSettings, selected, true); } // Mapping Mesh @@ -974,8 +1025,8 @@ namespace MagicaCloth2 if (isPlaying) { var renderMeshInfo = cloth.Process.GetRenderMeshInfo(cloth.GizmoSerializeData.debugMappingIndex); - if (renderMeshInfo != null && renderMeshInfo.renderMesh != null) - VirtualMeshEditorUtility.DrawRuntimeGizmos(cloth.Process, true, renderMeshInfo.renderMesh, cloth.GizmoSerializeData.mappingDebugSettings, active, true); + if (renderMeshInfo != null && renderMeshInfo.renderMeshContainer != null) + VirtualMeshEditorUtility.DrawRuntimeGizmos(cloth.Process, true, renderMeshInfo.renderMeshContainer, cloth.GizmoSerializeData.mappingDebugSettings, selected, true); } } #endif // MC2_DEBUG @@ -983,14 +1034,74 @@ namespace MagicaCloth2 // WindZone else if (info.component is MagicaWindZone) { - GizmoUtility.DrawWindZone(info.component as MagicaWindZone, camRot, active); + GizmoUtility.DrawWindZone(info.component as MagicaWindZone, camRot, selected); } + } - // 描画フラグoff - info.gizmoType = 0; + // 描画フラグoff + foreach (var info in editClothDict.Values) + { + if (info != null) + { + info.gizmoType = 0; + if (info.component) + info.component.IsGizmoVisible = false; + } } } } } + + //========================================================================================= + public static async Task InformationLog(StringBuilder allsb) + { + StringBuilder sb = new StringBuilder(); + + sb.AppendLine($"========== System Info =========="); + sb.AppendLine($"Unity Version:{Application.unityVersion}"); + sb.AppendLine($"MagicaCloth Version:{AboutMenu.MagicaClothVersion}"); + sb.AppendLine($"PlayMode:{Application.isPlaying}"); + sb.AppendLine($"CPU Type:{SystemInfo.processorType}"); + sb.AppendLine($"CPU Freq:{SystemInfo.processorFrequency}"); + sb.AppendLine($"CPU Core:{SystemInfo.processorCount}"); + sb.AppendLine($"Device Type:{SystemInfo.deviceType}"); + sb.AppendLine($"OS:{SystemInfo.operatingSystem}"); + sb.AppendLine($"OS Family:{SystemInfo.operatingSystemFamily}"); + + // インストールパッケージ一覧 + sb.AppendLine($"<< Install Packages >>"); + var listRequest = Client.List(true, false); + int timeout = 5000; // 5s + while (listRequest.IsCompleted == false && timeout > 0) + { + await Task.Delay(50); + timeout -= 50; + } + if (listRequest.IsCompleted) + { + if (listRequest.Status == StatusCode.Success) + { + foreach (var package in listRequest.Result) + { + //Debug.Log($"{package.name} : {package.version}"); + sb.AppendLine($"{package.name} : {package.version}"); + } + } + else + { + sb.AppendLine($"Package request error!"); + Debug.LogWarning($"Package request error!"); + } + } + else + { + sb.AppendLine($"Package request timeout!"); + Debug.LogWarning($"Package request timeout!"); + } + sb.AppendLine(); + + Debug.Log(sb.ToString()); + allsb.Append(sb); + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorManager.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorManager.cs.meta index f620c358..780ea505 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorManager.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorManager.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorManager.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorUtility.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorUtility.cs index 53eb3ba2..f3ea90b4 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorUtility.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorUtility.cs @@ -54,9 +54,10 @@ namespace MagicaCloth2 /// /// /// - public static void DrawClothEditor(VirtualMesh editMesh, ClothDebugSettings drawSettings, ClothSerializeData serializeData, bool selected, bool direction, bool paint) + /// 頂点ペイント中はtrue + public static void DrawClothEditor(VirtualMeshContainer editMeshContainer, ClothDebugSettings drawSettings, ClothSerializeData serializeData, bool selected, bool direction, bool painting) { - if (editMesh == null || editMesh.IsSuccess == false) + if (editMeshContainer == null || editMeshContainer.shareVirtualMesh == null || editMeshContainer.shareVirtualMesh.IsSuccess == false) return; if (drawSettings.enable == false || serializeData == null) @@ -69,7 +70,8 @@ namespace MagicaCloth2 var crot = scam.transform.rotation; // 座標空間に合わせる - var t = editMesh.GetCenterTransform(); + var editMesh = editMeshContainer.shareVirtualMesh; + var t = editMeshContainer.GetCenterTransform(); if (t == null) return; @@ -388,7 +390,7 @@ namespace MagicaCloth2 #endif // inertia center - if (paint == false && editMesh.CenterFixedPointCount > 0 && drawSettings.inertiaCenter) + if (painting == false && editMesh.CenterFixedPointCount > 0 && drawSettings.inertiaCenter) { float3 pos = 0; int ccnt = editMesh.CenterFixedPointCount; @@ -402,17 +404,20 @@ namespace MagicaCloth2 } Handles.matrix = Matrix4x4.identity; + crot = scam.transform.rotation; // custom skinning bone - if (paint == false) + if (painting == false && serializeData.customSkinningSetting.enable && drawSettings.customSkinningBone) { Handles.color = SkininngLine * colorScale; var boneList = serializeData.customSkinningSetting.skinningBones; +#if MC2_CUSTOM_SKINNING_V1 for (int i = 0; i < boneList.Count - 1; i++) { var bone1 = boneList[i]; if (bone1 == null) continue; + for (int j = i + 1; j < boneList.Count; j++) { var bone2 = boneList[j]; @@ -425,6 +430,17 @@ namespace MagicaCloth2 } } } +#else + // V2 + for (int i = 0; i < boneList.Count; i++) + { + var bone1 = boneList[i]; + if (bone1 == null) + continue; + + GizmoUtility.DrawWireSphere(bone1.position, quaternion.identity, drawSettings.GetCustomSkinningRadius(), crot, true); + } +#endif } } @@ -445,7 +461,7 @@ namespace MagicaCloth2 return; // プロキシメッシュ - var proxyMesh = cprocess.ProxyMesh; + var proxyMesh = cprocess.ProxyMeshContainer?.shareVirtualMesh; if (proxyMesh == null || proxyMesh.IsSuccess == false) return; @@ -530,7 +546,7 @@ namespace MagicaCloth2 } else { - float radius = cprocess.parameters.radiusCurveData.EvaluateCurve(depth); + float radius = cprocess.parameters.radiusCurveData.MC2EvaluateCurve(depth); radius *= tdata.scaleRatio; GizmoUtility.DrawSphere(pos, drawSettings.CheckRadiusDrawing() ? radius : drawPointSize, true); } @@ -1062,16 +1078,35 @@ namespace MagicaCloth2 Handles.Label(cen, i.ToString()); } } + // base line pos + if (drawSettings.baseLinePos) + { + var col = new Color(1.0f, 0.7f, 0.3f); + for (int i = 0; i < pcnt; i++) + { + if (drawSettings.CheckParticleDrawing(i) == false) + continue; + + int pindex = tdata.particleChunk.startIndex + i; + + var pos = sim.stepBasicPositionBuffer[pindex]; + GizmoUtility.SetColor(col * colorScale, true); + GizmoUtility.DrawSphere(pos, drawPointSize, true); + } + } #endif // 空間を戻す Handles.matrix = Matrix4x4.identity; + crot = scam.transform.rotation; // 以下はワールド // custom skinning bone + if (cprocess.cloth.SerializeData.customSkinningSetting.enable && drawSettings.customSkinningBone) { Handles.color = SkininngLine * colorScale; var boneList = cprocess.cloth.SerializeData.customSkinningSetting.skinningBones; +#if MC2_CUSTOM_SKINNING_V1 for (int i = 0; i < boneList.Count - 1; i++) { var bone1 = boneList[i]; @@ -1089,6 +1124,17 @@ namespace MagicaCloth2 } } } +#else + // V2 + for (int i = 0; i < boneList.Count; i++) + { + var bone1 = boneList[i]; + if (bone1 == null) + continue; + + GizmoUtility.DrawWireSphere(bone1.position, quaternion.identity, drawSettings.GetCustomSkinningRadius(), crot, true); + } +#endif } diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorUtility.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorUtility.cs.meta index 633458b0..72b76faf 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorUtility.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorUtility.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothEditorUtility.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothInspectorUtility.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothInspectorUtility.cs.meta index 08d88eb0..6efa362d 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothInspectorUtility.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothInspectorUtility.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothInspectorUtility.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPainter.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPainter.cs index 59d8397f..1ba59758 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPainter.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPainter.cs @@ -47,7 +47,7 @@ namespace MagicaCloth2 /// /// 編集対象のエディットメッシュ /// - static VirtualMesh editMesh = null; + static VirtualMeshContainer editMeshContainer = null; /// /// 編集対象のセレクションデータ @@ -98,22 +98,22 @@ namespace MagicaCloth2 /// ペイント開始 /// /// - public static void EnterPaint(PaintMode mode, MagicaClothEditor editor, MagicaCloth clothComponent, VirtualMesh vmesh, SelectionData sdata) + public static void EnterPaint(PaintMode mode, MagicaClothEditor editor, MagicaCloth clothComponent, VirtualMeshContainer cmesh, SelectionData sdata) { Develop.DebugLog($"EnterPaint"); paintMode = mode; cloth = clothComponent; clothEditor = editor; - editMesh = vmesh; + editMeshContainer = cmesh; selectionData = sdata; initSelectionData = sdata.Clone(); rayhit = default; forceUpdate = true; // ポイントバッファ - dispPointList = new NativeList(vmesh.VertexCount, Allocator.Persistent); - pointWorldPositions = new NativeArray(vmesh.VertexCount, Allocator.Persistent); + dispPointList = new NativeList(cmesh.shareVirtualMesh.VertexCount, Allocator.Persistent); + pointWorldPositions = new NativeArray(cmesh.shareVirtualMesh.VertexCount, Allocator.Persistent); // UndoRedoコールバック Undo.undoRedoPerformed += UndoRedoCallback; @@ -128,7 +128,7 @@ namespace MagicaCloth2 cloth = null; clothEditor = null; - editMesh = null; + editMeshContainer = null; selectionData = null; initSelectionData = null; rayhit = default; @@ -152,11 +152,11 @@ namespace MagicaCloth2 if (EditorApplication.isPlaying) return; - if (cloth == null || editMesh == null || selectionData == null || editMesh.IsSuccess == false) + if (cloth == null || editMeshContainer == null || selectionData == null || editMeshContainer.shareVirtualMesh.IsSuccess == false) return; // セレクションデータを取り直す - selectionData = clothEditor.GetSelectionData(cloth, editMesh); + selectionData = clothEditor.GetSelectionData(cloth, editMeshContainer.shareVirtualMesh); forceUpdate = true; } @@ -191,9 +191,9 @@ namespace MagicaCloth2 if (SceneView.lastActiveSceneView != sceneView) return; - if (cloth == null || editMesh == null || selectionData == null) + if (cloth == null || editMeshContainer == null || editMeshContainer.shareVirtualMesh == null || selectionData == null) return; - if (editMesh.IsSuccess == false || selectionData.IsValid() == false) + if (editMeshContainer.shareVirtualMesh.IsSuccess == false || selectionData.IsValid() == false) return; var windata = ScriptableSingleton.instance; @@ -326,7 +326,7 @@ namespace MagicaCloth2 // ペイント中のギズモ表示 if (windata.showShape) - ClothEditorUtility.DrawClothEditor(editMesh, ClothEditorUtility.PaintSettings, cloth.SerializeData, true, windata.backFaceCulling, true); + ClothEditorUtility.DrawClothEditor(editMeshContainer, ClothEditorUtility.PaintSettings, cloth.SerializeData, true, windata.backFaceCulling, true); } // GUI @@ -384,7 +384,8 @@ namespace MagicaCloth2 CreateDispPointList(through, ct, cam, showAll, brushSize, brushPos).Complete(); // サーフェース交差判定 - rayhit = editMesh.IntersectRayMesh(ray.origin, ray.direction, showAll, pointSize); + //rayhit = editMesh.IntersectRayMesh(ray.origin, ray.direction, showAll, pointSize); + rayhit = editMeshContainer.shareVirtualMesh.IntersectRayMesh(ray.origin, ray.direction, showAll, pointSize); } static JobHandle CreateDispPointList( @@ -394,6 +395,7 @@ namespace MagicaCloth2 { dispPointList.Clear(); + var editMesh = editMeshContainer.shareVirtualMesh; int vcnt = editMesh.VertexCount; if (vcnt == 0) return jobHandle; @@ -698,7 +700,8 @@ namespace MagicaCloth2 static void Fill(ClothPainterWindowData windata) { // 塗りつぶし用のポイントデータを作成する - int vcnt = editMesh.VertexCount; + //int vcnt = editMesh.VertexCount; + int vcnt = editMeshContainer.shareVirtualMesh.VertexCount; using var fillDispPointList = new NativeList(vcnt, Allocator.TempJob); BitField32 flag = new(); flag.SetBits(PointFlag_Selecting, true); @@ -860,6 +863,9 @@ namespace MagicaCloth2 // ペイント終了ボタン if (GUILayout.Button("Exit")) { + // 初期化データの保存確認 + ClothEditorManager.ApplyInitData(cloth, global: true); + // ペイント終了フラグ cloth = null; diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPainter.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPainter.cs.meta index 775b7326..a10d3b44 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPainter.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPainter.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPainter.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPresetUtility.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPresetUtility.cs.meta index fafeb6ba..60e3cb6e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPresetUtility.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPresetUtility.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/ClothPresetUtility.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaCapsuleColliderEditor.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaCapsuleColliderEditor.cs index deaa0a1e..488c8256 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaCapsuleColliderEditor.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaCapsuleColliderEditor.cs @@ -10,14 +10,16 @@ namespace MagicaCloth2 /// CapsuleColliderのエディタ拡張 /// [CustomEditor(typeof(MagicaCapsuleCollider))] - public class MagicaCapsuleColliderEditor : Editor + [CanEditMultipleObjects] + public class MagicaCapsuleColliderEditor : MagicaEditorBase { public override void OnInspectorGUI() { var scr = target as MagicaCapsuleCollider; + const string undoName = "CapsuleCollider"; serializedObject.Update(); - Undo.RecordObject(scr, "CapsuleCollider"); + Undo.RecordObject(scr, undoName); // separation var separationValue = serializedObject.FindProperty("radiusSeparation"); @@ -26,6 +28,9 @@ namespace MagicaCloth2 var directionValue = serializedObject.FindProperty("direction"); EditorGUILayout.PropertyField(directionValue); + // reverse direction + EditorGUILayout.PropertyField(serializedObject.FindProperty("reverseDirection")); + // aligned on center var alignedOnCenterValue = serializedObject.FindProperty("alignedOnCenter"); EditorGUILayout.PropertyField(alignedOnCenterValue); @@ -33,8 +38,19 @@ namespace MagicaCloth2 var sizeValue = serializedObject.FindProperty("size"); var size = sizeValue.vector3Value; + // マルチ選択時について + // CapsuleColliderではEditorGUI.showMixedValueは設定しない + // EditorGUI.showMixedValueを設定すると異なる値の場合は「ー」で表記されるようになるが、 + // カプセルコライダーでは1つのVector3に3つの異なるスライダーを割り当てているため、 + // 各スライダーの値が同じ場合でも「ー」表記になってしまう + // そうならないようにアクティブなコンポーネントの数値のみを表示するように、showMixedValueは常にfalseにしておく + // length - size.z = EditorGUILayout.Slider("Length", size.z, 0.0f, 2.0f); + using (var check = new EditorGUI.ChangeCheckScope()) + { + var newSize = EditorGUILayout.Slider("Length", size.z, 0.0f, 2.0f); + ApplyMultiSelection(check.changed, undoName, x => x.SetSizeZ(newSize)); + } // radius float lineHight = EditorGUIUtility.singleLineHeight; @@ -52,7 +68,11 @@ namespace MagicaCloth2 var sliderRect = new Rect(positionA.x, r.y, Mathf.Max(w - 35, 0), lineHight); // Slider - size.x = EditorGUI.Slider(sliderRect, size.x, 0.001f, 0.5f); + using (var check = new EditorGUI.ChangeCheckScope()) + { + var newSize = EditorGUI.Slider(sliderRect, size.x, 0.001f, 0.5f); + ApplyMultiSelection(check.changed, undoName, x => x.SetSizeX(newSize)); + } // 分割ボタン if (GUI.Button(buttonRect, scr.radiusSeparation ? "X" : "S")) @@ -75,18 +95,22 @@ namespace MagicaCloth2 var sliderRect = new Rect(positionA.x, r.y, Mathf.Max(w - 35, 0), lineHight); // Slider - size.y = EditorGUI.Slider(sliderRect, size.y, 0.001f, 0.5f); + using (var check = new EditorGUI.ChangeCheckScope()) + { + var newSize = EditorGUI.Slider(sliderRect, size.y, 0.001f, 0.5f); + ApplyMultiSelection(check.changed, undoName, x => x.SetSizeY(newSize)); + } } - //size.x = EditorGUILayout.Slider("Start Radius", size.x, 0.001f, 0.5f); - //size.y = EditorGUILayout.Slider("End Radius", size.y, 0.001f, 0.5f); - - // サイズ格納 - sizeValue.vector3Value = size; - // center - var centerValue = serializedObject.FindProperty("center"); - centerValue.vector3Value = EditorGUILayout.Vector3Field("Center", centerValue.vector3Value); + EditorGUILayout.PropertyField(serializedObject.FindProperty("center")); + + // Symmetry + EditorGUILayout.Space(); + var symmetryModeProperty = serializedObject.FindProperty("symmetryMode"); + EditorGUILayout.PropertyField(symmetryModeProperty); + if (symmetryModeProperty.enumValueIndex >= (int)ColliderSymmetryMode.AutomaticTarget) + EditorGUILayout.PropertyField(serializedObject.FindProperty("symmetryTarget")); serializedObject.ApplyModifiedProperties(); } diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaCapsuleColliderEditor.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaCapsuleColliderEditor.cs.meta index 2fa8017f..68abcc43 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaCapsuleColliderEditor.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaCapsuleColliderEditor.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaCapsuleColliderEditor.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaClothEditor.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaClothEditor.cs index 4e052f7c..5f4c7167 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaClothEditor.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaClothEditor.cs @@ -11,7 +11,7 @@ namespace MagicaCloth2 /// [CustomEditor(typeof(MagicaCloth))] [CanEditMultipleObjects] - public class MagicaClothEditor : Editor + public class MagicaClothEditor : MagicaEditorBase { //========================================================================================= private void Awake() @@ -104,10 +104,14 @@ namespace MagicaCloth2 EditorGUILayout.Space(); EditorGUILayout.Space(); EditorGUILayout.Space(); + EditorGUILayout.Space(); + EditorGUILayout.Space(); ClothParameterInspector(); EditorGUILayout.Space(); EditorGUILayout.Space(); GizmoInspector(); + EditorGUILayout.Space(); + ClothPreBuildInspector(); serializedObject.ApplyModifiedProperties(); //DrawDefaultInspector(); @@ -116,9 +120,16 @@ namespace MagicaCloth2 int nowActive = cloth.isActiveAndEnabled ? 1 : 0; if (nowActive != oldAcitve) { - //Debug.Log($"[{cloth.name}] rebuild. active:{nowActive}"); oldAcitve = nowActive; - ClothEditorManager.RegisterComponent(cloth, nowActive > 0 ? GizmoType.Active : 0, true); + + // ただしコンポーネントがProjectビューで選択されている場合は再構築しない + // Hierarchyおよびプレハブモードはこれに該当しない + bool inProject = AssetDatabase.Contains(cloth.gameObject.GetInstanceID()); + if (inProject == false) + { + //Develop.Log($"[{cloth.name}] rebuild. active:{nowActive}, inProject:{inProject}"); + ClothEditorManager.RegisterComponent(cloth, nowActive > 0 ? GizmoType.Active : 0, true); + } } } @@ -152,41 +163,61 @@ namespace MagicaCloth2 void DispVersion() { EditorGUILayout.LabelField($"Version {AboutMenu.MagicaClothVersion}"); - //using (new EditorGUILayout.HorizontalScope()) - //{ - // //GUILayout.FlexibleSpace(); - // EditorGUILayout.Space(); - // EditorGUILayout.LabelField($"Version {AboutMenu.MagicaClothVersion}", GUILayout.Width(100)); - //} } void DispStatus() { var cloth = target as MagicaCloth; - ResultCode result; if (EditorApplication.isPlaying) { - result = cloth.Process.Result; + StaticStringBuilder.Clear(); + StaticStringBuilder.AppendLine("[State]"); + StaticStringBuilder.Append(cloth.Process.IsState(ClothProcess.State_UsePreBuild) ? "Pre-Build Construction" : "Runtime Construction"); + DispClothStatus(StaticStringBuilder.ToString(), cloth.Process.Result, true); } else { - result = ClothEditorManager.GetResultCode(cloth); + var result = ClothEditorManager.GetResultCode(cloth); + var preBuildData = cloth.GetSerializeData2().preBuildData; + if (preBuildData.enabled) + { + // pre-build + if (result.IsError() == false) + result = preBuildData.DataValidate(); + DispClothStatus("[Pre-Build Construction]", result, false); + } + else + { + // runtime + DispClothStatus("[Runtime Construction]", result, true); + } } + } + + void DispClothStatus(string title, ResultCode result, bool dispWarning) + { + StaticStringBuilder.Clear(); + StaticStringBuilder.AppendLine(title); // normal / error MessageType mtype = MessageType.Info; if (result.IsError()) mtype = MessageType.Error; - var infoMessage = result.GetResultInformation(); if (infoMessage != null) - EditorGUILayout.HelpBox($"{result.GetResultString()}\n{infoMessage}", mtype); + { + StaticStringBuilder.AppendLine(result.GetResultString()); + StaticStringBuilder.AppendLine(infoMessage); + } else - EditorGUILayout.HelpBox(result.GetResultString(), mtype); + { + StaticStringBuilder.AppendLine(result.GetResultString()); + } + EditorGUILayout.HelpBox(StaticStringBuilder.ToString(), mtype); // warning - if (result.IsWarning()) + if (dispWarning && result.IsWarning()) { mtype = MessageType.Warning; infoMessage = result.GetWarningInformation(); @@ -201,30 +232,55 @@ namespace MagicaCloth2 { var cloth = target as MagicaCloth; - VirtualMesh vmesh = null; + VirtualMeshContainer cmesh; if (EditorApplication.isPlaying) { - vmesh = cloth.Process?.ProxyMesh; + cmesh = cloth.Process?.ProxyMeshContainer; } else { - vmesh = ClothEditorManager.GetEditMesh(cloth); + cmesh = ClothEditorManager.GetEditMeshContainer(cloth); } - if (vmesh == null) + if (cmesh == null || cmesh.shareVirtualMesh == null) return; + var vmesh = cmesh.shareVirtualMesh; + StaticStringBuilder.Clear(); + + // 初期化データ + StaticStringBuilder.AppendLine("[Init Data]"); + int initVersion = cloth.GetSerializeData2().initData?.initVersion ?? 0; + if (initVersion > 0) + { + StaticStringBuilder.Append($"v{initVersion}: "); + } + if (EditorApplication.isPlaying) + { + StaticStringBuilder.Append($"{cloth.Process.InitDataResult.GetResultString()}"); + } + else + { + StaticStringBuilder.Append($"{cloth.GetSerializeData2().initData.HasData()}"); + } + + // Proxyメッシュ + StaticStringBuilder.AppendLine(); if (EditorApplication.isPlaying) StaticStringBuilder.AppendLine("[Proxy Mesh]"); else StaticStringBuilder.AppendLine("[Edit Mesh]"); if (EditorApplication.isPlaying) - StaticStringBuilder.AppendLine($"Visible: {!cloth.Process.IsCullingInvisible()}"); + { + StaticStringBuilder.AppendLine($"Camera Visible: {!cloth.Process.IsCameraCullingInvisible()}"); + StaticStringBuilder.AppendLine($"Distance Visible: {!cloth.Process.IsDistanceCullingInvisible()}"); + } StaticStringBuilder.AppendLine($"Vertex: {vmesh.VertexCount}"); StaticStringBuilder.AppendLine($"Edge: {vmesh.EdgeCount}"); StaticStringBuilder.AppendLine($"Triangle: {vmesh.TriangleCount}"); StaticStringBuilder.AppendLine($"SkinBoneCount: {vmesh.SkinBoneCount}"); - StaticStringBuilder.Append($"TransformCount: {vmesh.TransformCount}"); + StaticStringBuilder.Append($"TransformCount: {cmesh.GetTransformCount()}"); + EditorGUILayout.HelpBox(StaticStringBuilder.ToString(), MessageType.Info); } @@ -239,7 +295,7 @@ namespace MagicaCloth2 bool runtime = EditorApplication.isPlaying; // 同期状態 - bool sync = EditorApplication.isPlaying && cloth.SyncCloth != null; + bool sync = EditorApplication.isPlaying && cloth.SyncPartnerCloth != null; EditorGUILayout.LabelField("Main", EditorStyles.boldLabel); @@ -278,12 +334,27 @@ namespace MagicaCloth2 else if (clothType == ClothProcess.ClothType.MeshCloth) { EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.sourceRenderers")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.meshWriteMode")); EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.reductionSetting")); } EditorGUILayout.Space(); - EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.updateMode")); + if (sync == false) + EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.updateMode")); + else + { + // 同期中は操作不可 + using (new EditorGUI.DisabledScope(true)) + { + using (new EditorGUILayout.HorizontalScope()) + { + EditorGUILayout.LabelField("Update Mode"); + EditorGUILayout.LabelField("(Synchronizing)"); + } + } + } EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.animationPoseRatio")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.blendWeight")); EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.normalAxis")); EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.normalAlignmentSetting.alignmentMode"), new GUIContent("Normal Alignment")); if (cloth.SerializeData.normalAlignmentSetting.alignmentMode == NormalAlignmentSettings.AlignmentMode.Transform) @@ -298,6 +369,7 @@ namespace MagicaCloth2 if (paintMode.enumValueIndex != 0) { EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.paintMaps")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.paintMapUvChannel")); } } } @@ -332,6 +404,14 @@ namespace MagicaCloth2 { EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.cullingSettings.cameraCullingRenderers")); } + EditorGUILayout.Space(); + EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.cullingSettings.distanceCullingLength")); + using (new EditorGUI.DisabledScope(cloth.SerializeData.cullingSettings.distanceCullingLength.use == false)) + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.cullingSettings.distanceCullingFadeRatio")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.cullingSettings.distanceCullingReferenceObject")); + EditorGUILayout.HelpBox("If Reference Object is [None], the main camera is referred.", MessageType.None); + } } else { @@ -348,11 +428,68 @@ namespace MagicaCloth2 EditorGUILayout.LabelField("Camera Culling Method"); EditorGUILayout.LabelField("(Synchronizing)"); } + using (new EditorGUILayout.HorizontalScope()) + { + EditorGUILayout.LabelField("Distance Culling Length"); + EditorGUILayout.LabelField("(Synchronizing)"); + } + using (new EditorGUILayout.HorizontalScope()) + { + EditorGUILayout.LabelField("Distance Culling Fade Ratio"); + EditorGUILayout.LabelField("(Synchronizing)"); + } + using (new EditorGUILayout.HorizontalScope()) + { + EditorGUILayout.LabelField("Distance Culling Reference Object"); + EditorGUILayout.LabelField("(Synchronizing)"); + } } } }); } + void ClothPreBuildInspector() + { + var cloth = target as MagicaCloth; + + bool generation = false; + + using (new EditorGUI.DisabledScope(EditorApplication.isPlaying)) + { + Foldout("Pre-Build", serializedObject.FindProperty("serializeData2.preBuildData.enabled"), null, () => + { + // information + var preBuildData = cloth.GetSerializeData2().preBuildData; + if (preBuildData.UsePreBuild()) + { + DispClothStatus("[Pre-Build Construction]", preBuildData.DataValidate(), false); + } + + EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData2.preBuildData.buildId"), new GUIContent("Build ID")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData2.preBuildData.preBuildScriptableObject"), new GUIContent("Write Object")); + using (var horizontalScope = new GUILayout.HorizontalScope()) + { + EditorGUILayout.Space(); + GUI.backgroundColor = Color.red; + if (GUILayout.Button("Create PreBuild Data")) + { + generation = true; + } + GUI.backgroundColor = Color.white; + EditorGUILayout.Space(); + } + }); + } + + if (generation) + { + // PreBuildデータ構築実行 + Develop.Log($"Start PreBuild data creation."); + var preBuildResult = PreBuildDataCreation.CreatePreBuildData(cloth); + Develop.Log($"PreBuild data creation completed. [{cloth.GetSerializeData2().preBuildData.buildId}] : {preBuildResult.GetResultString()}"); + } + } + void ClothParameterInspector() { var cloth = target as MagicaCloth; @@ -360,7 +497,7 @@ namespace MagicaCloth2 bool isBoneSpring = clothType == ClothProcess.ClothType.BoneSpring; // 同期状態 - bool sync = EditorApplication.isPlaying && cloth.SyncCloth != null; + bool sync = EditorApplication.isPlaying && cloth.SyncPartnerCloth != null; ClothPresetUtility.DrawPresetButton(cloth, cloth.SerializeData); @@ -426,7 +563,12 @@ namespace MagicaCloth2 { if (sync == false) { + EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.inertiaConstraint.anchor")); + if (cloth.SerializeData.inertiaConstraint.anchor != null) + EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.inertiaConstraint.anchorInertia")); + EditorGUILayout.Space(); EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.inertiaConstraint.worldInertia")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.inertiaConstraint.movementInertiaSmoothing"), new GUIContent("World Inertia Smoothing")); EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.inertiaConstraint.movementSpeedLimit"), new GUIContent("World Movement Speed Limit")); EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.inertiaConstraint.rotationSpeedLimit"), new GUIContent("World Rotation Speed Limit")); EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.inertiaConstraint.teleportMode")); @@ -438,12 +580,28 @@ namespace MagicaCloth2 // 同期中は操作不可 using (new EditorGUI.DisabledScope(true)) { + using (new EditorGUILayout.HorizontalScope()) + { + EditorGUILayout.LabelField("Anchor"); + EditorGUILayout.LabelField("(Synchronizing)"); + } + using (new EditorGUILayout.HorizontalScope()) + { + EditorGUILayout.LabelField("Anchor Inertia"); + EditorGUILayout.LabelField("(Synchronizing)"); + } + EditorGUILayout.Space(); using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField("World Inertia"); EditorGUILayout.LabelField("(Synchronizing)"); } using (new EditorGUILayout.HorizontalScope()) + { + EditorGUILayout.LabelField("World Inertia Smoothing"); + EditorGUILayout.LabelField("(Synchronizing)"); + } + using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField("World Movement Speed Limit"); EditorGUILayout.LabelField("(Synchronizing)"); @@ -539,7 +697,7 @@ namespace MagicaCloth2 // Self Collision if (isBoneSpring == false) { - Foldout("Self Collision", "Self Collision (Beta)", () => + Foldout("Self Collision", "Self Collision (Beta2)", () => { EditorGUILayout.PropertyField(serializedObject.FindProperty("serializeData.selfCollisionConstraint.selfMode")); var syncMode = serializedObject.FindProperty("serializeData.selfCollisionConstraint.syncMode"); @@ -601,6 +759,9 @@ namespace MagicaCloth2 case "particleSpeedLimit": minmax.Set(0.0f, Define.System.MaxParticleSpeedLimit); break; + case "distanceCullingLength": + minmax.Set(0.0f, Define.System.DistanceCullingMaxLength); + break; } return minmax; @@ -770,22 +931,25 @@ namespace MagicaCloth2 if (edit == false) { // 最新の編集メッシュからセレクションデータを生成する - var editMesh = ClothEditorManager.GetEditMesh(cloth); - if (editMesh != null) + var editMeshContainer = ClothEditorManager.GetEditMeshContainer(cloth); + if (editMeshContainer != null && editMeshContainer.shareVirtualMesh != null) { // すでにセレクションデータが存在し、かつユーザー編集データならばコンバートする - var selectionData = GetSelectionData(cloth, editMesh); + var selectionData = GetSelectionData(cloth, editMeshContainer.shareVirtualMesh); // セレクションデータにメッシュの最大接続距離を記録する - selectionData.maxConnectionDistance = editMesh.maxVertexDistance.Value; + selectionData.maxConnectionDistance = editMeshContainer.shareVirtualMesh.maxVertexDistance.Value; // ペイント開始 - ClothPainter.EnterPaint(paintMode, this, cloth, editMesh, selectionData); + ClothPainter.EnterPaint(paintMode, this, cloth, editMeshContainer, selectionData); SceneView.RepaintAll(); } } else { + // 初期化データの保存確認 + ClothEditorManager.ApplyInitData(cloth, global: true); + ClothPainter.ExitPaint(); SceneView.RepaintAll(); } diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaClothEditor.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaClothEditor.cs.meta index 73329efd..5974e4bf 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaClothEditor.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaClothEditor.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaClothEditor.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs new file mode 100644 index 00000000..f8d7ece3 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs @@ -0,0 +1,40 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using UnityEditor; + +namespace MagicaCloth2 +{ + /// + /// インスペクター拡張のベースクラス + /// + public class MagicaEditorBase : Editor + { + /// + /// マルチ選択編集の適用 + /// + /// + /// + /// + protected void ApplyMultiSelection(bool changed, string undoName, Action act) where T : ClothBehaviour + { + if (changed) + { + foreach (var obj in targets) + { + var tscr = obj as T; + + // Undo + Undo.RecordObject(tscr, undoName); + + act(tscr); + EditorUtility.SetDirty(tscr); + + // OnValidate()手動呼び出し + tscr.GetType().GetMethod("OnValidate", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.Invoke(tscr, null); + } + } + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs.meta new file mode 100644 index 00000000..ebdb5e29 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 3126cd1eb42b4af4aa38cea3c3836c3e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaEditorBase.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaPlaneColliderEditor.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaPlaneColliderEditor.cs index a9e306ed..f801a448 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaPlaneColliderEditor.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaPlaneColliderEditor.cs @@ -9,7 +9,8 @@ namespace MagicaCloth2 /// PlaneColliderのインスペクター拡張 /// [CustomEditor(typeof(MagicaPlaneCollider))] - public class MagicaPlaneColliderEditor : Editor + [CanEditMultipleObjects] + public class MagicaPlaneColliderEditor : MagicaEditorBase { public override void OnInspectorGUI() { @@ -19,8 +20,14 @@ namespace MagicaCloth2 Undo.RecordObject(scr, "PlaneCollider"); // center - var centerValue = serializedObject.FindProperty("center"); - centerValue.vector3Value = EditorGUILayout.Vector3Field("Center", centerValue.vector3Value); + EditorGUILayout.PropertyField(serializedObject.FindProperty("center")); + + // Symmetry + EditorGUILayout.Space(); + var symmetryModeProperty = serializedObject.FindProperty("symmetryMode"); + EditorGUILayout.PropertyField(symmetryModeProperty); + if (symmetryModeProperty.enumValueIndex >= (int)ColliderSymmetryMode.AutomaticTarget) + EditorGUILayout.PropertyField(serializedObject.FindProperty("symmetryTarget")); serializedObject.ApplyModifiedProperties(); } diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaPlaneColliderEditor.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaPlaneColliderEditor.cs.meta index df1798cb..e030ff09 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaPlaneColliderEditor.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaPlaneColliderEditor.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaPlaneColliderEditor.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSettingsEditor.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSettingsEditor.cs index b95fd162..b6e7d4e5 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSettingsEditor.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSettingsEditor.cs @@ -7,7 +7,7 @@ namespace MagicaCloth2 { [CustomEditor(typeof(MagicaSettings))] [CanEditMultipleObjects] - public class MagicaSettingsEditor : Editor + public class MagicaSettingsEditor : MagicaEditorBase { //========================================================================================= /// @@ -28,7 +28,10 @@ namespace MagicaCloth2 EditorGUILayout.PropertyField(serializedObject.FindProperty("refreshMode")); EditorGUILayout.PropertyField(serializedObject.FindProperty("simulationFrequency")); EditorGUILayout.PropertyField(serializedObject.FindProperty("maxSimulationCountPerFrame")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("initializationLocation")); EditorGUILayout.PropertyField(serializedObject.FindProperty("updateLocation")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("monitorPlayerLoop")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("splitProxyMeshVertexCount")); } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSettingsEditor.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSettingsEditor.cs.meta index f5b47d09..d7e212bd 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSettingsEditor.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSettingsEditor.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSettingsEditor.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSphereColliderEditor.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSphereColliderEditor.cs index a1e205b0..f684c4a2 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSphereColliderEditor.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSphereColliderEditor.cs @@ -9,24 +9,40 @@ namespace MagicaCloth2 /// SphereColliderのインスペクター拡張 /// [CustomEditor(typeof(MagicaSphereCollider))] - public class MagicaSphereColliderEditor : Editor + [CanEditMultipleObjects] + public class MagicaSphereColliderEditor : MagicaEditorBase { public override void OnInspectorGUI() { var scr = target as MagicaSphereCollider; + const string undoName = "SphereCollider"; serializedObject.Update(); - Undo.RecordObject(scr, "SphereCollider"); + Undo.RecordObject(scr, undoName); - // radius - var sizeValue = serializedObject.FindProperty("size"); - var size = sizeValue.vector3Value; - size.x = EditorGUILayout.Slider("Radius", size.x, 0.001f, 0.5f); - sizeValue.vector3Value = size; + using (var check = new EditorGUI.ChangeCheckScope()) + { + + // radius + var sizeValue = serializedObject.FindProperty("size"); + + //EditorGUI.showMixedValue = sizeValue.hasMultipleDifferentValues; + var size = sizeValue.vector3Value; + float newSize = EditorGUILayout.Slider("Radius", size.x, 0.001f, 0.5f); + //EditorGUI.showMixedValue = false; + + ApplyMultiSelection(check.changed, undoName, x => x.SetSize(newSize)); + } // center - var centerValue = serializedObject.FindProperty("center"); - centerValue.vector3Value = EditorGUILayout.Vector3Field("Center", centerValue.vector3Value); + EditorGUILayout.PropertyField(serializedObject.FindProperty("center")); + + // Symmetry + EditorGUILayout.Space(); + var symmetryModeProperty = serializedObject.FindProperty("symmetryMode"); + EditorGUILayout.PropertyField(symmetryModeProperty); + if (symmetryModeProperty.enumValueIndex >= (int)ColliderSymmetryMode.AutomaticTarget) + EditorGUILayout.PropertyField(serializedObject.FindProperty("symmetryTarget")); serializedObject.ApplyModifiedProperties(); } diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSphereColliderEditor.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSphereColliderEditor.cs.meta index 22ee8fee..d5ecdecf 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSphereColliderEditor.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSphereColliderEditor.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaSphereColliderEditor.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaWindZoneEditor.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaWindZoneEditor.cs index 47c10ec5..d579eefd 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaWindZoneEditor.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaWindZoneEditor.cs @@ -8,7 +8,7 @@ namespace MagicaCloth2 { [CustomEditor(typeof(MagicaWindZone))] [CanEditMultipleObjects] - public class MagicaWindZoneEditor : Editor + public class MagicaWindZoneEditor : MagicaEditorBase { //========================================================================================= /// diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaWindZoneEditor.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaWindZoneEditor.cs.meta index 97d51c20..84bb6bbb 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaWindZoneEditor.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaWindZoneEditor.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/MagicaWindZoneEditor.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/VirtualMeshEditorUtility.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/VirtualMeshEditorUtility.cs index 1cefa6c2..e9c06c7e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/VirtualMeshEditorUtility.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/VirtualMeshEditorUtility.cs @@ -29,14 +29,15 @@ namespace MagicaCloth2 /// /// /// - public static void DrawGizmos(VirtualMesh vmesh, VirtualMeshDebugSettings debugSettings, bool selected, bool useHandles) + public static void DrawGizmos(VirtualMeshContainer cmesh, VirtualMeshDebugSettings debugSettings, bool selected, bool useHandles) { if (debugSettings.enable == false) return; - if (vmesh == null || vmesh.IsSuccess == false || vmesh.VertexCount == 0) + if (cmesh == null || cmesh.shareVirtualMesh == null || cmesh.shareVirtualMesh.IsSuccess == false || cmesh.shareVirtualMesh.VertexCount == 0) return; - var t = vmesh.GetCenterTransform(); + var vmesh = cmesh.shareVirtualMesh; + var t = cmesh.GetCenterTransform(); if (t == null) return; @@ -45,7 +46,7 @@ namespace MagicaCloth2 useHandles, true, selected, - vmesh, + cmesh, debugSettings, t, 0, @@ -54,7 +55,9 @@ namespace MagicaCloth2 dummyRotations, vmesh.localNormals.GetNativeArray(), vmesh.localTangents.GetNativeArray(), + 0, vmesh.boneWeights.GetNativeArray(), + vmesh.skinBoneTransformIndices.GetNativeArray(), vmesh.uv.GetNativeArray() ); } @@ -66,7 +69,7 @@ namespace MagicaCloth2 /// /// /// - public static void DrawRuntimeGizmos(ClothProcess cprocess, bool isMapping, VirtualMesh vmesh, VirtualMeshDebugSettings debugSettings, bool selected, bool useHandles) + public static void DrawRuntimeGizmos(ClothProcess cprocess, bool isMapping, VirtualMeshContainer cmesh, VirtualMeshDebugSettings debugSettings, bool selected, bool useHandles) { if (cprocess == null || cprocess.IsValid() == false) return; @@ -77,10 +80,10 @@ namespace MagicaCloth2 if (MagicaManager.Team.ContainsTeamData(cprocess.TeamId) == false) return; - if (vmesh == null || vmesh.IsSuccess == false) + if (cmesh == null || cmesh.shareVirtualMesh == null || cmesh.shareVirtualMesh.IsSuccess == false) return; - var t = vmesh.GetCenterTransform(); + var t = cmesh.GetCenterTransform(); if (t == null) return; @@ -91,10 +94,13 @@ namespace MagicaCloth2 var vm = MagicaManager.VMesh; // メッシュタイプにより参照するデータを切り替える + var vmesh = cmesh.shareVirtualMesh; var attributes = vmesh.IsMapping ? vm.mappingAttributes : vm.attributes; var positions = vmesh.IsMapping ? vm.mappingPositions : vm.positions; var rotations = vmesh.IsMapping ? null : vm.rotations; + int boneWeightOffset = vmesh.IsMapping ? 0 : tdata.proxySkinBoneChunk.startIndex + tdata.proxyTransformChunk.startIndex; var boneWeights = vmesh.IsMapping ? vm.mappingBoneWeights : vm.boneWeights; + var skinBoneTransformIndices = vmesh.IsMapping ? vm.skinBoneTransformIndices : vm.skinBoneTransformIndices; var uvs = vmesh.IsMapping ? null : vmesh.uv; int vstart = vmesh.IsMapping ? tm.mappingDataArray[vmesh.mappingId].mappingCommonChunk.startIndex : tdata.proxyCommonChunk.startIndex; @@ -105,7 +111,7 @@ namespace MagicaCloth2 useHandles, isMapping ? true : false, selected, - vmesh, + cmesh, debugSettings, t, vstart, @@ -114,7 +120,9 @@ namespace MagicaCloth2 rotations != null ? rotations.GetNativeArray() : dummyRotations, vmesh.localNormals.GetNativeArray(), vmesh.localTangents.GetNativeArray(), + boneWeightOffset, boneWeights.GetNativeArray(), + skinBoneTransformIndices.GetNativeArray(), uvs != null ? uvs.GetNativeArray() : dummyUvs ); } @@ -123,7 +131,7 @@ namespace MagicaCloth2 bool useHandles, bool isLocal, bool selected, - VirtualMesh vmesh, + VirtualMeshContainer cmesh, VirtualMeshDebugSettings debugSettings, Transform center, int vstart, @@ -132,7 +140,9 @@ namespace MagicaCloth2 NativeArray rotations, NativeArray normals, NativeArray tangents, + int boneWeightOffset, NativeArray boneWeights, + NativeArray skinBoneTransformIndices, NativeArray uvs ) { @@ -154,7 +164,8 @@ namespace MagicaCloth2 if (scam == null) return; quaternion camRot = scam.transform.rotation; - quaternion invCamRot = math.inverse(camRot); + //quaternion invCamRot = math.inverse(camRot); + var vmesh = cmesh.shareVirtualMesh; int vcnt = vmesh.VertexCount; // 表示スケール調整 @@ -241,6 +252,11 @@ namespace MagicaCloth2 continue; var pos = positions[vstart + i]; var bw = boneWeights[vstart + i]; + bw.boneIndices += boneWeightOffset; // グローバルインデックスに変換 + bw.boneIndices.x = skinBoneTransformIndices[bw.boneIndices.x]; + bw.boneIndices.y = skinBoneTransformIndices[bw.boneIndices.y]; + bw.boneIndices.z = skinBoneTransformIndices[bw.boneIndices.z]; + bw.boneIndices.w = skinBoneTransformIndices[bw.boneIndices.w]; Handles.Label(pos, $"[{bw.boneIndices.x},{bw.boneIndices.y},{bw.boneIndices.z},{bw.boneIndices.w}] w({bw.weights.x:0.###}, {bw.weights.y:0.###}, {bw.weights.z:0.###}, {bw.weights.w:0.###})"); } } @@ -503,10 +519,12 @@ namespace MagicaCloth2 // bone name if (debugSettings.boneName) { - int cnt = vmesh.transformData.Count; + //int cnt = vmesh.transformData.Count; + int cnt = cmesh.GetTransformCount(); for (int i = 0; i < cnt; i++) { - var t = vmesh.transformData.GetTransformFromIndex(i); + //var t = vmesh.transformData.GetTransformFromIndex(i); + var t = cmesh.GetTransformFromIndex(i); if (t) { var pos = t.position; diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/VirtualMeshEditorUtility.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/VirtualMeshEditorUtility.cs.meta index 9b32cfca..fe5de226 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/VirtualMeshEditorUtility.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Cloth/VirtualMeshEditorUtility.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Cloth/VirtualMeshEditorUtility.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/AboutMenu.cs b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/AboutMenu.cs index 3779e4ab..8de254ad 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/AboutMenu.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/AboutMenu.cs @@ -14,7 +14,7 @@ namespace MagicaCloth2 [SerializeField] private Texture2D image = null; - public const string MagicaClothVersion = "2.4.2"; + public const string MagicaClothVersion = "2.16.1"; public static AboutMenu AboutWindow { get; set; } private const float windowWidth = 300; diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/AboutMenu.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/AboutMenu.cs.meta index ad4ec39a..91a85c5e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/AboutMenu.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/AboutMenu.cs.meta @@ -11,3 +11,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/AboutMenu.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/CheckSliderSerializeDataDrawer.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/CheckSliderSerializeDataDrawer.cs.meta index 7d042ce2..23772dce 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/CheckSliderSerializeDataDrawer.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/CheckSliderSerializeDataDrawer.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/CheckSliderSerializeDataDrawer.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/CurveSerializeDataDrawer.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/CurveSerializeDataDrawer.cs.meta index 27848676..acf0f4ba 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/CurveSerializeDataDrawer.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/CurveSerializeDataDrawer.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/CurveSerializeDataDrawer.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/DrawIconInHierarchy.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/DrawIconInHierarchy.cs.meta index 28bab98b..9bb9d7da 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/DrawIconInHierarchy.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/DrawIconInHierarchy.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/DrawIconInHierarchy.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/MenuItemScript.cs b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/MenuItemScript.cs index cc3bd169..5f76f08e 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/MenuItemScript.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/MenuItemScript.cs @@ -96,16 +96,12 @@ namespace MagicaCloth2 //========================================================================================= [MenuItem("Tools/Magica Cloth2/Manager information", false)] - static void DispClothManagerInfo() + static async void DispClothManagerInfo() { - if (MagicaManager.IsPlaying() == false) - { - Debug.Log("This feature is run-time only."); - return; - } - StringBuilder allsb = new StringBuilder(); + await ClothEditorManager.InformationLog(allsb); + var timeManager = MagicaManager.Time; if (timeManager == null) { @@ -186,8 +182,15 @@ namespace MagicaCloth2 renderManager.InformationLog(allsb); } - // clipboard - //GUIUtility.systemCopyBuffer = allsb.ToString(); + var preBuildManager = MagicaManager.PreBuild; + if (preBuildManager == null) + { + Debug.LogWarning("PreBuild Manager is null!"); + } + else + { + preBuildManager.InformationLog(allsb); + } // file DateTime dt = DateTime.Now; @@ -197,5 +200,24 @@ namespace MagicaCloth2 sw.Flush(); sw.Close(); } + + //========================================================================================= + // インスペクターのコンテキストメニュー + [MenuItem("CONTEXT/MagicaCloth/Rebuild InitData")] + private static void SampleMenu(MenuCommand menuCommand) + { + // 初期化データをクリアして再構築する + var cloth = menuCommand.context as MagicaCloth; + if (cloth) + { + cloth.GetSerializeData2().initData.Clear(); + EditorUtility.SetDirty(cloth); + + // 編集用メッシュの再構築 + ClothEditorManager.RegisterComponent(cloth, GizmoType.Active, true); // 強制更新 + + Develop.Log($"[{cloth.name}] Initialization data rebuilt."); + } + } } } diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/MenuItemScript.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/MenuItemScript.cs.meta index fd86cc30..4c63803f 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/MenuItemScript.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/MenuItemScript.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/MenuItemScript.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs new file mode 100644 index 00000000..8812fcb0 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs @@ -0,0 +1,76 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using UnityEditor; +using UnityEngine; + +namespace MagicaCloth2 +{ + [CustomPropertyDrawer(typeof(SharePreBuildData))] + public class SharePreBuildDataDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + EditorGUI.BeginProperty(position, label, property); + + // サイズ + float lineHight = EditorGUIUtility.singleLineHeight; + + // 子のフィールドをインデントしない + var indent = EditorGUI.indentLevel; + EditorGUI.indentLevel = 0; + + var buildIdProperty = property.FindPropertyRelative("buildId"); + var versionProperty = property.FindPropertyRelative("version"); + var resultProperty = property.FindPropertyRelative("buildResult.result"); + + // テキスト幅調整 + EditorGUIUtility.labelWidth = position.width; + + // build Id + string buildId = string.IsNullOrEmpty(buildIdProperty.stringValue) ? "(Empty)" : buildIdProperty.stringValue; + EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), new GUIContent(buildId)); + position.y += lineHight; + + // インデント+1 + EditorGUI.indentLevel = indent + 1; + + // result + Define.Result ret = (Define.Result)resultProperty.enumValueIndex; + var result = new ResultCode(ret); + if (result.IsFaild() == false) + { + // バージョン確認 + if (versionProperty.intValue != Define.System.LatestPreBuildVersion) + result.SetError(Define.Result.PreBuildData_VersionMismatch); + } + + // result text + var backColor = GUI.color; + if (result.IsSuccess()) + { + GUI.color = Color.green; + EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), new GUIContent($"{result.Result}")); + } + else + { + GUI.color = Color.red; + EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), new GUIContent($"Error: {result.Result}")); + } + GUI.color = backColor; + + // インデントを元通りに戻します + EditorGUI.indentLevel = indent; + + EditorGUI.EndProperty(); + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + float h = EditorGUIUtility.singleLineHeight; + h *= 2; + + return h; + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs.meta new file mode 100644 index 00000000..691a7d15 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: c6706416db7bdd14cb7ed3f5195d6498 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/EditorExtension/SharePreBuildDataDrawer.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/GizmoUtility.cs b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/GizmoUtility.cs index afece445..b3170017 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/GizmoUtility.cs +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/GizmoUtility.cs @@ -1,6 +1,7 @@ // Magica Cloth 2. // Copyright (c) 2023 MagicaSoft. // https://magicasoft.jp +using Unity.Mathematics; using UnityEditor; using UnityEngine; @@ -10,6 +11,7 @@ namespace MagicaCloth2 { // ギズモカラー定義 public static readonly Color ColorCollider = new Color(0.0f, 1.0f, 0.0f); + public static readonly Color ColorSymmetryCollider = new Color(0.0f, 1.0f, 1.0f); public static readonly Color ColorNonSelectedCollider = new Color(0.5f, 0.3f, 0.0f); public static readonly Color ColorSkinningBone = new Color(1.0f, 0.5f, 0.0f); public static readonly Color ColorWindZone = new Color(1f, 1f, 1f); @@ -162,56 +164,142 @@ namespace MagicaCloth2 } //========================================================================================= - public static void DrawCollider(ColliderComponent collider, Quaternion camRot, bool useHandles, bool selected) + public static void DrawCollider(ColliderComponent collider, Quaternion camRot, bool selected) { if (collider == null) return; - var cpos = collider.transform.TransformPoint(collider.center); - var crot = collider.transform.rotation; - var cscl = Vector3.one * collider.GetScale(); // スケールはx軸のみ(つまり均等スケールのみ) + Handles.color = selected ? ColorCollider : ColorCollider * 0.5f; + // Main + var ct = collider.transform; + //var cpos = ct.TransformPoint(collider.center); + float3 cpos = ct.position; + quaternion crot = ct.rotation; + float3 cscl = ct.lossyScale; + // マイナススケール + float3 sclSign = math.sign(cscl); + // オフセット + cpos += math.mul(crot, collider.center * sclSign) * cscl * sclSign; // カメラ回転をコライダーのローカル回転に変換 - camRot = Quaternion.Inverse(crot) * camRot; + var camRotN = Quaternion.Inverse(crot) * camRot; + DrawColliderInternal(collider, camRotN, cpos, crot, cscl, 1.0f); - // サイズ - var size = collider.GetSize(); - - if (useHandles) + // Symmetry + // 実行時と同じ計算をして表示 + ColliderSymmetryMode? smode = ColliderSymmetryMode.None; + Transform symmetryParent = null; + if (EditorApplication.isPlaying) { - Handles.matrix = Matrix4x4.TRS(cpos, crot, cscl); - Handles.color = selected ? ColorCollider : ColorCollider * 0.5f; - switch (collider.GetColliderType()) - { - case ColliderManager.ColliderType.Sphere: - DrawWireSphere(Vector3.zero, Quaternion.identity, size.x, camRot, true); - break; - case ColliderManager.ColliderType.CapsuleX_Center: - DrawWireCapsule(Vector3.zero, Quaternion.identity, Vector3.right, Vector3.up, size.x, size.y, size.z, true, camRot, true); - break; - case ColliderManager.ColliderType.CapsuleY_Center: - DrawWireCapsule(Vector3.zero, Quaternion.identity, Vector3.up, Vector3.right, size.x, size.y, size.z, true, camRot, true); - break; - case ColliderManager.ColliderType.CapsuleZ_Center: - DrawWireCapsule(Vector3.zero, Quaternion.identity, Vector3.forward, Vector3.up, size.x, size.y, size.z, true, camRot, true); - break; - case ColliderManager.ColliderType.CapsuleX_Start: - DrawWireCapsule(Vector3.zero, Quaternion.identity, Vector3.right, Vector3.up, size.x, size.y, size.z, false, camRot, true); - break; - case ColliderManager.ColliderType.CapsuleY_Start: - DrawWireCapsule(Vector3.zero, Quaternion.identity, Vector3.up, Vector3.right, size.x, size.y, size.z, false, camRot, true); - break; - case ColliderManager.ColliderType.CapsuleZ_Start: - DrawWireCapsule(Vector3.zero, Quaternion.identity, Vector3.forward, Vector3.up, size.x, size.y, size.z, false, camRot, true); - break; - case ColliderManager.ColliderType.Plane: - DrawWireCube(Vector3.zero, Quaternion.identity, new Vector3(1.0f, 0.0f, 1.0f) * 1.0f, true); - break; - } + smode = collider.ActiveSymmetryMode; + symmetryParent = collider.ActiveSymmetryTarget; } - else + if (smode.HasValue == false || smode == ColliderSymmetryMode.None) + smode = collider.CalcSymmetryMode(out symmetryParent); + if (smode != ColliderSymmetryMode.None && symmetryParent) { + float3 lpos = ct.localPosition; + //float3 lerot = ct.localEulerAngles; + float3 lerot = MathUtility.ToEuler(ct.localRotation); + float3 lscl = ct.localScale; + float3 center = collider.center; + switch (smode) + { + case ColliderSymmetryMode.X_Symmetry: + lpos.x = -lpos.x; + center.x = -center.x; + lerot.y = -lerot.y; + lerot.z = -lerot.z; + break; + case ColliderSymmetryMode.Y_Symmetry: + lpos.y = -lpos.y; + center.y = -center.y; + lerot.x = -lerot.x; + lerot.z = -lerot.z; + break; + case ColliderSymmetryMode.Z_Symmetry: + lpos.z = -lpos.z; + center.z = -center.z; + lerot.x = -lerot.x; + lerot.y = -lerot.y; + break; + case ColliderSymmetryMode.XYZ_Symmetry: + lpos = -lpos; + center = -center; + break; + default: + return; + } + // 方向性 + float direction = 1.0f; + if (collider is MagicaCapsuleCollider) + { + var ccol = collider as MagicaCapsuleCollider; + if (smode == ColliderSymmetryMode.X_Symmetry && ccol.direction == MagicaCapsuleCollider.Direction.X) + direction = -1.0f; + else if (smode == ColliderSymmetryMode.Y_Symmetry && ccol.direction == MagicaCapsuleCollider.Direction.Y) + direction = -1.0f; + else if (smode == ColliderSymmetryMode.Z_Symmetry && ccol.direction == MagicaCapsuleCollider.Direction.Z) + direction = -1.0f; + else if (smode == ColliderSymmetryMode.XYZ_Symmetry) + direction = -1.0f; + } + else if (collider is MagicaPlaneCollider) + { + switch (smode) + { + case ColliderSymmetryMode.Y_Symmetry: + case ColliderSymmetryMode.XYZ_Symmetry: + direction = -1.0f; + break; + } + } + + // シンメトリーの親 + float3 ppos = symmetryParent.position; + quaternion prot = symmetryParent.rotation; + float3 pscl = symmetryParent.lossyScale; + + // マイナススケール + sclSign = math.sign(pscl); + float3 sclEulerSign = 1; + if (pscl.x < 0 || pscl.y < 0 || pscl.z < 0) + sclEulerSign = sclSign * -1; + + // シンメトリーコライダーの姿勢 + float3 wpos = MathUtility.TransformPoint(lpos, ppos, prot, pscl); + quaternion wrot = math.mul(prot, quaternion.Euler(math.radians(lerot * sclEulerSign))); + float3 wscl = pscl * lscl; + wpos += math.mul(wrot, center * sclSign) * wscl * sclSign; + + // カメラ回転をコライダーのローカル回転に変換 + var camRotS = Quaternion.Inverse(wrot) * camRot; + + Handles.color = selected ? ColorSymmetryCollider : ColorSymmetryCollider * 0.5f; + DrawColliderInternal(collider, camRotS, wpos, wrot, wscl, direction); + } + } + + static void DrawColliderInternal(ColliderComponent collider, Quaternion camRot, Vector3 cpos, Quaternion crot, Vector3 cscl, float direction) + { + var size = collider.GetSize(); + Handles.matrix = Matrix4x4.TRS(cpos, crot, cscl); + if (collider is MagicaSphereCollider) + { + DrawWireSphere(Vector3.zero, Quaternion.identity, size.x, camRot, true); + } + else if (collider is MagicaPlaneCollider) + { + DrawWireCube(Vector3.zero, Quaternion.identity, new Vector3(1.0f, 0.0f, 1.0f) * 1.0f, true); + DrawLine(Vector3.zero, Vector3.up * 0.25f * direction, true); + } + else if (collider is MagicaCapsuleCollider) + { + var c = collider as MagicaCapsuleCollider; + var ldir = c.GetLocalDir() * direction; + var lup = c.GetLocalUp(); + DrawWireCapsule(Vector3.zero, Quaternion.identity, ldir, lup, size.x, size.y, size.z, c.alignedOnCenter, camRot, true); } } @@ -300,23 +388,6 @@ namespace MagicaCloth2 Gizmos.matrix = Matrix4x4.identity; } - //public static void DrawWireSphere( - // Vector3 pos, Quaternion rot, Vector3 scl, float radius, - // Quaternion camRot, bool useHandles - // ) - //{ - // if(useHandles) - // { - // Handles.matrix = Matrix4x4.TRS(pos, rot, scl); - - // } - // else - // { - - // } - //} - - #if false /// /// ワイヤーボックスを描画する diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/GizmoUtility.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/GizmoUtility.cs.meta index 971ff0e8..aa6c3331 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/GizmoUtility.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/GizmoUtility.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/GizmoUtility.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaCapsuleColliderGizmoDrawer.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaCapsuleColliderGizmoDrawer.cs.meta index 5001161a..de6465bc 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaCapsuleColliderGizmoDrawer.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaCapsuleColliderGizmoDrawer.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaCapsuleColliderGizmoDrawer.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaClothGizmoDrawer.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaClothGizmoDrawer.cs.meta index 47e732ac..046ba4de 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaClothGizmoDrawer.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaClothGizmoDrawer.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaClothGizmoDrawer.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaPlaneColliderGizmoDrawer.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaPlaneColliderGizmoDrawer.cs.meta index f1706776..7f0c07b1 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaPlaneColliderGizmoDrawer.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaPlaneColliderGizmoDrawer.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaPlaneColliderGizmoDrawer.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaSphereColliderGizmoDrawer.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaSphereColliderGizmoDrawer.cs.meta index f83baf65..7bf496b2 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaSphereColliderGizmoDrawer.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaSphereColliderGizmoDrawer.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaSphereColliderGizmoDrawer.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaWindZoneGizmoDrawer.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaWindZoneGizmoDrawer.cs.meta index 2c5aa165..411b3373 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaWindZoneGizmoDrawer.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaWindZoneGizmoDrawer.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/Gizmos/MagicaWindZoneGizmoDrawer.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/MagicaCloth2.Editor.asmdef.meta b/Assets/External/MagicaCloth2/Scripts/Editor/MagicaCloth2.Editor.asmdef.meta index b1b61ec0..f06e346c 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/MagicaCloth2.Editor.asmdef.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/MagicaCloth2.Editor.asmdef.meta @@ -5,3 +5,10 @@ AssemblyDefinitionImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/MagicaCloth2.Editor.asmdef + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild.meta b/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild.meta new file mode 100644 index 00000000..bbbd80b8 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d09f86fb6833fb048935d02b3254e292 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs b/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs new file mode 100644 index 00000000..a645eaf0 --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs @@ -0,0 +1,514 @@ +// Magica Cloth 2. +// Copyright (c) 2024 MagicaSoft. +// https://magicasoft.jp +using System; +using System.Collections.Generic; +using Unity.Mathematics; +using UnityEditor; +using UnityEngine; + +namespace MagicaCloth2 +{ + /// + /// PreBuildDataの作成 + /// + public static class PreBuildDataCreation + { + /// + /// PreBuildDataを作成しアセットとして保存する. + /// Create PreBuildData and save it as an asset. + /// + /// + /// Show save dialog if ScriptableObject does not exist. + /// + public static ResultCode CreatePreBuildData(MagicaCloth cloth, bool useNewSaveDialog = true) + { + var sdata = cloth.SerializeData; + var preBuildData = cloth.GetSerializeData2().preBuildData; + string buildId = preBuildData.buildId; + + // ビルドIDが存在しない場合はここで新規作成する + if (string.IsNullOrEmpty(buildId)) + { + buildId = PreBuildSerializeData.GenerateBuildID(); + } + + // スクリプタブルオブジェクトへ保存 + if (preBuildData.preBuildScriptableObject == null && useNewSaveDialog) + { + string assetName = $"MagicaPreBuild_{buildId}"; + + // 保存フォルダ読み込み + const string StateKey = "MagicaCloth2_PreBuild_Folder"; + string path = SessionState.GetString(StateKey, "Assets/"); + + string assetPath = EditorUtility.SaveFilePanelInProject("Saving MagicaCloth pre-build data", assetName, "asset", "MagicaCloth pre-build data name", path); + //Debug.Log($"AssetPath:{assetPath}"); + if (string.IsNullOrEmpty(assetPath)) + return new ResultCode(Define.Result.Cancel); + + // 保存フォルダ書き込み + SessionState.SetString(StateKey, System.IO.Path.GetDirectoryName(assetPath)); + + var sobj = ScriptableObject.CreateInstance(); + AssetDatabase.CreateAsset(sobj, assetPath); + AssetDatabase.Refresh(); + + preBuildData.preBuildScriptableObject = sobj; + } + + var preBuildScriptableObject = preBuildData.preBuildScriptableObject; + if (preBuildScriptableObject == null) + return new ResultCode(Define.Result.PreBuild_InvalidPreBuildData); + + // 構築 + var sharePreBuildData = new SharePreBuildData(); + var uniquePreBuildData = new UniquePreBuildData(); + if (sdata.IsValid()) + { + MakePreBuildData(cloth, buildId, sharePreBuildData, uniquePreBuildData); + } + else + { + sharePreBuildData.buildResult.SetError(Define.Result.PreBuildData_InvalidClothData); + } + + // データシリアライズ + preBuildData.buildId = buildId; + preBuildScriptableObject.AddPreBuildData(sharePreBuildData); + preBuildData.uniquePreBuildData = uniquePreBuildData; + + EditorUtility.SetDirty(preBuildScriptableObject); + EditorUtility.SetDirty(cloth); + AssetDatabase.Refresh(); + + return sharePreBuildData.buildResult; + } + + static void MakePreBuildData(MagicaCloth cloth, string buildId, SharePreBuildData sharePreBuildData, UniquePreBuildData uniquePreBuildData) + { + //Debug.Log($"MakePreBuildData().start"); + //var span = new TimeSpan("PreBuild"); + + sharePreBuildData.version = Define.System.LatestPreBuildVersion; + sharePreBuildData.buildId = buildId; + sharePreBuildData.buildResult.SetProcess(); + uniquePreBuildData.version = Define.System.LatestPreBuildVersion; + uniquePreBuildData.buildResult.SetProcess(); + + var setupDataList = new List(); + VirtualMesh proxyMesh = null; + var renderMeshList = new List(); + + try + { + var sdata = cloth.SerializeData; + var sdata2 = cloth.GetSerializeData2(); + var clothType = sdata.clothType; + + //======================== Initialize ============================ + // クロスを生成するための最低限の情報が揃っているかチェックする + if (sdata.IsValid() == false) + { + sharePreBuildData.buildResult.SetResult(sdata.VerificationResult); + throw new MagicaClothProcessingException(); + } + + // 初期トランスフォーム状態 + var clothTransformRecord = new TransformRecord(cloth.ClothTransform, read: true); + + // 法線調整用トランスフォーム + var normalAdjustmentTransformRecord = new TransformRecord( + sdata.normalAlignmentSetting.adjustmentTransform ? + sdata.normalAlignmentSetting.adjustmentTransform : + cloth.ClothTransform, read: true); + + // セットアップ情報の初期化 + if (clothType == ClothProcess.ClothType.MeshCloth) + { + foreach (var ren in sdata.sourceRenderers) + { + if (ren) + { + var setupData = new RenderSetupData(null, ren); + if (setupData.IsFaild()) + { + sharePreBuildData.buildResult.Merge(setupData.result); + throw new MagicaClothProcessingException(); + } + setupDataList.Add(setupData); + + // セットアップ情報のシリアライズ + sharePreBuildData.renderSetupDataList.Add(setupData.ShareSerialize()); + uniquePreBuildData.renderSetupDataList.Add(setupData.UniqueSerialize()); + } + } + } + else if (clothType == ClothProcess.ClothType.BoneCloth || clothType == ClothProcess.ClothType.BoneSpring) + { + var setupData = new RenderSetupData( + null, + clothType == ClothProcess.ClothType.BoneCloth ? RenderSetupData.SetupType.BoneCloth : RenderSetupData.SetupType.BoneSpring, + clothTransformRecord.transform, + sdata.rootBones, + clothType == ClothProcess.ClothType.BoneCloth ? null : sdata.colliderCollisionConstraint.collisionBones, + clothType == ClothProcess.ClothType.BoneCloth ? sdata.connectionMode : RenderSetupData.BoneConnectionMode.Line, + cloth.name + ); + if (setupData.IsFaild()) + { + sharePreBuildData.buildResult.Merge(setupData.result); + throw new MagicaClothProcessingException(); + } + setupDataList.Add(setupData); + } + + // カスタムスキニングのボーン情報 + List customSkinningBoneRecords = new List(); + int bcnt = sdata.customSkinningSetting.skinningBones.Count; + for (int i = 0; i < bcnt; i++) + { + customSkinningBoneRecords.Add(new TransformRecord(sdata.customSkinningSetting.skinningBones[i], read: true)); + } + + //======================== Proxy/Mapping Mesh ============================ + // ペイントマップ情報 + bool usePaintMap = false; + var paintMapDataList = new List(); + if (clothType == ClothProcess.ClothType.MeshCloth && sdata.paintMode != ClothSerializeData.PaintMode.Manual) + { + var ret = cloth.Process.GeneratePaintMapDataList(paintMapDataList); + Develop.DebugLog($"Generate paint map data list. {ret.GetResultString()}"); + if (ret.IsError()) + { + sharePreBuildData.buildResult.Merge(ret); + throw new MagicaClothProcessingException(); + } + //if (paintMapDataList.Count != renderHandleList.Count) + if (paintMapDataList.Count != setupDataList.Count) + { + sharePreBuildData.buildResult.SetError(Define.Result.CreateCloth_PaintMapCountMismatch); + throw new MagicaClothProcessingException(); + } + usePaintMap = true; + } + + // セレクションデータ + SelectionData selectionData = usePaintMap ? new SelectionData() : sdata2.selectionData.Clone(); + bool isValidSelection = selectionData?.IsValid() ?? false; + + // プロキシメッシュ作成 + proxyMesh = new VirtualMesh("Proxy"); + proxyMesh.result.SetProcess(); + if (clothType == ClothProcess.ClothType.MeshCloth) + { + + // MeshClothではクロストランスフォームを追加しておく + proxyMesh.SetTransform(clothTransformRecord); + + if (setupDataList.Count == 0) + { + sharePreBuildData.buildResult.SetError(Define.Result.ClothProcess_InvalidRenderHandleList); + throw new MagicaClothProcessingException(); + } + + // render mesh import + selection + merge + for (int i = 0; i < setupDataList.Count; i++) + { + VirtualMesh renderMesh = null; + try + { + // レンダーメッシュ作成 + var renderSetupData = setupDataList[i]; + renderMesh = new VirtualMesh($"[{renderSetupData.name}]"); + renderMesh.result.SetProcess(); + + // import ------------------------------------------------- + renderMesh.ImportFrom(renderSetupData, sdata.GetUvChannel()); + if (renderMesh.IsError) + { + sharePreBuildData.buildResult.Merge(renderMesh.result); + throw new MagicaClothProcessingException(); + } + Develop.DebugLog($"(IMPORT) {renderMesh}"); + + // selection ---------------------------------------------- + // MeshClothでペイントテクスチャ指定の場合はセレクションデータを生成する + SelectionData renderSelectionData = selectionData; + if (usePaintMap) + { + // セレクションデータ生成 + var ret = cloth.Process.GenerateSelectionDataFromPaintMap(clothTransformRecord, renderMesh, paintMapDataList[i], out renderSelectionData); + Develop.DebugLog($"Generate selection from paint map. {ret.GetResultString()}"); + if (ret.IsError()) + { + sharePreBuildData.buildResult.Merge(ret); + throw new MagicaClothProcessingException(); + } + + // セレクションデータ結合 + selectionData.Merge(renderSelectionData); + } + isValidSelection = selectionData?.IsValid() ?? false; + + // メッシュの切り取り + if (renderSelectionData?.IsValid() ?? false) + { + // 余白 + float mergin = renderMesh.CalcSelectionMergin(sdata.reductionSetting); + mergin = math.max(mergin, Define.System.MinimumGridSize); + + // セレクション情報から切り取りの実行 + // ペイントマップの場合はレンダラーごとのセレクションデータで切り取り + renderMesh.SelectionMesh(renderSelectionData, clothTransformRecord.localToWorldMatrix, mergin); + if (renderMesh.IsError) + { + sharePreBuildData.buildResult.Merge(renderMesh.result); + throw new MagicaClothProcessingException(); + } + Develop.DebugLog($"(SELECTION) {renderMesh}"); + } + + // レンダーメッシュの作成完了 + renderMesh.result.SetSuccess(); + + // merge -------------------------------------------------- + proxyMesh.AddMesh(renderMesh); + + // レンダーメッシュ情報を記録 + renderMeshList.Add(renderMesh); + renderMesh = null; + } + catch (MagicaClothProcessingException) + { + throw; + } + catch (Exception exception) + { + Debug.LogException(exception); + sharePreBuildData.buildResult.SetError(Define.Result.ClothProcess_Exception); + throw; + } + finally + { + // この時点で作業用renderMeshが存在する場合は中断されているので開放する + renderMesh?.Dispose(); + } + } + Develop.DebugLog($"(MERGE) {proxyMesh}"); + + // リダクション + if (proxyMesh.VertexCount > 1) + { + if (sdata.reductionSetting.IsEnabled) + { + proxyMesh.Reduction(sdata.reductionSetting, System.Threading.CancellationToken.None); + if (proxyMesh.IsError) + { + sharePreBuildData.buildResult.Merge(proxyMesh.result); + throw new MagicaClothProcessingException(); + } + + Develop.DebugLog($"(REDUCTION) {proxyMesh}"); + } + } + } + else if (clothType == ClothProcess.ClothType.BoneCloth || clothType == ClothProcess.ClothType.BoneSpring) + { + // import + var boneClothSetupData = setupDataList[0]; + proxyMesh.ImportFrom(boneClothSetupData, 0); + if (proxyMesh.IsError) + { + sharePreBuildData.buildResult.Merge(proxyMesh.result); + throw new MagicaClothProcessingException(); + } + Develop.DebugLog($"(IMPORT) {proxyMesh}"); + + // セレクションデータが存在しない場合は簡易作成する + if (isValidSelection == false) + { + selectionData = new SelectionData(proxyMesh, float4x4.identity); + if (selectionData.Count > 0) + { + // まずすべて移動設定 + selectionData.Fill(VertexAttribute.Move); + + // 次にルートのみ固定 + foreach (int id in boneClothSetupData.rootTransformIdList) + { + int rootIndex = boneClothSetupData.GetTransformIndexFromId(id); + selectionData.attributes[rootIndex] = VertexAttribute.Fixed; + } + isValidSelection = selectionData.IsValid(); + } + } + } + + // 元の頂点から結合頂点へのインデックスを初期化 + if (proxyMesh.joinIndices.IsCreated == false) + { + proxyMesh.joinIndices = new Unity.Collections.NativeArray(proxyMesh.VertexCount, Unity.Collections.Allocator.Persistent); + JobUtility.SerialNumberRun(proxyMesh.joinIndices, proxyMesh.VertexCount); // 連番をつける + } + + // optimization + proxyMesh.Optimization(); + if (proxyMesh.IsError) + { + sharePreBuildData.buildResult.Merge(proxyMesh.result); + throw new MagicaClothProcessingException(); + } + Develop.DebugLog($"(OPTIMIZE) {proxyMesh}"); + + // attribute + if (isValidSelection) + { + // セレクションデータから頂点属性を付与する + proxyMesh.ApplySelectionAttribute(selectionData); + if (proxyMesh.IsError) + { + sharePreBuildData.buildResult.Merge(proxyMesh.result); + throw new MagicaClothProcessingException(); + } + } + + // proxy mesh(属性決定後に実行) + proxyMesh.ConvertProxyMesh(sdata, clothTransformRecord, customSkinningBoneRecords, normalAdjustmentTransformRecord); + if (proxyMesh.IsError) + { + sharePreBuildData.buildResult.Merge(proxyMesh.result); + throw new MagicaClothProcessingException(); + } + Develop.DebugLog($"(PROXY) {proxyMesh}"); + + // ProxyMeshの最終チェック + if (proxyMesh.VertexCount > Define.System.MaxProxyMeshVertexCount) + { + sharePreBuildData.buildResult.SetError(Define.Result.ProxyMesh_Over32767Vertices); + throw new MagicaClothProcessingException(); + } + if (proxyMesh.EdgeCount > Define.System.MaxProxyMeshEdgeCount) + { + sharePreBuildData.buildResult.SetError(Define.Result.ProxyMesh_Over32767Edges); + throw new MagicaClothProcessingException(); + } + if (proxyMesh.TriangleCount > Define.System.MaxProxyMeshTriangleCount) + { + sharePreBuildData.buildResult.SetError(Define.Result.ProxyMesh_Over32767Triangles); + throw new MagicaClothProcessingException(); + } + + // finish + if (proxyMesh.IsError) + { + sharePreBuildData.buildResult.Merge(proxyMesh.result); + throw new MagicaClothProcessingException(); + } + proxyMesh.result.SetSuccess(); + Develop.DebugLog("CreateProxyMesh finish!"); + + // Mapping(MeshClothのみ) + if (clothType == ClothProcess.ClothType.MeshCloth) + { + foreach (VirtualMesh renderMesh in renderMeshList) + { + renderMesh.Mapping(proxyMesh); + if (renderMesh.IsError) + { + sharePreBuildData.buildResult.Merge(renderMesh.result); + throw new MagicaClothProcessingException(); + } + Develop.DebugLog($"(MAPPING) {renderMesh}"); + } + } + + // ======================= Cloth Data =============================== + // クロスデータ作成 + var parameters = cloth.SerializeData.GetClothParameters(); + var distanceConstraintData = DistanceConstraint.CreateData(proxyMesh, parameters); + if (distanceConstraintData != null) + { + if (distanceConstraintData.result.IsSuccess()) + { + sharePreBuildData.distanceConstraintData = distanceConstraintData; + } + else + { + sharePreBuildData.buildResult.Merge(distanceConstraintData.result); + throw new MagicaClothProcessingException(); + } + } + var bendingConstraintData = TriangleBendingConstraint.CreateData(proxyMesh, parameters); + if (bendingConstraintData != null) + { + if (bendingConstraintData.result.IsSuccess()) + { + sharePreBuildData.bendingConstraintData = bendingConstraintData; + } + else + { + sharePreBuildData.buildResult.Merge(bendingConstraintData.result); + throw new MagicaClothProcessingException(); + } + } + var inertiaConstraintData = InertiaConstraint.CreateData(proxyMesh, parameters); + if (inertiaConstraintData != null) + { + if (inertiaConstraintData.result.IsSuccess()) + { + sharePreBuildData.inertiaConstraintData = inertiaConstraintData; + } + else + { + sharePreBuildData.buildResult.Merge(inertiaConstraintData.result); + throw new MagicaClothProcessingException(); + } + } + + // ======================= Serialize =============================== + sharePreBuildData.buildScale = clothTransformRecord.scale; + sharePreBuildData.proxyMesh = proxyMesh.ShareSerialize(); + uniquePreBuildData.proxyMesh = proxyMesh.UniqueSerialize(); + foreach (VirtualMesh renderMesh in renderMeshList) + { + sharePreBuildData.renderMeshList.Add(renderMesh.ShareSerialize()); + uniquePreBuildData.renderMeshList.Add(renderMesh.UniqueSerialize()); + } + + // 成功 + sharePreBuildData.buildResult.SetSuccess(); + + Develop.DebugLog(sharePreBuildData); + } + catch (MagicaClothProcessingException) + { + if (sharePreBuildData.buildResult.IsError() == false) + sharePreBuildData.buildResult.SetError(Define.Result.PreBuildData_MagicaClothException); + sharePreBuildData.buildResult.DebugLog(); + } + catch (Exception exception) + { + Debug.LogException(exception); + sharePreBuildData.buildResult.SetError(Define.Result.PreBuildData_UnknownError); + } + finally + { + setupDataList.ForEach(x => x.Dispose()); + setupDataList.Clear(); + + renderMeshList.ForEach(x => x?.Dispose()); + renderMeshList.Clear(); + + proxyMesh?.Dispose(); + proxyMesh = null; + + // 内部情報は外部情報の結果をコピー + uniquePreBuildData.buildResult = sharePreBuildData.buildResult; + } + + //Debug.Log(span); + //Debug.Log($"MakePreBuildData().end"); + } + } +} diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs.meta new file mode 100644 index 00000000..a03a8dbb --- /dev/null +++ b/Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d37ab6d9c5e31034a9503a7cedd96ee3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/PreBuild/PreBuildDataCreation.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Burst/MagicaCloth2UPMImporterBurst.asmdef.meta b/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Burst/MagicaCloth2UPMImporterBurst.asmdef.meta index 9db694ef..903126e0 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Burst/MagicaCloth2UPMImporterBurst.asmdef.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Burst/MagicaCloth2UPMImporterBurst.asmdef.meta @@ -5,3 +5,10 @@ AssemblyDefinitionImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Burst/MagicaCloth2UPMImporterBurst.asmdef + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Burst/UnityPackageImporter.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Burst/UnityPackageImporter.cs.meta index 557f2b47..165e7125 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Burst/UnityPackageImporter.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Burst/UnityPackageImporter.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Burst/UnityPackageImporter.cs + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Collections/MagicaCloth2UPMImporterCollections.asmdef.meta b/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Collections/MagicaCloth2UPMImporterCollections.asmdef.meta index b046c5b3..acc24da9 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Collections/MagicaCloth2UPMImporterCollections.asmdef.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Collections/MagicaCloth2UPMImporterCollections.asmdef.meta @@ -5,3 +5,10 @@ AssemblyDefinitionImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Collections/MagicaCloth2UPMImporterCollections.asmdef + uploadId: 756593 diff --git a/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Collections/UnityPackageImporter.cs.meta b/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Collections/UnityPackageImporter.cs.meta index 54f51dfe..8d7ebc3b 100644 --- a/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Collections/UnityPackageImporter.cs.meta +++ b/Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Collections/UnityPackageImporter.cs.meta @@ -9,3 +9,10 @@ MonoImporter: userData: assetBundleName: assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 242307 + packageName: Magica Cloth 2 + packageVersion: 2.16.1 + assetPath: Assets/External/MagicaCloth2/Scripts/Editor/UnityPackageImporter/Collections/UnityPackageImporter.cs + uploadId: 756593