@bloomengine/engine 0.3.3 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (494) hide show
  1. package/native/shared/build.rs +137 -6
  2. package/package.json +4 -11
  3. package/native/third_party/JoltPhysics/Build/Android/PerformanceTest/build.gradle +0 -51
  4. package/native/third_party/JoltPhysics/Build/Android/PerformanceTest/src/main/AndroidManifest.xml +0 -20
  5. package/native/third_party/JoltPhysics/Build/Android/PerformanceTest/src/main/cpp/CMakeLists.txt +0 -20
  6. package/native/third_party/JoltPhysics/Build/Android/UnitTests/build.gradle +0 -51
  7. package/native/third_party/JoltPhysics/Build/Android/UnitTests/src/main/AndroidManifest.xml +0 -20
  8. package/native/third_party/JoltPhysics/Build/Android/UnitTests/src/main/cpp/CMakeLists.txt +0 -20
  9. package/native/third_party/JoltPhysics/Build/Android/build.gradle +0 -17
  10. package/native/third_party/JoltPhysics/Build/Android/gradle/wrapper/gradle-wrapper.jar +0 -0
  11. package/native/third_party/JoltPhysics/Build/Android/gradle/wrapper/gradle-wrapper.properties +0 -5
  12. package/native/third_party/JoltPhysics/Build/Android/gradle.properties +0 -21
  13. package/native/third_party/JoltPhysics/Build/Android/gradlew +0 -185
  14. package/native/third_party/JoltPhysics/Build/Android/gradlew.bat +0 -89
  15. package/native/third_party/JoltPhysics/Build/Android/settings.gradle +0 -10
  16. package/native/third_party/JoltPhysics/Build/CMakeLists.txt +0 -449
  17. package/native/third_party/JoltPhysics/Build/README.md +0 -250
  18. package/native/third_party/JoltPhysics/Build/cmake_linux_clang_gcc.sh +0 -28
  19. package/native/third_party/JoltPhysics/Build/cmake_linux_emscripten.sh +0 -19
  20. package/native/third_party/JoltPhysics/Build/cmake_linux_mingw.sh +0 -19
  21. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl.bat +0 -3
  22. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl_32bit.bat +0 -3
  23. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl_arm.bat +0 -3
  24. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl_arm_32bit.bat +0 -4
  25. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl_cross_platform_deterministic.bat +0 -3
  26. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl_double.bat +0 -3
  27. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl_no_object_stream.bat +0 -3
  28. package/native/third_party/JoltPhysics/Build/cmake_vs2022_clang.bat +0 -10
  29. package/native/third_party/JoltPhysics/Build/cmake_vs2022_clang_cross_platform_deterministic.bat +0 -10
  30. package/native/third_party/JoltPhysics/Build/cmake_vs2022_clang_double.bat +0 -10
  31. package/native/third_party/JoltPhysics/Build/cmake_vs2022_uwp.bat +0 -5
  32. package/native/third_party/JoltPhysics/Build/cmake_vs2022_uwp_arm.bat +0 -5
  33. package/native/third_party/JoltPhysics/Build/cmake_vs2026_cl.bat +0 -3
  34. package/native/third_party/JoltPhysics/Build/cmake_vs2026_cl_cross_platform_deterministic.bat +0 -3
  35. package/native/third_party/JoltPhysics/Build/cmake_vs2026_cl_double.bat +0 -3
  36. package/native/third_party/JoltPhysics/Build/cmake_vs2026_clang.bat +0 -10
  37. package/native/third_party/JoltPhysics/Build/cmake_vs2026_clang_cross_platform_deterministic.bat +0 -10
  38. package/native/third_party/JoltPhysics/Build/cmake_vs2026_clang_double.bat +0 -10
  39. package/native/third_party/JoltPhysics/Build/cmake_windows_mingw.sh +0 -19
  40. package/native/third_party/JoltPhysics/Build/cmake_xcode_ios.sh +0 -4
  41. package/native/third_party/JoltPhysics/Build/cmake_xcode_macos.sh +0 -4
  42. package/native/third_party/JoltPhysics/Build/iOS/JoltViewerInfo.plist +0 -34
  43. package/native/third_party/JoltPhysics/Build/iOS/SamplesInfo.plist +0 -34
  44. package/native/third_party/JoltPhysics/Build/iOS/UnitTestsInfo.plist +0 -34
  45. package/native/third_party/JoltPhysics/Build/macOS/icon.icns +0 -0
  46. package/native/third_party/JoltPhysics/Build/macos_install_vulkan_sdk.sh +0 -13
  47. package/native/third_party/JoltPhysics/Build/ubuntu24_install_vulkan_sdk.sh +0 -4
  48. package/native/third_party/JoltPhysics/Jolt/AABBTree/AABBTreeBuilder.cpp +0 -242
  49. package/native/third_party/JoltPhysics/Jolt/AABBTree/AABBTreeBuilder.h +0 -121
  50. package/native/third_party/JoltPhysics/Jolt/AABBTree/AABBTreeToBuffer.h +0 -296
  51. package/native/third_party/JoltPhysics/Jolt/AABBTree/NodeCodec/NodeCodecQuadTreeHalfFloat.h +0 -323
  52. package/native/third_party/JoltPhysics/Jolt/AABBTree/TriangleCodec/TriangleCodecIndexed8BitPackSOA4Flags.h +0 -555
  53. package/native/third_party/JoltPhysics/Jolt/ConfigurationString.h +0 -112
  54. package/native/third_party/JoltPhysics/Jolt/Core/ARMNeon.h +0 -94
  55. package/native/third_party/JoltPhysics/Jolt/Core/Array.h +0 -713
  56. package/native/third_party/JoltPhysics/Jolt/Core/Atomics.h +0 -44
  57. package/native/third_party/JoltPhysics/Jolt/Core/BinaryHeap.h +0 -96
  58. package/native/third_party/JoltPhysics/Jolt/Core/ByteBuffer.h +0 -74
  59. package/native/third_party/JoltPhysics/Jolt/Core/Color.cpp +0 -38
  60. package/native/third_party/JoltPhysics/Jolt/Core/Color.h +0 -98
  61. package/native/third_party/JoltPhysics/Jolt/Core/Core.h +0 -652
  62. package/native/third_party/JoltPhysics/Jolt/Core/FPControlWord.h +0 -143
  63. package/native/third_party/JoltPhysics/Jolt/Core/FPException.h +0 -96
  64. package/native/third_party/JoltPhysics/Jolt/Core/FPFlushDenormals.h +0 -43
  65. package/native/third_party/JoltPhysics/Jolt/Core/Factory.cpp +0 -92
  66. package/native/third_party/JoltPhysics/Jolt/Core/Factory.h +0 -54
  67. package/native/third_party/JoltPhysics/Jolt/Core/FixedSizeFreeList.h +0 -122
  68. package/native/third_party/JoltPhysics/Jolt/Core/FixedSizeFreeList.inl +0 -215
  69. package/native/third_party/JoltPhysics/Jolt/Core/HashCombine.h +0 -234
  70. package/native/third_party/JoltPhysics/Jolt/Core/HashTable.h +0 -876
  71. package/native/third_party/JoltPhysics/Jolt/Core/InsertionSort.h +0 -58
  72. package/native/third_party/JoltPhysics/Jolt/Core/IssueReporting.cpp +0 -27
  73. package/native/third_party/JoltPhysics/Jolt/Core/IssueReporting.h +0 -38
  74. package/native/third_party/JoltPhysics/Jolt/Core/JobSystem.h +0 -311
  75. package/native/third_party/JoltPhysics/Jolt/Core/JobSystem.inl +0 -56
  76. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemSingleThreaded.cpp +0 -65
  77. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemSingleThreaded.h +0 -62
  78. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemThreadPool.cpp +0 -364
  79. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemThreadPool.h +0 -101
  80. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemWithBarrier.cpp +0 -230
  81. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemWithBarrier.h +0 -85
  82. package/native/third_party/JoltPhysics/Jolt/Core/LinearCurve.cpp +0 -51
  83. package/native/third_party/JoltPhysics/Jolt/Core/LinearCurve.h +0 -67
  84. package/native/third_party/JoltPhysics/Jolt/Core/LockFreeHashMap.h +0 -182
  85. package/native/third_party/JoltPhysics/Jolt/Core/LockFreeHashMap.inl +0 -351
  86. package/native/third_party/JoltPhysics/Jolt/Core/Memory.cpp +0 -85
  87. package/native/third_party/JoltPhysics/Jolt/Core/Memory.h +0 -85
  88. package/native/third_party/JoltPhysics/Jolt/Core/Mutex.h +0 -223
  89. package/native/third_party/JoltPhysics/Jolt/Core/MutexArray.h +0 -98
  90. package/native/third_party/JoltPhysics/Jolt/Core/NonCopyable.h +0 -18
  91. package/native/third_party/JoltPhysics/Jolt/Core/Profiler.cpp +0 -677
  92. package/native/third_party/JoltPhysics/Jolt/Core/Profiler.h +0 -301
  93. package/native/third_party/JoltPhysics/Jolt/Core/Profiler.inl +0 -90
  94. package/native/third_party/JoltPhysics/Jolt/Core/QuickSort.h +0 -137
  95. package/native/third_party/JoltPhysics/Jolt/Core/RTTI.cpp +0 -149
  96. package/native/third_party/JoltPhysics/Jolt/Core/RTTI.h +0 -436
  97. package/native/third_party/JoltPhysics/Jolt/Core/Reference.h +0 -244
  98. package/native/third_party/JoltPhysics/Jolt/Core/Result.h +0 -174
  99. package/native/third_party/JoltPhysics/Jolt/Core/STLAlignedAllocator.h +0 -72
  100. package/native/third_party/JoltPhysics/Jolt/Core/STLAllocator.h +0 -127
  101. package/native/third_party/JoltPhysics/Jolt/Core/STLLocalAllocator.h +0 -170
  102. package/native/third_party/JoltPhysics/Jolt/Core/STLTempAllocator.h +0 -80
  103. package/native/third_party/JoltPhysics/Jolt/Core/ScopeExit.h +0 -49
  104. package/native/third_party/JoltPhysics/Jolt/Core/Semaphore.cpp +0 -135
  105. package/native/third_party/JoltPhysics/Jolt/Core/Semaphore.h +0 -68
  106. package/native/third_party/JoltPhysics/Jolt/Core/StaticArray.h +0 -329
  107. package/native/third_party/JoltPhysics/Jolt/Core/StreamIn.h +0 -120
  108. package/native/third_party/JoltPhysics/Jolt/Core/StreamOut.h +0 -97
  109. package/native/third_party/JoltPhysics/Jolt/Core/StreamUtils.h +0 -168
  110. package/native/third_party/JoltPhysics/Jolt/Core/StreamWrapper.h +0 -53
  111. package/native/third_party/JoltPhysics/Jolt/Core/StridedPtr.h +0 -63
  112. package/native/third_party/JoltPhysics/Jolt/Core/StringTools.cpp +0 -101
  113. package/native/third_party/JoltPhysics/Jolt/Core/StringTools.h +0 -38
  114. package/native/third_party/JoltPhysics/Jolt/Core/TempAllocator.h +0 -209
  115. package/native/third_party/JoltPhysics/Jolt/Core/TickCounter.cpp +0 -37
  116. package/native/third_party/JoltPhysics/Jolt/Core/TickCounter.h +0 -58
  117. package/native/third_party/JoltPhysics/Jolt/Core/UnorderedMap.h +0 -80
  118. package/native/third_party/JoltPhysics/Jolt/Core/UnorderedSet.h +0 -32
  119. package/native/third_party/JoltPhysics/Jolt/Geometry/AABox.h +0 -313
  120. package/native/third_party/JoltPhysics/Jolt/Geometry/AABox4.h +0 -224
  121. package/native/third_party/JoltPhysics/Jolt/Geometry/ClipPoly.h +0 -200
  122. package/native/third_party/JoltPhysics/Jolt/Geometry/ClosestPoint.h +0 -498
  123. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder.cpp +0 -1467
  124. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder.h +0 -276
  125. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder2D.cpp +0 -335
  126. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder2D.h +0 -105
  127. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexSupport.h +0 -188
  128. package/native/third_party/JoltPhysics/Jolt/Geometry/EPAConvexHullBuilder.h +0 -845
  129. package/native/third_party/JoltPhysics/Jolt/Geometry/EPAPenetrationDepth.h +0 -557
  130. package/native/third_party/JoltPhysics/Jolt/Geometry/Ellipse.h +0 -77
  131. package/native/third_party/JoltPhysics/Jolt/Geometry/GJKClosestPoint.h +0 -945
  132. package/native/third_party/JoltPhysics/Jolt/Geometry/IndexedTriangle.h +0 -130
  133. package/native/third_party/JoltPhysics/Jolt/Geometry/Indexify.cpp +0 -222
  134. package/native/third_party/JoltPhysics/Jolt/Geometry/Indexify.h +0 -19
  135. package/native/third_party/JoltPhysics/Jolt/Geometry/MortonCode.h +0 -40
  136. package/native/third_party/JoltPhysics/Jolt/Geometry/OrientedBox.cpp +0 -178
  137. package/native/third_party/JoltPhysics/Jolt/Geometry/OrientedBox.h +0 -39
  138. package/native/third_party/JoltPhysics/Jolt/Geometry/Plane.h +0 -104
  139. package/native/third_party/JoltPhysics/Jolt/Geometry/RayAABox.h +0 -241
  140. package/native/third_party/JoltPhysics/Jolt/Geometry/RayCapsule.h +0 -37
  141. package/native/third_party/JoltPhysics/Jolt/Geometry/RayCylinder.h +0 -101
  142. package/native/third_party/JoltPhysics/Jolt/Geometry/RaySphere.h +0 -96
  143. package/native/third_party/JoltPhysics/Jolt/Geometry/RayTriangle.h +0 -158
  144. package/native/third_party/JoltPhysics/Jolt/Geometry/Sphere.h +0 -72
  145. package/native/third_party/JoltPhysics/Jolt/Geometry/Triangle.h +0 -34
  146. package/native/third_party/JoltPhysics/Jolt/Jolt.cmake +0 -703
  147. package/native/third_party/JoltPhysics/Jolt/Jolt.h +0 -16
  148. package/native/third_party/JoltPhysics/Jolt/Jolt.natvis +0 -116
  149. package/native/third_party/JoltPhysics/Jolt/Math/BVec16.h +0 -99
  150. package/native/third_party/JoltPhysics/Jolt/Math/BVec16.inl +0 -177
  151. package/native/third_party/JoltPhysics/Jolt/Math/DMat44.h +0 -158
  152. package/native/third_party/JoltPhysics/Jolt/Math/DMat44.inl +0 -310
  153. package/native/third_party/JoltPhysics/Jolt/Math/DVec3.h +0 -291
  154. package/native/third_party/JoltPhysics/Jolt/Math/DVec3.inl +0 -941
  155. package/native/third_party/JoltPhysics/Jolt/Math/Double3.h +0 -48
  156. package/native/third_party/JoltPhysics/Jolt/Math/DynMatrix.h +0 -31
  157. package/native/third_party/JoltPhysics/Jolt/Math/EigenValueSymmetric.h +0 -177
  158. package/native/third_party/JoltPhysics/Jolt/Math/FindRoot.h +0 -42
  159. package/native/third_party/JoltPhysics/Jolt/Math/Float2.h +0 -36
  160. package/native/third_party/JoltPhysics/Jolt/Math/Float3.h +0 -50
  161. package/native/third_party/JoltPhysics/Jolt/Math/Float4.h +0 -44
  162. package/native/third_party/JoltPhysics/Jolt/Math/GaussianElimination.h +0 -102
  163. package/native/third_party/JoltPhysics/Jolt/Math/HalfFloat.h +0 -208
  164. package/native/third_party/JoltPhysics/Jolt/Math/Mat44.h +0 -243
  165. package/native/third_party/JoltPhysics/Jolt/Math/Mat44.inl +0 -952
  166. package/native/third_party/JoltPhysics/Jolt/Math/Math.h +0 -208
  167. package/native/third_party/JoltPhysics/Jolt/Math/MathTypes.h +0 -32
  168. package/native/third_party/JoltPhysics/Jolt/Math/Matrix.h +0 -259
  169. package/native/third_party/JoltPhysics/Jolt/Math/Quat.h +0 -268
  170. package/native/third_party/JoltPhysics/Jolt/Math/Quat.inl +0 -406
  171. package/native/third_party/JoltPhysics/Jolt/Math/Real.h +0 -44
  172. package/native/third_party/JoltPhysics/Jolt/Math/Swizzle.h +0 -19
  173. package/native/third_party/JoltPhysics/Jolt/Math/Trigonometry.h +0 -79
  174. package/native/third_party/JoltPhysics/Jolt/Math/UVec4.h +0 -232
  175. package/native/third_party/JoltPhysics/Jolt/Math/UVec4.inl +0 -636
  176. package/native/third_party/JoltPhysics/Jolt/Math/Vec3.cpp +0 -71
  177. package/native/third_party/JoltPhysics/Jolt/Math/Vec3.h +0 -308
  178. package/native/third_party/JoltPhysics/Jolt/Math/Vec3.inl +0 -942
  179. package/native/third_party/JoltPhysics/Jolt/Math/Vec4.h +0 -320
  180. package/native/third_party/JoltPhysics/Jolt/Math/Vec4.inl +0 -1152
  181. package/native/third_party/JoltPhysics/Jolt/Math/Vector.h +0 -211
  182. package/native/third_party/JoltPhysics/Jolt/ObjectStream/GetPrimitiveTypeOfType.h +0 -54
  183. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStream.cpp +0 -38
  184. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStream.h +0 -337
  185. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryIn.cpp +0 -252
  186. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryIn.h +0 -57
  187. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryOut.cpp +0 -165
  188. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryOut.h +0 -57
  189. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamIn.cpp +0 -635
  190. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamIn.h +0 -148
  191. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamOut.cpp +0 -166
  192. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamOut.h +0 -101
  193. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextIn.cpp +0 -418
  194. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextIn.h +0 -55
  195. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextOut.cpp +0 -255
  196. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextOut.h +0 -62
  197. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTypes.h +0 -26
  198. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableAttribute.h +0 -111
  199. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableAttributeEnum.h +0 -67
  200. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableAttributeTyped.h +0 -60
  201. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableObject.cpp +0 -15
  202. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableObject.h +0 -170
  203. package/native/third_party/JoltPhysics/Jolt/ObjectStream/TypeDeclarations.cpp +0 -70
  204. package/native/third_party/JoltPhysics/Jolt/ObjectStream/TypeDeclarations.h +0 -45
  205. package/native/third_party/JoltPhysics/Jolt/Physics/Body/AllowedDOFs.h +0 -68
  206. package/native/third_party/JoltPhysics/Jolt/Physics/Body/Body.cpp +0 -426
  207. package/native/third_party/JoltPhysics/Jolt/Physics/Body/Body.h +0 -452
  208. package/native/third_party/JoltPhysics/Jolt/Physics/Body/Body.inl +0 -197
  209. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyAccess.h +0 -68
  210. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyActivationListener.h +0 -28
  211. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyCreationSettings.cpp +0 -234
  212. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyCreationSettings.h +0 -124
  213. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyFilter.h +0 -130
  214. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyID.h +0 -101
  215. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyInterface.cpp +0 -1099
  216. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyInterface.h +0 -324
  217. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyLock.h +0 -111
  218. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyLockInterface.h +0 -134
  219. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyLockMulti.h +0 -120
  220. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyManager.cpp +0 -1220
  221. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyManager.h +0 -403
  222. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyPair.h +0 -36
  223. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyType.h +0 -19
  224. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MassProperties.cpp +0 -185
  225. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MassProperties.h +0 -58
  226. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionProperties.cpp +0 -92
  227. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionProperties.h +0 -308
  228. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionProperties.inl +0 -178
  229. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionQuality.h +0 -31
  230. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionType.h +0 -17
  231. package/native/third_party/JoltPhysics/Jolt/Physics/Character/Character.cpp +0 -354
  232. package/native/third_party/JoltPhysics/Jolt/Physics/Character/Character.h +0 -159
  233. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterBase.cpp +0 -59
  234. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterBase.h +0 -157
  235. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterID.h +0 -98
  236. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterVirtual.cpp +0 -1933
  237. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterVirtual.h +0 -752
  238. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/AABoxCast.h +0 -20
  239. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ActiveEdgeMode.h +0 -17
  240. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ActiveEdges.h +0 -114
  241. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BackFaceMode.h +0 -16
  242. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhase.cpp +0 -16
  243. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhase.h +0 -109
  244. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.cpp +0 -313
  245. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.h +0 -38
  246. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h +0 -148
  247. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseLayerInterfaceMask.h +0 -92
  248. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseLayerInterfaceTable.h +0 -64
  249. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.cpp +0 -629
  250. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.h +0 -108
  251. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuery.h +0 -56
  252. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/ObjectVsBroadPhaseLayerFilterMask.h +0 -35
  253. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/ObjectVsBroadPhaseLayerFilterTable.h +0 -66
  254. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/QuadTree.cpp +0 -1768
  255. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/QuadTree.h +0 -389
  256. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastConvexVsTriangles.cpp +0 -107
  257. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastConvexVsTriangles.h +0 -46
  258. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastResult.h +0 -37
  259. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastSphereVsTriangles.cpp +0 -223
  260. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastSphereVsTriangles.h +0 -49
  261. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollectFacesMode.h +0 -16
  262. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideConvexVsTriangles.cpp +0 -155
  263. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideConvexVsTriangles.h +0 -56
  264. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollidePointResult.h +0 -25
  265. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideShape.h +0 -106
  266. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideShapeVsShapePerLeaf.h +0 -94
  267. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSoftBodyVertexIterator.h +0 -110
  268. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSoftBodyVerticesVsTriangles.h +0 -102
  269. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSphereVsTriangles.cpp +0 -121
  270. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSphereVsTriangles.h +0 -50
  271. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionCollector.h +0 -109
  272. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionCollectorImpl.h +0 -219
  273. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionDispatch.cpp +0 -107
  274. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionDispatch.h +0 -97
  275. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionGroup.cpp +0 -35
  276. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionGroup.h +0 -97
  277. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ContactListener.h +0 -143
  278. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/EstimateCollisionResponse.cpp +0 -213
  279. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/EstimateCollisionResponse.h +0 -48
  280. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilter.cpp +0 -32
  281. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilter.h +0 -46
  282. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilterTable.cpp +0 -38
  283. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilterTable.h +0 -130
  284. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/InternalEdgeRemovingCollector.h +0 -279
  285. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ManifoldBetweenTwoFaces.cpp +0 -271
  286. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ManifoldBetweenTwoFaces.h +0 -44
  287. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseQuery.cpp +0 -448
  288. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseQuery.h +0 -77
  289. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseStats.cpp +0 -62
  290. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseStats.h +0 -110
  291. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ObjectLayer.h +0 -111
  292. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ObjectLayerPairFilterMask.h +0 -52
  293. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ObjectLayerPairFilterTable.h +0 -78
  294. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterial.cpp +0 -35
  295. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterial.h +0 -57
  296. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterialSimple.cpp +0 -38
  297. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterialSimple.h +0 -37
  298. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/RayCast.h +0 -87
  299. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/BoxShape.cpp +0 -318
  300. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/BoxShape.h +0 -115
  301. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CapsuleShape.cpp +0 -438
  302. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CapsuleShape.h +0 -129
  303. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CompoundShape.cpp +0 -433
  304. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CompoundShape.h +0 -354
  305. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CompoundShapeVisitors.h +0 -461
  306. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexHullShape.cpp +0 -1311
  307. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexHullShape.h +0 -202
  308. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexShape.cpp +0 -566
  309. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexShape.h +0 -150
  310. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CylinderShape.cpp +0 -418
  311. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CylinderShape.h +0 -126
  312. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/DecoratedShape.cpp +0 -87
  313. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/DecoratedShape.h +0 -80
  314. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/EmptyShape.cpp +0 -64
  315. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/EmptyShape.h +0 -75
  316. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/GetTrianglesContext.h +0 -248
  317. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/HeightFieldShape.cpp +0 -2754
  318. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/HeightFieldShape.h +0 -380
  319. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MeshShape.cpp +0 -1305
  320. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MeshShape.h +0 -228
  321. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MutableCompoundShape.cpp +0 -596
  322. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MutableCompoundShape.h +0 -176
  323. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.cpp +0 -217
  324. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.h +0 -140
  325. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/PlaneShape.cpp +0 -541
  326. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/PlaneShape.h +0 -147
  327. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/PolyhedronSubmergedVolumeCalculator.h +0 -319
  328. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/RotatedTranslatedShape.cpp +0 -333
  329. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h +0 -161
  330. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ScaleHelpers.h +0 -83
  331. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ScaledShape.cpp +0 -238
  332. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ScaledShape.h +0 -145
  333. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/Shape.cpp +0 -325
  334. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/Shape.h +0 -466
  335. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SphereShape.cpp +0 -347
  336. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SphereShape.h +0 -125
  337. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/StaticCompoundShape.cpp +0 -674
  338. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/StaticCompoundShape.h +0 -139
  339. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SubShapeID.h +0 -138
  340. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SubShapeIDPair.h +0 -65
  341. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCapsuleShape.cpp +0 -453
  342. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCapsuleShape.gliffy +0 -1
  343. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCapsuleShape.h +0 -135
  344. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCylinderShape.cpp +0 -691
  345. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCylinderShape.h +0 -132
  346. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TriangleShape.cpp +0 -430
  347. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TriangleShape.h +0 -143
  348. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ShapeCast.h +0 -173
  349. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ShapeFilter.h +0 -73
  350. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/SimShapeFilter.h +0 -40
  351. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/SimShapeFilterWrapper.h +0 -58
  352. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/SortReverseAndStore.h +0 -48
  353. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/TransformedShape.cpp +0 -180
  354. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/TransformedShape.h +0 -194
  355. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/CalculateSolverSteps.h +0 -70
  356. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConeConstraint.cpp +0 -246
  357. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConeConstraint.h +0 -133
  358. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/Constraint.cpp +0 -73
  359. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/Constraint.h +0 -243
  360. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintManager.cpp +0 -289
  361. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintManager.h +0 -100
  362. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/AngleConstraintPart.h +0 -257
  363. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/AxisConstraintPart.h +0 -682
  364. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/DualAxisConstraintPart.h +0 -276
  365. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/GearConstraintPart.h +0 -195
  366. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/HingeRotationConstraintPart.h +0 -222
  367. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/IndependentAxisConstraintPart.h +0 -246
  368. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/PointConstraintPart.h +0 -239
  369. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/RackAndPinionConstraintPart.h +0 -196
  370. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/RotationEulerConstraintPart.h +0 -283
  371. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/RotationQuatConstraintPart.h +0 -246
  372. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/SpringPart.h +0 -169
  373. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/SwingTwistConstraintPart.h +0 -597
  374. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ContactConstraintManager.cpp +0 -1804
  375. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ContactConstraintManager.h +0 -524
  376. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/DistanceConstraint.cpp +0 -266
  377. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/DistanceConstraint.h +0 -120
  378. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/FixedConstraint.cpp +0 -215
  379. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/FixedConstraint.h +0 -96
  380. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/GearConstraint.cpp +0 -188
  381. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/GearConstraint.h +0 -116
  382. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/HingeConstraint.cpp +0 -443
  383. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/HingeConstraint.h +0 -205
  384. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/MotorSettings.cpp +0 -43
  385. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/MotorSettings.h +0 -66
  386. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraint.cpp +0 -458
  387. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraint.h +0 -191
  388. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPath.cpp +0 -85
  389. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPath.h +0 -76
  390. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPathHermite.cpp +0 -308
  391. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPathHermite.h +0 -54
  392. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PointConstraint.cpp +0 -157
  393. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PointConstraint.h +0 -94
  394. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PulleyConstraint.cpp +0 -253
  395. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PulleyConstraint.h +0 -137
  396. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/RackAndPinionConstraint.cpp +0 -189
  397. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/RackAndPinionConstraint.h +0 -118
  398. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SixDOFConstraint.cpp +0 -900
  399. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SixDOFConstraint.h +0 -289
  400. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SliderConstraint.cpp +0 -501
  401. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SliderConstraint.h +0 -198
  402. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SpringSettings.cpp +0 -35
  403. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SpringSettings.h +0 -70
  404. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SwingTwistConstraint.cpp +0 -524
  405. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SwingTwistConstraint.h +0 -197
  406. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/TwoBodyConstraint.cpp +0 -56
  407. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/TwoBodyConstraint.h +0 -65
  408. package/native/third_party/JoltPhysics/Jolt/Physics/DeterminismLog.cpp +0 -17
  409. package/native/third_party/JoltPhysics/Jolt/Physics/DeterminismLog.h +0 -159
  410. package/native/third_party/JoltPhysics/Jolt/Physics/EActivation.h +0 -16
  411. package/native/third_party/JoltPhysics/Jolt/Physics/EPhysicsUpdateError.h +0 -37
  412. package/native/third_party/JoltPhysics/Jolt/Physics/IslandBuilder.cpp +0 -492
  413. package/native/third_party/JoltPhysics/Jolt/Physics/IslandBuilder.h +0 -144
  414. package/native/third_party/JoltPhysics/Jolt/Physics/LargeIslandSplitter.cpp +0 -582
  415. package/native/third_party/JoltPhysics/Jolt/Physics/LargeIslandSplitter.h +0 -187
  416. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsLock.h +0 -169
  417. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsScene.cpp +0 -261
  418. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsScene.h +0 -104
  419. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsSettings.h +0 -125
  420. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsStepListener.h +0 -37
  421. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsSystem.cpp +0 -2915
  422. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsSystem.h +0 -391
  423. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsUpdateContext.cpp +0 -25
  424. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsUpdateContext.h +0 -176
  425. package/native/third_party/JoltPhysics/Jolt/Physics/Ragdoll/Ragdoll.cpp +0 -744
  426. package/native/third_party/JoltPhysics/Jolt/Physics/Ragdoll/Ragdoll.h +0 -245
  427. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyContactListener.h +0 -55
  428. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyCreationSettings.cpp +0 -128
  429. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyCreationSettings.h +0 -75
  430. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyManifold.h +0 -74
  431. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp +0 -1501
  432. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h +0 -333
  433. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyShape.cpp +0 -354
  434. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyShape.h +0 -73
  435. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodySharedSettings.cpp +0 -1487
  436. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodySharedSettings.h +0 -390
  437. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyUpdateContext.h +0 -63
  438. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyVertex.h +0 -36
  439. package/native/third_party/JoltPhysics/Jolt/Physics/StateRecorder.h +0 -136
  440. package/native/third_party/JoltPhysics/Jolt/Physics/StateRecorderImpl.cpp +0 -90
  441. package/native/third_party/JoltPhysics/Jolt/Physics/StateRecorderImpl.h +0 -50
  442. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/MotorcycleController.cpp +0 -306
  443. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/MotorcycleController.h +0 -119
  444. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/TrackedVehicleController.cpp +0 -547
  445. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/TrackedVehicleController.h +0 -169
  446. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleAntiRollBar.cpp +0 -33
  447. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleAntiRollBar.h +0 -33
  448. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleCollisionTester.cpp +0 -376
  449. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleCollisionTester.h +0 -146
  450. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleConstraint.cpp +0 -703
  451. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleConstraint.h +0 -252
  452. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleController.cpp +0 -17
  453. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleController.h +0 -87
  454. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleDifferential.cpp +0 -81
  455. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleDifferential.h +0 -39
  456. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleEngine.cpp +0 -122
  457. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleEngine.h +0 -93
  458. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTrack.cpp +0 -52
  459. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTrack.h +0 -56
  460. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTransmission.cpp +0 -159
  461. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTransmission.h +0 -87
  462. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/Wheel.cpp +0 -93
  463. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/Wheel.h +0 -148
  464. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/WheeledVehicleController.cpp +0 -866
  465. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/WheeledVehicleController.h +0 -205
  466. package/native/third_party/JoltPhysics/Jolt/RegisterTypes.cpp +0 -204
  467. package/native/third_party/JoltPhysics/Jolt/RegisterTypes.h +0 -29
  468. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRenderer.cpp +0 -1107
  469. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRenderer.h +0 -383
  470. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererPlayback.cpp +0 -168
  471. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererPlayback.h +0 -48
  472. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererRecorder.cpp +0 -158
  473. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererRecorder.h +0 -130
  474. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererSimple.cpp +0 -80
  475. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererSimple.h +0 -88
  476. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletalAnimation.cpp +0 -165
  477. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletalAnimation.h +0 -91
  478. package/native/third_party/JoltPhysics/Jolt/Skeleton/Skeleton.cpp +0 -82
  479. package/native/third_party/JoltPhysics/Jolt/Skeleton/Skeleton.h +0 -72
  480. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonMapper.cpp +0 -237
  481. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonMapper.h +0 -145
  482. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonPose.cpp +0 -87
  483. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonPose.h +0 -82
  484. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitter.cpp +0 -73
  485. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitter.h +0 -84
  486. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterBinning.cpp +0 -139
  487. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterBinning.h +0 -52
  488. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterMean.cpp +0 -43
  489. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterMean.h +0 -28
  490. package/native/third_party/JoltPhysics/LICENSE +0 -7
  491. package/native/third_party/JoltPhysics/README.md +0 -173
  492. package/native/third_party/bloom_jolt/CMakeLists.txt +0 -87
  493. package/native/third_party/bloom_jolt/include/bloom_jolt.h +0 -519
  494. package/native/third_party/bloom_jolt/src/bloom_jolt.cpp +0 -1780
@@ -1,2915 +0,0 @@
1
- // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
- // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
- // SPDX-License-Identifier: MIT
4
-
5
- #include <Jolt/Jolt.h>
6
-
7
- #include <Jolt/Physics/PhysicsSystem.h>
8
- #include <Jolt/Physics/PhysicsSettings.h>
9
- #include <Jolt/Physics/PhysicsUpdateContext.h>
10
- #include <Jolt/Physics/PhysicsStepListener.h>
11
- #include <Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.h>
12
- #include <Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.h>
13
- #include <Jolt/Physics/Collision/CollisionDispatch.h>
14
- #include <Jolt/Physics/Collision/AABoxCast.h>
15
- #include <Jolt/Physics/Collision/ShapeCast.h>
16
- #include <Jolt/Physics/Collision/CollideShape.h>
17
- #include <Jolt/Physics/Collision/CollisionCollectorImpl.h>
18
- #include <Jolt/Physics/Collision/CastResult.h>
19
- #include <Jolt/Physics/Collision/CollideConvexVsTriangles.h>
20
- #include <Jolt/Physics/Collision/ManifoldBetweenTwoFaces.h>
21
- #include <Jolt/Physics/Collision/Shape/ConvexShape.h>
22
- #include <Jolt/Physics/Collision/SimShapeFilterWrapper.h>
23
- #include <Jolt/Physics/Collision/InternalEdgeRemovingCollector.h>
24
- #include <Jolt/Physics/Constraints/CalculateSolverSteps.h>
25
- #include <Jolt/Physics/Constraints/ConstraintPart/AxisConstraintPart.h>
26
- #include <Jolt/Physics/DeterminismLog.h>
27
- #include <Jolt/Physics/SoftBody/SoftBodyMotionProperties.h>
28
- #include <Jolt/Physics/SoftBody/SoftBodyShape.h>
29
- #include <Jolt/Geometry/RayAABox.h>
30
- #include <Jolt/Geometry/ClosestPoint.h>
31
- #include <Jolt/Core/JobSystem.h>
32
- #include <Jolt/Core/TempAllocator.h>
33
- #include <Jolt/Core/QuickSort.h>
34
- #include <Jolt/Core/ScopeExit.h>
35
- #ifdef JPH_DEBUG_RENDERER
36
- #include <Jolt/Renderer/DebugRenderer.h>
37
- #endif // JPH_DEBUG_RENDERER
38
-
39
- JPH_NAMESPACE_BEGIN
40
-
41
- #ifdef JPH_DEBUG_RENDERER
42
- bool PhysicsSystem::sDrawMotionQualityLinearCast = false;
43
- #endif // JPH_DEBUG_RENDERER
44
-
45
- //#define BROAD_PHASE BroadPhaseBruteForce
46
- #define BROAD_PHASE BroadPhaseQuadTree
47
-
48
- static const Color cColorUpdateBroadPhaseFinalize = Color::sGetDistinctColor(1);
49
- static const Color cColorUpdateBroadPhasePrepare = Color::sGetDistinctColor(2);
50
- static const Color cColorFindCollisions = Color::sGetDistinctColor(3);
51
- static const Color cColorApplyGravity = Color::sGetDistinctColor(4);
52
- static const Color cColorSetupVelocityConstraints = Color::sGetDistinctColor(5);
53
- static const Color cColorBuildIslandsFromConstraints = Color::sGetDistinctColor(6);
54
- static const Color cColorDetermineActiveConstraints = Color::sGetDistinctColor(7);
55
- static const Color cColorFinalizeIslands = Color::sGetDistinctColor(8);
56
- static const Color cColorContactRemovedCallbacks = Color::sGetDistinctColor(9);
57
- static const Color cColorBodySetIslandIndex = Color::sGetDistinctColor(10);
58
- static const Color cColorStartNextStep = Color::sGetDistinctColor(11);
59
- static const Color cColorSolveVelocityConstraints = Color::sGetDistinctColor(12);
60
- static const Color cColorPreIntegrateVelocity = Color::sGetDistinctColor(13);
61
- static const Color cColorIntegrateVelocity = Color::sGetDistinctColor(14);
62
- static const Color cColorPostIntegrateVelocity = Color::sGetDistinctColor(15);
63
- static const Color cColorResolveCCDContacts = Color::sGetDistinctColor(16);
64
- static const Color cColorSolvePositionConstraints = Color::sGetDistinctColor(17);
65
- static const Color cColorFindCCDContacts = Color::sGetDistinctColor(18);
66
- static const Color cColorStepListeners = Color::sGetDistinctColor(19);
67
- static const Color cColorSoftBodyPrepare = Color::sGetDistinctColor(20);
68
- static const Color cColorSoftBodyCollide = Color::sGetDistinctColor(21);
69
- static const Color cColorSoftBodySimulate = Color::sGetDistinctColor(22);
70
- static const Color cColorSoftBodyFinalize = Color::sGetDistinctColor(23);
71
-
72
- PhysicsSystem::~PhysicsSystem()
73
- {
74
- // Remove broadphase
75
- delete mBroadPhase;
76
- }
77
-
78
- void PhysicsSystem::Init(uint inMaxBodies, uint inNumBodyMutexes, uint inMaxBodyPairs, uint inMaxContactConstraints, const BroadPhaseLayerInterface &inBroadPhaseLayerInterface, const ObjectVsBroadPhaseLayerFilter &inObjectVsBroadPhaseLayerFilter, const ObjectLayerPairFilter &inObjectLayerPairFilter)
79
- {
80
- // Clamp max bodies
81
- uint max_bodies = min(inMaxBodies, cMaxBodiesLimit);
82
- JPH_ASSERT(max_bodies == inMaxBodies, "Cannot support this many bodies!");
83
-
84
- mObjectVsBroadPhaseLayerFilter = &inObjectVsBroadPhaseLayerFilter;
85
- mObjectLayerPairFilter = &inObjectLayerPairFilter;
86
-
87
- // Initialize body manager
88
- mBodyManager.Init(max_bodies, inNumBodyMutexes, inBroadPhaseLayerInterface);
89
-
90
- // Create broadphase
91
- mBroadPhase = new BROAD_PHASE();
92
- mBroadPhase->Init(&mBodyManager, inBroadPhaseLayerInterface);
93
-
94
- // Init contact constraint manager
95
- mContactManager.Init(inMaxBodyPairs, inMaxContactConstraints);
96
-
97
- // Init islands builder
98
- mIslandBuilder.Init(max_bodies);
99
-
100
- // Initialize body interface
101
- mBodyInterfaceLocking.Init(mBodyLockInterfaceLocking, mBodyManager, *mBroadPhase);
102
- mBodyInterfaceNoLock.Init(mBodyLockInterfaceNoLock, mBodyManager, *mBroadPhase);
103
-
104
- // Initialize narrow phase query
105
- mNarrowPhaseQueryLocking.Init(mBodyLockInterfaceLocking, *mBroadPhase);
106
- mNarrowPhaseQueryNoLock.Init(mBodyLockInterfaceNoLock, *mBroadPhase);
107
- }
108
-
109
- void PhysicsSystem::OptimizeBroadPhase()
110
- {
111
- mBroadPhase->Optimize();
112
- }
113
-
114
- void PhysicsSystem::AddStepListener(PhysicsStepListener *inListener)
115
- {
116
- lock_guard lock(mStepListenersMutex);
117
-
118
- JPH_ASSERT(std::find(mStepListeners.begin(), mStepListeners.end(), inListener) == mStepListeners.end());
119
- mStepListeners.push_back(inListener);
120
- }
121
-
122
- void PhysicsSystem::RemoveStepListener(PhysicsStepListener *inListener)
123
- {
124
- lock_guard lock(mStepListenersMutex);
125
-
126
- StepListeners::iterator i = std::find(mStepListeners.begin(), mStepListeners.end(), inListener);
127
- JPH_ASSERT(i != mStepListeners.end());
128
- *i = mStepListeners.back();
129
- mStepListeners.pop_back();
130
- }
131
-
132
- #ifdef JPH_TRACK_SIMULATION_STATS
133
- void PhysicsSystem::GatherIslandStats()
134
- {
135
- JPH_PROFILE_FUNCTION();
136
-
137
- for (uint32 island_idx = 0; island_idx < mIslandBuilder.GetNumIslands(); ++island_idx)
138
- {
139
- BodyID *bodies_begin, *bodies_end;
140
- mIslandBuilder.GetBodiesInIsland(island_idx, bodies_begin, bodies_end);
141
- uint64 num_bodies = bodies_end - bodies_begin;
142
-
143
- // Calculate the number of dynamic bodies
144
- uint64 num_dynamic_bodies = 0;
145
- for (BodyID *body_id = bodies_begin; body_id < bodies_end; ++body_id)
146
- if (mBodyManager.GetBody(*body_id).GetMotionType() == EMotionType::Dynamic)
147
- ++num_dynamic_bodies;
148
- num_dynamic_bodies = max<uint64>(num_dynamic_bodies, 1); // Ensure we don't divide by zero
149
-
150
- // Equally distribute the stats over all bodies
151
- const IslandBuilder::IslandStats &stats = mIslandBuilder.GetIslandStats(island_idx);
152
- uint64 num_velocity_ticks = stats.mVelocityConstraintTicks / num_dynamic_bodies;
153
- uint64 num_position_ticks = stats.mPositionConstraintTicks / num_dynamic_bodies;
154
- uint64 num_update_bounds_ticks = stats.mUpdateBoundsTicks / num_bodies;
155
-
156
- for (BodyID *body_id = bodies_begin; body_id < bodies_end; ++body_id)
157
- {
158
- Body &body = mBodyManager.GetBody(*body_id);
159
- MotionProperties::SimulationStats &out_stats = body.GetMotionProperties()->GetSimulationStats();
160
- out_stats.mNumVelocitySteps = stats.mNumVelocitySteps;
161
- out_stats.mNumPositionSteps = stats.mNumPositionSteps;
162
- if (body.GetMotionType() == EMotionType::Dynamic)
163
- {
164
- out_stats.mVelocityConstraintTicks += num_velocity_ticks; // In case of multiple collision steps we accumulate
165
- out_stats.mPositionConstraintTicks += num_position_ticks;
166
- }
167
- out_stats.mUpdateBoundsTicks += num_update_bounds_ticks;
168
- out_stats.mIsLargeIsland = stats.mIsLargeIsland;
169
- }
170
- }
171
- }
172
- #endif // JPH_TRACK_SIMULATION_STATS
173
-
174
- EPhysicsUpdateError PhysicsSystem::Update(float inDeltaTime, int inCollisionSteps, TempAllocator *inTempAllocator, JobSystem *inJobSystem)
175
- {
176
- JPH_PROFILE_FUNCTION();
177
-
178
- JPH_DET_LOG("PhysicsSystem::Update: dt: " << inDeltaTime << " steps: " << inCollisionSteps);
179
-
180
- JPH_ASSERT(inCollisionSteps > 0);
181
- JPH_ASSERT(inDeltaTime >= 0.0f);
182
-
183
- // Sync point for the broadphase. This will allow it to do clean up operations without having any mutexes locked yet.
184
- mBroadPhase->FrameSync();
185
-
186
- // If there are no active bodies (and no step listener to wake them up) or there's no time delta
187
- uint32 num_active_rigid_bodies = mBodyManager.GetNumActiveBodies(EBodyType::RigidBody);
188
- uint32 num_active_soft_bodies = mBodyManager.GetNumActiveBodies(EBodyType::SoftBody);
189
- if ((num_active_rigid_bodies == 0 && num_active_soft_bodies == 0 && mStepListeners.empty()) || inDeltaTime <= 0.0f)
190
- {
191
- mBodyManager.LockAllBodies();
192
-
193
- // Update broadphase
194
- mBroadPhase->LockModifications();
195
- BroadPhase::UpdateState update_state = mBroadPhase->UpdatePrepare();
196
- mBroadPhase->UpdateFinalize(update_state);
197
- mBroadPhase->UnlockModifications();
198
-
199
- // If time has passed, call contact removal callbacks from contacts that existed in the previous update
200
- if (inDeltaTime > 0.0f)
201
- mContactManager.FinalizeContactCacheAndCallContactPointRemovedCallbacks(0, 0);
202
-
203
- mBodyManager.UnlockAllBodies();
204
- return EPhysicsUpdateError::None;
205
- }
206
-
207
- #ifdef JPH_TRACK_SIMULATION_STATS
208
- // Reset accumulated stats on the active bodies
209
- mBodyManager.ResetSimulationStats();
210
- #endif
211
-
212
- // Calculate ratio between current and previous frame delta time to scale initial constraint forces
213
- float step_delta_time = inDeltaTime / inCollisionSteps;
214
- float warm_start_impulse_ratio = mPhysicsSettings.mConstraintWarmStart && mPreviousStepDeltaTime > 0.0f? step_delta_time / mPreviousStepDeltaTime : 0.0f;
215
- mPreviousStepDeltaTime = step_delta_time;
216
-
217
- // Create the context used for passing information between jobs
218
- PhysicsUpdateContext context(*inTempAllocator);
219
- context.mPhysicsSystem = this;
220
- context.mJobSystem = inJobSystem;
221
- context.mBarrier = inJobSystem->CreateBarrier();
222
- context.mIslandBuilder = &mIslandBuilder;
223
- context.mStepDeltaTime = step_delta_time;
224
- context.mWarmStartImpulseRatio = warm_start_impulse_ratio;
225
- context.mSteps.resize(inCollisionSteps);
226
-
227
- // Allocate space for body pairs
228
- JPH_ASSERT(context.mBodyPairs == nullptr);
229
- context.mBodyPairs = static_cast<BodyPair *>(inTempAllocator->Allocate(sizeof(BodyPair) * mPhysicsSettings.mMaxInFlightBodyPairs));
230
-
231
- // Lock all bodies for write so that we can freely touch them
232
- mStepListenersMutex.lock();
233
- mBodyManager.LockAllBodies();
234
- mBroadPhase->LockModifications();
235
-
236
- // Get max number of concurrent jobs
237
- int max_concurrency = context.GetMaxConcurrency();
238
-
239
- // Calculate how many step listener jobs we spawn
240
- int num_step_listener_jobs = mStepListeners.empty()? 0 : max(1, min((int)mStepListeners.size() / mPhysicsSettings.mStepListenersBatchSize / mPhysicsSettings.mStepListenerBatchesPerJob, max_concurrency));
241
-
242
- // Number of gravity jobs depends on the amount of active bodies.
243
- // Launch max 1 job per batch of active bodies
244
- // Leave 1 thread for update broadphase prepare and 1 for determine active constraints
245
- int num_apply_gravity_jobs = max(1, min(((int)num_active_rigid_bodies + cApplyGravityBatchSize - 1) / cApplyGravityBatchSize, max_concurrency - 2));
246
-
247
- // Number of determine active constraints jobs to run depends on number of constraints.
248
- // Leave 1 thread for update broadphase prepare and 1 for apply gravity
249
- int num_determine_active_constraints_jobs = max(1, min(((int)mConstraintManager.GetNumConstraints() + cDetermineActiveConstraintsBatchSize - 1) / cDetermineActiveConstraintsBatchSize, max_concurrency - 2));
250
-
251
- // Number of setup velocity constraints jobs to run depends on number of constraints.
252
- int num_setup_velocity_constraints_jobs = max(1, min(((int)mConstraintManager.GetNumConstraints() + cSetupVelocityConstraintsBatchSize - 1) / cSetupVelocityConstraintsBatchSize, max_concurrency));
253
-
254
- // Number of find collisions jobs to run depends on number of active bodies.
255
- // Note that when we have more than 1 thread, we always spawn at least 2 find collisions jobs so that the first job can wait for build islands from constraints
256
- // (which may activate additional bodies that need to be processed) while the second job can start processing collision work.
257
- int num_find_collisions_jobs = max(max_concurrency == 1? 1 : 2, min(((int)num_active_rigid_bodies + cActiveBodiesBatchSize - 1) / cActiveBodiesBatchSize, max_concurrency));
258
-
259
- // Number of integrate velocity jobs depends on number of active bodies.
260
- int num_integrate_velocity_jobs = max(1, min(((int)num_active_rigid_bodies + cIntegrateVelocityBatchSize - 1) / cIntegrateVelocityBatchSize, max_concurrency));
261
-
262
- {
263
- JPH_PROFILE("Build Jobs");
264
-
265
- // Iterate over collision steps
266
- for (int step_idx = 0; step_idx < inCollisionSteps; ++step_idx)
267
- {
268
- bool is_first_step = step_idx == 0;
269
- bool is_last_step = step_idx == inCollisionSteps - 1;
270
-
271
- PhysicsUpdateContext::Step &step = context.mSteps[step_idx];
272
- step.mContext = &context;
273
- step.mIsFirst = is_first_step;
274
- step.mIsLast = is_last_step;
275
-
276
- // Create job to do broadphase finalization
277
- // This job must finish before integrating velocities. Until then the positions will not be updated neither will bodies be added / removed.
278
- step.mUpdateBroadphaseFinalize = inJobSystem->CreateJob("UpdateBroadPhaseFinalize", cColorUpdateBroadPhaseFinalize, [&context, &step]()
279
- {
280
- // Validate that all find collision jobs have stopped
281
- JPH_ASSERT(step.mActiveFindCollisionJobs.load(memory_order_relaxed) == 0);
282
-
283
- // Finalize the broadphase update
284
- context.mPhysicsSystem->mBroadPhase->UpdateFinalize(step.mBroadPhaseUpdateState);
285
-
286
- // Signal that it is done
287
- step.mPreIntegrateVelocity.RemoveDependency();
288
- }, num_find_collisions_jobs + 2); // depends on: find collisions, broadphase prepare update, finish building jobs
289
-
290
- // The immediate jobs below are only immediate for the first step, the all finished job will kick them for the next step
291
- int previous_step_dependency_count = is_first_step? 0 : 1;
292
-
293
- // Start job immediately: Start the prepare broadphase
294
- // Must be done under body lock protection since the order is body locks then broadphase mutex
295
- // If this is turned around the RemoveBody call will hang since it locks in that order
296
- step.mBroadPhasePrepare = inJobSystem->CreateJob("UpdateBroadPhasePrepare", cColorUpdateBroadPhasePrepare, [&context, &step]()
297
- {
298
- // Prepare the broadphase update
299
- step.mBroadPhaseUpdateState = context.mPhysicsSystem->mBroadPhase->UpdatePrepare();
300
-
301
- // Now the finalize can run (if other dependencies are met too)
302
- step.mUpdateBroadphaseFinalize.RemoveDependency();
303
- }, previous_step_dependency_count);
304
-
305
- // This job will find all collisions
306
- step.mBodyPairQueues.resize(max_concurrency);
307
- step.mMaxBodyPairsPerQueue = mPhysicsSettings.mMaxInFlightBodyPairs / max_concurrency;
308
- step.mActiveFindCollisionJobs.store(~PhysicsUpdateContext::JobMask(0) >> (sizeof(PhysicsUpdateContext::JobMask) * 8 - num_find_collisions_jobs), memory_order_release);
309
- step.mFindCollisions.resize(num_find_collisions_jobs);
310
- for (int i = 0; i < num_find_collisions_jobs; ++i)
311
- {
312
- // Build islands from constraints may activate additional bodies, so the first job will wait for this to finish in order to not miss any active bodies
313
- int num_dep_build_islands_from_constraints = i == 0? 1 : 0;
314
- step.mFindCollisions[i] = inJobSystem->CreateJob("FindCollisions", cColorFindCollisions, [&step, i]()
315
- {
316
- step.mContext->mPhysicsSystem->JobFindCollisions(&step, i);
317
- }, num_apply_gravity_jobs + num_determine_active_constraints_jobs + 1 + num_dep_build_islands_from_constraints); // depends on: apply gravity, determine active constraints, finish building jobs, build islands from constraints
318
- }
319
-
320
- if (is_first_step)
321
- {
322
- #ifdef JPH_ENABLE_ASSERTS
323
- // Don't allow write operations to the active bodies list
324
- mBodyManager.SetActiveBodiesLocked(true);
325
- #endif
326
-
327
- // Store the number of active bodies at the start of the step
328
- step.mNumActiveBodiesAtStepStart = mBodyManager.GetNumActiveBodies(EBodyType::RigidBody);
329
-
330
- // Lock all constraints
331
- mConstraintManager.LockAllConstraints();
332
-
333
- // Allocate memory for storing the active constraints
334
- JPH_ASSERT(context.mActiveConstraints == nullptr);
335
- context.mActiveConstraints = static_cast<Constraint **>(inTempAllocator->Allocate(mConstraintManager.GetNumConstraints() * sizeof(Constraint *)));
336
-
337
- // Prepare contact buffer
338
- mContactManager.PrepareConstraintBuffer(&context);
339
-
340
- // Setup island builder
341
- mIslandBuilder.PrepareContactConstraints(mContactManager.GetMaxConstraints(), context.mTempAllocator);
342
- }
343
-
344
- // This job applies gravity to all active bodies
345
- step.mApplyGravity.resize(num_apply_gravity_jobs);
346
- for (int i = 0; i < num_apply_gravity_jobs; ++i)
347
- step.mApplyGravity[i] = inJobSystem->CreateJob("ApplyGravity", cColorApplyGravity, [&context, &step]()
348
- {
349
- context.mPhysicsSystem->JobApplyGravity(&context, &step);
350
-
351
- JobHandle::sRemoveDependencies(step.mFindCollisions);
352
- }, num_step_listener_jobs > 0? num_step_listener_jobs : previous_step_dependency_count); // depends on: step listeners (or previous step if no step listeners)
353
-
354
- // This job will setup velocity constraints for non-collision constraints
355
- step.mSetupVelocityConstraints.resize(num_setup_velocity_constraints_jobs);
356
- for (int i = 0; i < num_setup_velocity_constraints_jobs; ++i)
357
- step.mSetupVelocityConstraints[i] = inJobSystem->CreateJob("SetupVelocityConstraints", cColorSetupVelocityConstraints, [&context, &step]()
358
- {
359
- context.mPhysicsSystem->JobSetupVelocityConstraints(context.mStepDeltaTime, &step);
360
-
361
- JobHandle::sRemoveDependencies(step.mSolveVelocityConstraints);
362
- }, num_determine_active_constraints_jobs + 1); // depends on: determine active constraints, finish building jobs
363
-
364
- // This job will build islands from constraints
365
- step.mBuildIslandsFromConstraints = inJobSystem->CreateJob("BuildIslandsFromConstraints", cColorBuildIslandsFromConstraints, [&context, &step]()
366
- {
367
- context.mPhysicsSystem->JobBuildIslandsFromConstraints(&context, &step);
368
-
369
- step.mFindCollisions[0].RemoveDependency(); // The first collisions job cannot start running until we've finished building islands and activated all bodies
370
- step.mFinalizeIslands.RemoveDependency();
371
- }, num_determine_active_constraints_jobs + 1); // depends on: determine active constraints, finish building jobs
372
-
373
- // This job determines active constraints
374
- step.mDetermineActiveConstraints.resize(num_determine_active_constraints_jobs);
375
- for (int i = 0; i < num_determine_active_constraints_jobs; ++i)
376
- step.mDetermineActiveConstraints[i] = inJobSystem->CreateJob("DetermineActiveConstraints", cColorDetermineActiveConstraints, [&context, &step]()
377
- {
378
- context.mPhysicsSystem->JobDetermineActiveConstraints(&step);
379
-
380
- step.mBuildIslandsFromConstraints.RemoveDependency();
381
-
382
- // Kick these jobs last as they will use up all CPU cores leaving no space for the previous job, we prefer setup velocity constraints to finish first so we kick it first
383
- JobHandle::sRemoveDependencies(step.mSetupVelocityConstraints);
384
- JobHandle::sRemoveDependencies(step.mFindCollisions);
385
- }, num_step_listener_jobs > 0? num_step_listener_jobs : previous_step_dependency_count); // depends on: step listeners (or previous step if no step listeners)
386
-
387
- // This job calls the step listeners
388
- step.mStepListeners.resize(num_step_listener_jobs);
389
- for (int i = 0; i < num_step_listener_jobs; ++i)
390
- step.mStepListeners[i] = inJobSystem->CreateJob("StepListeners", cColorStepListeners, [&context, &step]()
391
- {
392
- // Call the step listeners
393
- context.mPhysicsSystem->JobStepListeners(&step);
394
-
395
- // Kick apply gravity and determine active constraint jobs
396
- JobHandle::sRemoveDependencies(step.mApplyGravity);
397
- JobHandle::sRemoveDependencies(step.mDetermineActiveConstraints);
398
- }, previous_step_dependency_count);
399
-
400
- // Unblock the previous step
401
- if (!is_first_step)
402
- context.mSteps[step_idx - 1].mStartNextStep.RemoveDependency();
403
-
404
- // This job will finalize the simulation islands
405
- step.mFinalizeIslands = inJobSystem->CreateJob("FinalizeIslands", cColorFinalizeIslands, [&context, &step]()
406
- {
407
- // Validate that all find collision jobs have stopped
408
- JPH_ASSERT(step.mActiveFindCollisionJobs.load(memory_order_relaxed) == 0);
409
-
410
- context.mPhysicsSystem->JobFinalizeIslands(&context);
411
-
412
- JobHandle::sRemoveDependencies(step.mSolveVelocityConstraints);
413
- step.mBodySetIslandIndex.RemoveDependency();
414
- }, num_find_collisions_jobs + 2); // depends on: find collisions, build islands from constraints, finish building jobs
415
-
416
- // Unblock previous job
417
- // Note: technically we could release find collisions here but we don't want to because that could make them run before 'setup velocity constraints' which means that job won't have a thread left
418
- step.mBuildIslandsFromConstraints.RemoveDependency();
419
-
420
- // This job will call the contact removed callbacks
421
- step.mContactRemovedCallbacks = inJobSystem->CreateJob("ContactRemovedCallbacks", cColorContactRemovedCallbacks, [&context, &step]()
422
- {
423
- context.mPhysicsSystem->JobContactRemovedCallbacks(&step);
424
-
425
- if (step.mStartNextStep.IsValid())
426
- step.mStartNextStep.RemoveDependency();
427
- }, 1); // depends on the find ccd contacts
428
-
429
- // This job will set the island index on each body (only used for debug drawing purposes)
430
- // It will also delete any bodies that have been destroyed in the last frame
431
- step.mBodySetIslandIndex = inJobSystem->CreateJob("BodySetIslandIndex", cColorBodySetIslandIndex, [&context, &step]()
432
- {
433
- context.mPhysicsSystem->JobBodySetIslandIndex();
434
-
435
- JobHandle::sRemoveDependencies(step.mSolvePositionConstraints);
436
- }, 2); // depends on: finalize islands, finish building jobs
437
-
438
- // Job to start the next collision step
439
- if (!is_last_step)
440
- {
441
- PhysicsUpdateContext::Step *next_step = &context.mSteps[step_idx + 1];
442
- step.mStartNextStep = inJobSystem->CreateJob("StartNextStep", cColorStartNextStep, [this, next_step]()
443
- {
444
- #ifdef JPH_DEBUG
445
- // Validate that the cached bounds are correct
446
- mBodyManager.ValidateActiveBodyBounds();
447
- #endif // JPH_DEBUG
448
-
449
- #ifdef JPH_TRACK_SIMULATION_STATS
450
- // Gather stats from the islands and distribute them over the bodies
451
- GatherIslandStats();
452
- #endif
453
-
454
- // Store the number of active bodies at the start of the step
455
- next_step->mNumActiveBodiesAtStepStart = mBodyManager.GetNumActiveBodies(EBodyType::RigidBody);
456
-
457
- // Clear the large island splitter
458
- TempAllocator *temp_allocator = next_step->mContext->mTempAllocator;
459
- mLargeIslandSplitter.Reset(temp_allocator);
460
-
461
- // Clear the island builder
462
- mIslandBuilder.ResetIslands(temp_allocator);
463
-
464
- // Setup island builder
465
- mIslandBuilder.PrepareContactConstraints(mContactManager.GetMaxConstraints(), temp_allocator);
466
-
467
- // Restart the contact manager
468
- mContactManager.RecycleConstraintBuffer();
469
-
470
- // Kick the jobs of the next step (in the same order as the first step)
471
- next_step->mBroadPhasePrepare.RemoveDependency();
472
- if (next_step->mStepListeners.empty())
473
- {
474
- // Kick the gravity and active constraints jobs immediately
475
- JobHandle::sRemoveDependencies(next_step->mApplyGravity);
476
- JobHandle::sRemoveDependencies(next_step->mDetermineActiveConstraints);
477
- }
478
- else
479
- {
480
- // Kick the step listeners job first
481
- JobHandle::sRemoveDependencies(next_step->mStepListeners);
482
- }
483
- }, 3); // depends on: update soft bodies, contact removed callbacks, finish building the previous step
484
- }
485
-
486
- // This job will solve the velocity constraints
487
- step.mSolveVelocityConstraints.resize(max_concurrency);
488
- for (int i = 0; i < max_concurrency; ++i)
489
- step.mSolveVelocityConstraints[i] = inJobSystem->CreateJob("SolveVelocityConstraints", cColorSolveVelocityConstraints, [&context, &step]()
490
- {
491
- context.mPhysicsSystem->JobSolveVelocityConstraints(&context, &step);
492
-
493
- step.mPreIntegrateVelocity.RemoveDependency();
494
- }, num_setup_velocity_constraints_jobs + 2); // depends on: finalize islands, setup velocity constraints, finish building jobs.
495
-
496
- // We prefer setup velocity constraints to finish first so we kick it first
497
- JobHandle::sRemoveDependencies(step.mSetupVelocityConstraints);
498
- JobHandle::sRemoveDependencies(step.mFindCollisions);
499
-
500
- // Finalize islands is a dependency on find collisions so it can go last
501
- step.mFinalizeIslands.RemoveDependency();
502
-
503
- // This job will prepare the position update of all active bodies
504
- step.mPreIntegrateVelocity = inJobSystem->CreateJob("PreIntegrateVelocity", cColorPreIntegrateVelocity, [&context, &step]()
505
- {
506
- context.mPhysicsSystem->JobPreIntegrateVelocity(&context, &step);
507
-
508
- JobHandle::sRemoveDependencies(step.mIntegrateVelocity);
509
- }, 2 + max_concurrency); // depends on: broadphase update finalize, solve velocity constraints, finish building jobs.
510
-
511
- // Unblock previous jobs
512
- step.mUpdateBroadphaseFinalize.RemoveDependency();
513
- JobHandle::sRemoveDependencies(step.mSolveVelocityConstraints);
514
-
515
- // This job will update the positions of all active bodies
516
- step.mIntegrateVelocity.resize(num_integrate_velocity_jobs);
517
- for (int i = 0; i < num_integrate_velocity_jobs; ++i)
518
- step.mIntegrateVelocity[i] = inJobSystem->CreateJob("IntegrateVelocity", cColorIntegrateVelocity, [&context, &step]()
519
- {
520
- context.mPhysicsSystem->JobIntegrateVelocity(&context, &step);
521
-
522
- step.mPostIntegrateVelocity.RemoveDependency();
523
- }, 2); // depends on: pre integrate velocity, finish building jobs.
524
-
525
- // Unblock previous job
526
- step.mPreIntegrateVelocity.RemoveDependency();
527
-
528
- // This job will finish the position update of all active bodies
529
- step.mPostIntegrateVelocity = inJobSystem->CreateJob("PostIntegrateVelocity", cColorPostIntegrateVelocity, [&context, &step]()
530
- {
531
- context.mPhysicsSystem->JobPostIntegrateVelocity(&context, &step);
532
-
533
- step.mResolveCCDContacts.RemoveDependency();
534
- }, num_integrate_velocity_jobs + 1); // depends on: integrate velocity, finish building jobs
535
-
536
- // Unblock previous jobs
537
- JobHandle::sRemoveDependencies(step.mIntegrateVelocity);
538
-
539
- // This job will update the positions and velocities for all bodies that need continuous collision detection
540
- step.mResolveCCDContacts = inJobSystem->CreateJob("ResolveCCDContacts", cColorResolveCCDContacts, [&context, &step]()
541
- {
542
- context.mPhysicsSystem->JobResolveCCDContacts(&context, &step);
543
-
544
- JobHandle::sRemoveDependencies(step.mSolvePositionConstraints);
545
- }, 2); // depends on: integrate velocities, detect ccd contacts (added dynamically), finish building jobs.
546
-
547
- // Unblock previous job
548
- step.mPostIntegrateVelocity.RemoveDependency();
549
-
550
- // Fixes up drift in positions and updates the broadphase with new body positions
551
- step.mSolvePositionConstraints.resize(max_concurrency);
552
- for (int i = 0; i < max_concurrency; ++i)
553
- step.mSolvePositionConstraints[i] = inJobSystem->CreateJob("SolvePositionConstraints", cColorSolvePositionConstraints, [&context, &step]()
554
- {
555
- context.mPhysicsSystem->JobSolvePositionConstraints(&context, &step);
556
-
557
- // Kick the next step
558
- if (step.mSoftBodyPrepare.IsValid())
559
- step.mSoftBodyPrepare.RemoveDependency();
560
- }, 3); // depends on: resolve ccd contacts, body set island index, finish building jobs.
561
-
562
- // Unblock previous jobs.
563
- step.mResolveCCDContacts.RemoveDependency();
564
- step.mBodySetIslandIndex.RemoveDependency();
565
-
566
- // The soft body prepare job will create other jobs if needed
567
- step.mSoftBodyPrepare = inJobSystem->CreateJob("SoftBodyPrepare", cColorSoftBodyPrepare, [&context, &step]()
568
- {
569
- context.mPhysicsSystem->JobSoftBodyPrepare(&context, &step);
570
- }, max_concurrency); // depends on: solve position constraints.
571
-
572
- // Unblock previous jobs
573
- JobHandle::sRemoveDependencies(step.mSolvePositionConstraints);
574
- }
575
- }
576
-
577
- // Build the list of jobs to wait for
578
- JobSystem::Barrier *barrier = context.mBarrier;
579
- {
580
- JPH_PROFILE("Build job barrier");
581
-
582
- StaticArray<JobHandle, cMaxPhysicsJobs> handles;
583
- for (const PhysicsUpdateContext::Step &step : context.mSteps)
584
- {
585
- if (step.mBroadPhasePrepare.IsValid())
586
- handles.push_back(step.mBroadPhasePrepare);
587
- for (const JobHandle &h : step.mStepListeners)
588
- handles.push_back(h);
589
- for (const JobHandle &h : step.mDetermineActiveConstraints)
590
- handles.push_back(h);
591
- for (const JobHandle &h : step.mApplyGravity)
592
- handles.push_back(h);
593
- for (const JobHandle &h : step.mFindCollisions)
594
- handles.push_back(h);
595
- if (step.mUpdateBroadphaseFinalize.IsValid())
596
- handles.push_back(step.mUpdateBroadphaseFinalize);
597
- for (const JobHandle &h : step.mSetupVelocityConstraints)
598
- handles.push_back(h);
599
- handles.push_back(step.mBuildIslandsFromConstraints);
600
- handles.push_back(step.mFinalizeIslands);
601
- handles.push_back(step.mBodySetIslandIndex);
602
- for (const JobHandle &h : step.mSolveVelocityConstraints)
603
- handles.push_back(h);
604
- handles.push_back(step.mPreIntegrateVelocity);
605
- for (const JobHandle &h : step.mIntegrateVelocity)
606
- handles.push_back(h);
607
- handles.push_back(step.mPostIntegrateVelocity);
608
- handles.push_back(step.mResolveCCDContacts);
609
- for (const JobHandle &h : step.mSolvePositionConstraints)
610
- handles.push_back(h);
611
- handles.push_back(step.mContactRemovedCallbacks);
612
- if (step.mSoftBodyPrepare.IsValid())
613
- handles.push_back(step.mSoftBodyPrepare);
614
- if (step.mStartNextStep.IsValid())
615
- handles.push_back(step.mStartNextStep);
616
- }
617
- barrier->AddJobs(handles.data(), handles.size());
618
- }
619
-
620
- // Wait until all jobs finish
621
- // Note we don't just wait for the last job. If we would and another job
622
- // would be scheduled in between there is the possibility of a deadlock.
623
- // The other job could try to e.g. add/remove a body which would try to
624
- // lock a body mutex while this thread has already locked the mutex
625
- inJobSystem->WaitForJobs(barrier);
626
-
627
- // We're done with the barrier for this update
628
- inJobSystem->DestroyBarrier(barrier);
629
-
630
- #ifdef JPH_DEBUG
631
- // Validate that the cached bounds are correct
632
- mBodyManager.ValidateActiveBodyBounds();
633
- #endif // JPH_DEBUG
634
-
635
- #ifdef JPH_TRACK_SIMULATION_STATS
636
- // Gather stats from the islands and distribute them over the bodies
637
- GatherIslandStats();
638
- #endif
639
-
640
- // Clear the large island splitter
641
- mLargeIslandSplitter.Reset(inTempAllocator);
642
-
643
- // Clear the island builder
644
- mIslandBuilder.ResetIslands(inTempAllocator);
645
-
646
- // Clear the contact manager
647
- mContactManager.FinishConstraintBuffer();
648
-
649
- // Free active constraints
650
- inTempAllocator->Free(context.mActiveConstraints, mConstraintManager.GetNumConstraints() * sizeof(Constraint *));
651
- context.mActiveConstraints = nullptr;
652
-
653
- // Free body pairs
654
- inTempAllocator->Free(context.mBodyPairs, sizeof(BodyPair) * mPhysicsSettings.mMaxInFlightBodyPairs);
655
- context.mBodyPairs = nullptr;
656
-
657
- // Unlock the broadphase
658
- mBroadPhase->UnlockModifications();
659
-
660
- // Unlock all constraints
661
- mConstraintManager.UnlockAllConstraints();
662
-
663
- #ifdef JPH_ENABLE_ASSERTS
664
- // Allow write operations to the active bodies list
665
- mBodyManager.SetActiveBodiesLocked(false);
666
- #endif
667
-
668
- // Unlock all bodies
669
- mBodyManager.UnlockAllBodies();
670
-
671
- // Unlock step listeners
672
- mStepListenersMutex.unlock();
673
-
674
- // Return any errors
675
- EPhysicsUpdateError errors = static_cast<EPhysicsUpdateError>(context.mErrors.load(memory_order_acquire));
676
- JPH_ASSERT(errors == EPhysicsUpdateError::None, "An error occurred during the physics update, see EPhysicsUpdateError for more information");
677
- return errors;
678
- }
679
-
680
- void PhysicsSystem::JobStepListeners(PhysicsUpdateContext::Step *ioStep)
681
- {
682
- #ifdef JPH_ENABLE_ASSERTS
683
- // Read positions (broadphase updates concurrently so we can't write), read/write velocities
684
- BodyAccess::Grant grant(BodyAccess::EAccess::ReadWrite, BodyAccess::EAccess::Read);
685
-
686
- // Can activate bodies only (we cache the amount of active bodies at the beginning of the step in mNumActiveBodiesAtStepStart so we cannot deactivate here)
687
- BodyManager::GrantActiveBodiesAccess grant_active(true, false);
688
- #endif
689
-
690
- PhysicsStepListenerContext context;
691
- context.mDeltaTime = ioStep->mContext->mStepDeltaTime;
692
- context.mIsFirstStep = ioStep->mIsFirst;
693
- context.mIsLastStep = ioStep->mIsLast;
694
- context.mPhysicsSystem = this;
695
-
696
- uint32 batch_size = mPhysicsSettings.mStepListenersBatchSize;
697
- for (;;)
698
- {
699
- // Get the start of a new batch
700
- uint32 batch = ioStep->mStepListenerReadIdx.fetch_add(batch_size);
701
- if (batch >= mStepListeners.size())
702
- break;
703
-
704
- // Call the listeners
705
- for (uint32 i = batch, i_end = min((uint32)mStepListeners.size(), batch + batch_size); i < i_end; ++i)
706
- mStepListeners[i]->OnStep(context);
707
- }
708
- }
709
-
710
- void PhysicsSystem::JobDetermineActiveConstraints(PhysicsUpdateContext::Step *ioStep) const
711
- {
712
- #ifdef JPH_ENABLE_ASSERTS
713
- // No body access
714
- BodyAccess::Grant grant(BodyAccess::EAccess::None, BodyAccess::EAccess::None);
715
- #endif
716
-
717
- uint32 num_constraints = mConstraintManager.GetNumConstraints();
718
- uint32 num_active_constraints;
719
- Constraint **active_constraints = (Constraint **)JPH_STACK_ALLOC(cDetermineActiveConstraintsBatchSize * sizeof(Constraint *));
720
-
721
- for (;;)
722
- {
723
- // Atomically fetch a batch of constraints
724
- uint32 constraint_idx = ioStep->mDetermineActiveConstraintReadIdx.fetch_add(cDetermineActiveConstraintsBatchSize);
725
- if (constraint_idx >= num_constraints)
726
- break;
727
-
728
- // Calculate the end of the batch
729
- uint32 constraint_idx_end = min(num_constraints, constraint_idx + cDetermineActiveConstraintsBatchSize);
730
-
731
- // Store the active constraints at the start of the step (bodies get activated during the step which in turn may activate constraints leading to an inconsistent shapshot)
732
- mConstraintManager.GetActiveConstraints(constraint_idx, constraint_idx_end, active_constraints, num_active_constraints);
733
-
734
- // Copy the block of active constraints to the global list of active constraints
735
- if (num_active_constraints > 0)
736
- {
737
- uint32 active_constraint_idx = ioStep->mNumActiveConstraints.fetch_add(num_active_constraints);
738
- memcpy(ioStep->mContext->mActiveConstraints + active_constraint_idx, active_constraints, num_active_constraints * sizeof(Constraint *));
739
- }
740
- }
741
- }
742
-
743
- void PhysicsSystem::JobApplyGravity(const PhysicsUpdateContext *ioContext, PhysicsUpdateContext::Step *ioStep)
744
- {
745
- #ifdef JPH_ENABLE_ASSERTS
746
- // We update velocities and need the rotation to do so
747
- BodyAccess::Grant grant(BodyAccess::EAccess::ReadWrite, BodyAccess::EAccess::Read);
748
- #endif
749
-
750
- // Get list of active bodies that we had at the start of the physics update.
751
- // Any body that is activated as part of the simulation step does not receive gravity this frame.
752
- // Note that bodies may be activated during this job but not deactivated, this means that only elements
753
- // will be added to the array. Since the array is made to not reallocate, this is a safe operation.
754
- const BodyID *active_bodies = mBodyManager.GetActiveBodiesUnsafe(EBodyType::RigidBody);
755
- uint32 num_active_bodies_at_step_start = ioStep->mNumActiveBodiesAtStepStart;
756
-
757
- // Fetch delta time once outside the loop
758
- float delta_time = ioContext->mStepDeltaTime;
759
-
760
- // Update velocities from forces
761
- for (;;)
762
- {
763
- // Atomically fetch a batch of bodies
764
- uint32 active_body_idx = ioStep->mApplyGravityReadIdx.fetch_add(cApplyGravityBatchSize);
765
- if (active_body_idx >= num_active_bodies_at_step_start)
766
- break;
767
-
768
- // Calculate the end of the batch
769
- uint32 active_body_idx_end = min(num_active_bodies_at_step_start, active_body_idx + cApplyGravityBatchSize);
770
-
771
- // Process the batch
772
- while (active_body_idx < active_body_idx_end)
773
- {
774
- Body &body = mBodyManager.GetBody(active_bodies[active_body_idx]);
775
- if (body.IsDynamic())
776
- {
777
- MotionProperties *mp = body.GetMotionProperties();
778
- Quat rotation = body.GetRotation();
779
-
780
- if (body.GetApplyGyroscopicForce())
781
- mp->ApplyGyroscopicForceInternal(rotation, delta_time);
782
-
783
- mp->ApplyForceTorqueAndDragInternal(rotation, mGravity, delta_time);
784
- }
785
- active_body_idx++;
786
- }
787
- }
788
- }
789
-
790
- void PhysicsSystem::JobSetupVelocityConstraints(float inDeltaTime, PhysicsUpdateContext::Step *ioStep) const
791
- {
792
- #ifdef JPH_ENABLE_ASSERTS
793
- // We only read positions
794
- BodyAccess::Grant grant(BodyAccess::EAccess::None, BodyAccess::EAccess::Read);
795
- #endif
796
-
797
- uint32 num_constraints = ioStep->mNumActiveConstraints;
798
-
799
- for (;;)
800
- {
801
- // Atomically fetch a batch of constraints
802
- uint32 constraint_idx = ioStep->mSetupVelocityConstraintsReadIdx.fetch_add(cSetupVelocityConstraintsBatchSize);
803
- if (constraint_idx >= num_constraints)
804
- break;
805
-
806
- ConstraintManager::sSetupVelocityConstraints(ioStep->mContext->mActiveConstraints + constraint_idx, min<uint32>(cSetupVelocityConstraintsBatchSize, num_constraints - constraint_idx), inDeltaTime);
807
- }
808
- }
809
-
810
- void PhysicsSystem::JobBuildIslandsFromConstraints(PhysicsUpdateContext *ioContext, PhysicsUpdateContext::Step *ioStep)
811
- {
812
- #ifdef JPH_ENABLE_ASSERTS
813
- // We read constraints and positions
814
- BodyAccess::Grant grant(BodyAccess::EAccess::None, BodyAccess::EAccess::Read);
815
-
816
- // Can only activate bodies
817
- BodyManager::GrantActiveBodiesAccess grant_active(true, false);
818
- #endif
819
-
820
- // Prepare the island builder
821
- mIslandBuilder.PrepareNonContactConstraints(ioStep->mNumActiveConstraints, ioContext->mTempAllocator);
822
-
823
- // Build the islands
824
- ConstraintManager::sBuildIslands(ioStep->mContext->mActiveConstraints, ioStep->mNumActiveConstraints, mIslandBuilder, mBodyManager);
825
- }
826
-
827
- void PhysicsSystem::TrySpawnJobFindCollisions(PhysicsUpdateContext::Step *ioStep) const
828
- {
829
- // Get how many jobs we can spawn and check if we can spawn more
830
- uint max_jobs = ioStep->mBodyPairQueues.size();
831
- if (CountBits(ioStep->mActiveFindCollisionJobs.load(memory_order_relaxed)) >= max_jobs)
832
- return;
833
-
834
- // Count how many body pairs we have waiting
835
- uint32 num_body_pairs = 0;
836
- for (const PhysicsUpdateContext::BodyPairQueue &queue : ioStep->mBodyPairQueues)
837
- num_body_pairs += queue.mWriteIdx - queue.mReadIdx;
838
-
839
- // Count how many active bodies we have waiting
840
- uint32 num_active_bodies = mBodyManager.GetNumActiveBodies(EBodyType::RigidBody) - ioStep->mActiveBodyReadIdx;
841
-
842
- // Calculate how many jobs we would like
843
- uint desired_num_jobs = min((num_body_pairs + cNarrowPhaseBatchSize - 1) / cNarrowPhaseBatchSize + (num_active_bodies + cActiveBodiesBatchSize - 1) / cActiveBodiesBatchSize, max_jobs);
844
-
845
- for (;;)
846
- {
847
- // Get the bit mask of active jobs and see if we can spawn more
848
- PhysicsUpdateContext::JobMask current_active_jobs = ioStep->mActiveFindCollisionJobs.load(memory_order_relaxed);
849
- uint job_index = CountTrailingZeros(~current_active_jobs);
850
- if (job_index >= desired_num_jobs)
851
- break;
852
-
853
- // Try to claim the job index
854
- PhysicsUpdateContext::JobMask job_mask = PhysicsUpdateContext::JobMask(1) << job_index;
855
- PhysicsUpdateContext::JobMask prev_value = ioStep->mActiveFindCollisionJobs.fetch_or(job_mask, memory_order_acquire);
856
- if ((prev_value & job_mask) == 0)
857
- {
858
- // Add dependencies from the find collisions job to the next jobs
859
- ioStep->mUpdateBroadphaseFinalize.AddDependency();
860
- ioStep->mFinalizeIslands.AddDependency();
861
-
862
- // Start the job
863
- JobHandle job = ioStep->mContext->mJobSystem->CreateJob("FindCollisions", cColorFindCollisions, [step = ioStep, job_index]()
864
- {
865
- step->mContext->mPhysicsSystem->JobFindCollisions(step, job_index);
866
- });
867
-
868
- // Add the job to the job barrier so the main updating thread can execute the job too
869
- ioStep->mContext->mBarrier->AddJob(job);
870
-
871
- // Spawn only 1 extra job at a time
872
- return;
873
- }
874
- }
875
- }
876
-
877
- static void sFinalizeContactAllocator(PhysicsUpdateContext::Step &ioStep, const ContactConstraintManager::ContactAllocator &inAllocator)
878
- {
879
- // Atomically accumulate the number of found manifolds and body pairs
880
- ioStep.mNumBodyPairs.fetch_add(inAllocator.mNumBodyPairs, memory_order_relaxed);
881
- ioStep.mNumManifolds.fetch_add(inAllocator.mNumManifolds, memory_order_relaxed);
882
-
883
- // Combine update errors
884
- ioStep.mContext->mErrors.fetch_or((uint32)inAllocator.mErrors, memory_order_relaxed);
885
- }
886
-
887
- // Disable TSAN for this function. It detects a false positive race condition on mBodyPairs.
888
- // We have written mBodyPairs before doing mWriteIdx++ and we check mWriteIdx before reading mBodyPairs, so this should be safe.
889
- JPH_TSAN_NO_SANITIZE
890
- void PhysicsSystem::JobFindCollisions(PhysicsUpdateContext::Step *ioStep, int inJobIndex)
891
- {
892
- #ifdef JPH_ENABLE_ASSERTS
893
- // We read positions and read velocities (for elastic collisions)
894
- BodyAccess::Grant grant(BodyAccess::EAccess::Read, BodyAccess::EAccess::Read);
895
-
896
- // Can only activate bodies
897
- BodyManager::GrantActiveBodiesAccess grant_active(true, false);
898
- #endif
899
-
900
- // Allocation context for allocating new contact points
901
- ContactAllocator contact_allocator(mContactManager.GetContactAllocator());
902
-
903
- // Determine initial queue to read pairs from if no broadphase work can be done
904
- // (always start looking at results from the next job)
905
- int read_queue_idx = (inJobIndex + 1) % ioStep->mBodyPairQueues.size();
906
-
907
- // Allocate space to temporarily store a batch of active bodies
908
- BodyID *active_bodies = (BodyID *)JPH_STACK_ALLOC(cActiveBodiesBatchSize * sizeof(BodyID));
909
-
910
- for (;;)
911
- {
912
- // Check if there are active bodies to be processed
913
- uint32 active_bodies_read_idx = ioStep->mActiveBodyReadIdx;
914
- uint32 num_active_bodies = mBodyManager.GetNumActiveBodies(EBodyType::RigidBody);
915
- if (active_bodies_read_idx < num_active_bodies)
916
- {
917
- // Take a batch of active bodies
918
- uint32 active_bodies_read_idx_end = min(num_active_bodies, active_bodies_read_idx + cActiveBodiesBatchSize);
919
- if (ioStep->mActiveBodyReadIdx.compare_exchange_strong(active_bodies_read_idx, active_bodies_read_idx_end))
920
- {
921
- // Callback when a new body pair is found
922
- class MyBodyPairCallback : public BodyPairCollector
923
- {
924
- public:
925
- // Constructor
926
- MyBodyPairCallback(PhysicsUpdateContext::Step *inStep, ContactAllocator &ioContactAllocator, int inJobIndex) :
927
- mStep(inStep),
928
- mContactAllocator(ioContactAllocator),
929
- mJobIndex(inJobIndex)
930
- {
931
- }
932
-
933
- // Callback function when a body pair is found
934
- virtual void AddHit(const BodyPair &inPair) override
935
- {
936
- // Check if we have space in our write queue
937
- PhysicsUpdateContext::BodyPairQueue &queue = mStep->mBodyPairQueues[mJobIndex];
938
- uint32 body_pairs_in_queue = queue.mWriteIdx - queue.mReadIdx;
939
- if (body_pairs_in_queue >= mStep->mMaxBodyPairsPerQueue)
940
- {
941
- // Buffer full, process the pair now
942
- mStep->mContext->mPhysicsSystem->ProcessBodyPair(mContactAllocator, inPair);
943
- }
944
- else
945
- {
946
- // Store the pair in our own queue
947
- mStep->mContext->mBodyPairs[mJobIndex * mStep->mMaxBodyPairsPerQueue + queue.mWriteIdx % mStep->mMaxBodyPairsPerQueue] = inPair;
948
- ++queue.mWriteIdx;
949
- }
950
- }
951
-
952
- private:
953
- PhysicsUpdateContext::Step * mStep;
954
- ContactAllocator & mContactAllocator;
955
- int mJobIndex;
956
- };
957
- MyBodyPairCallback add_pair(ioStep, contact_allocator, inJobIndex);
958
-
959
- // Copy active bodies to temporary array, broadphase will reorder them
960
- uint32 batch_size = active_bodies_read_idx_end - active_bodies_read_idx;
961
- memcpy(active_bodies, mBodyManager.GetActiveBodiesUnsafe(EBodyType::RigidBody) + active_bodies_read_idx, batch_size * sizeof(BodyID));
962
-
963
- // Find pairs in the broadphase
964
- mBroadPhase->FindCollidingPairs(active_bodies, batch_size, mPhysicsSettings.mSpeculativeContactDistance, *mObjectVsBroadPhaseLayerFilter, *mObjectLayerPairFilter, add_pair);
965
-
966
- // Check if we have enough pairs in the buffer to start a new job
967
- const PhysicsUpdateContext::BodyPairQueue &queue = ioStep->mBodyPairQueues[inJobIndex];
968
- uint32 body_pairs_in_queue = queue.mWriteIdx - queue.mReadIdx;
969
- if (body_pairs_in_queue >= cNarrowPhaseBatchSize)
970
- TrySpawnJobFindCollisions(ioStep);
971
- }
972
- }
973
- else
974
- {
975
- // Lockless loop to get the next body pair from the pairs buffer
976
- const PhysicsUpdateContext *context = ioStep->mContext;
977
- int first_read_queue_idx = read_queue_idx;
978
- for (;;)
979
- {
980
- PhysicsUpdateContext::BodyPairQueue &queue = ioStep->mBodyPairQueues[read_queue_idx];
981
-
982
- // Get the next pair to process
983
- uint32 pair_idx = queue.mReadIdx;
984
-
985
- // If the pair hasn't been written yet
986
- if (pair_idx >= queue.mWriteIdx)
987
- {
988
- // Go to the next queue
989
- read_queue_idx = (read_queue_idx + 1) % ioStep->mBodyPairQueues.size();
990
-
991
- // If we're back at the first queue, we've looked at all of them and found nothing
992
- if (read_queue_idx == first_read_queue_idx)
993
- {
994
- // Collect information from the contact allocator and accumulate it in the step.
995
- sFinalizeContactAllocator(*ioStep, contact_allocator);
996
-
997
- // Mark this job as inactive
998
- ioStep->mActiveFindCollisionJobs.fetch_and(~PhysicsUpdateContext::JobMask(1 << inJobIndex), memory_order_release);
999
-
1000
- // Trigger the next jobs
1001
- ioStep->mUpdateBroadphaseFinalize.RemoveDependency();
1002
- ioStep->mFinalizeIslands.RemoveDependency();
1003
- return;
1004
- }
1005
-
1006
- // Try again reading from the next queue
1007
- continue;
1008
- }
1009
-
1010
- // Copy the body pair out of the buffer
1011
- const BodyPair bp = context->mBodyPairs[read_queue_idx * ioStep->mMaxBodyPairsPerQueue + pair_idx % ioStep->mMaxBodyPairsPerQueue];
1012
-
1013
- // Mark this pair as taken
1014
- if (queue.mReadIdx.compare_exchange_strong(pair_idx, pair_idx + 1))
1015
- {
1016
- // Process the actual body pair
1017
- ProcessBodyPair(contact_allocator, bp);
1018
- break;
1019
- }
1020
- }
1021
- }
1022
- }
1023
- }
1024
-
1025
- void PhysicsSystem::sDefaultSimCollideBodyVsBody(const Body &inBody1, const Body &inBody2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, CollideShapeSettings &ioCollideShapeSettings, CollideShapeCollector &ioCollector, const ShapeFilter &inShapeFilter)
1026
- {
1027
- SubShapeIDCreator part1, part2;
1028
-
1029
- if (inBody1.GetEnhancedInternalEdgeRemovalWithBody(inBody2))
1030
- {
1031
- // Collide with enhanced internal edge removal
1032
- ioCollideShapeSettings.mActiveEdgeMode = EActiveEdgeMode::CollideWithAll;
1033
- InternalEdgeRemovingCollector::sCollideShapeVsShape(inBody1.GetShape(), inBody2.GetShape(), Vec3::sOne(), Vec3::sOne(), inCenterOfMassTransform1, inCenterOfMassTransform2, part1, part2, ioCollideShapeSettings, ioCollector, inShapeFilter
1034
- #ifdef JPH_INTERNAL_EDGE_REMOVING_COLLECTOR_DEBUG
1035
- , inBody1.GetCenterOfMassPosition() // Query is done relative to the position of body 1
1036
- #endif // JPH_INTERNAL_EDGE_REMOVING_COLLECTOR_DEBUG
1037
- );
1038
- }
1039
- else
1040
- {
1041
- // Regular collide
1042
- CollisionDispatch::sCollideShapeVsShape(inBody1.GetShape(), inBody2.GetShape(), Vec3::sOne(), Vec3::sOne(), inCenterOfMassTransform1, inCenterOfMassTransform2, part1, part2, ioCollideShapeSettings, ioCollector, inShapeFilter);
1043
- }
1044
- }
1045
-
1046
- void PhysicsSystem::ProcessBodyPair(ContactAllocator &ioContactAllocator, const BodyPair &inBodyPair)
1047
- {
1048
- JPH_PROFILE_FUNCTION();
1049
-
1050
- // Fetch body pair
1051
- Body *body1 = &mBodyManager.GetBody(inBodyPair.mBodyA);
1052
- Body *body2 = &mBodyManager.GetBody(inBodyPair.mBodyB);
1053
- JPH_ASSERT(body1->IsActive());
1054
-
1055
- JPH_DET_LOG("ProcessBodyPair: id1: " << inBodyPair.mBodyA << " id2: " << inBodyPair.mBodyB << " p1: " << body1->GetCenterOfMassPosition() << " p2: " << body2->GetCenterOfMassPosition() << " r1: " << body1->GetRotation() << " r2: " << body2->GetRotation());
1056
-
1057
- // Check for soft bodies
1058
- if (body2->IsSoftBody())
1059
- {
1060
- // If the 2nd body is a soft body and not active, we activate it now
1061
- if (!body2->IsActive())
1062
- mBodyManager.ActivateBodies(&inBodyPair.mBodyB, 1);
1063
-
1064
- // Soft body processing is done later in the pipeline
1065
- return;
1066
- }
1067
-
1068
- // Ensure that body1 has the higher motion type (i.e. dynamic trumps kinematic), this ensures that we do the collision detection in the space of a moving body,
1069
- // which avoids accuracy problems when testing a very large static object against a small dynamic object
1070
- // Ensure that body1 id < body2 id when motion types are the same.
1071
- if (body1->GetMotionType() < body2->GetMotionType()
1072
- || (body1->GetMotionType() == body2->GetMotionType() && inBodyPair.mBodyB < inBodyPair.mBodyA))
1073
- std::swap(body1, body2);
1074
-
1075
- // Check if the contact points from the previous frame are reusable and if so copy them
1076
- bool pair_handled = false, constraint_created = false;
1077
- if (mPhysicsSettings.mUseBodyPairContactCache && !(body1->IsCollisionCacheInvalid() || body2->IsCollisionCacheInvalid()))
1078
- mContactManager.GetContactsFromCache(ioContactAllocator, *body1, *body2, pair_handled, constraint_created);
1079
-
1080
- // If the cache hasn't handled this body pair do actual collision detection
1081
- if (!pair_handled)
1082
- {
1083
- #ifdef JPH_TRACK_SIMULATION_STATS
1084
- uint64 start_ticks = GetProcessorTickCount();
1085
- #endif
1086
-
1087
- // Create entry in the cache for this body pair
1088
- // Needs to happen irrespective if we found a collision or not (we want to remember that no collision was found too)
1089
- ContactConstraintManager::BodyPairHandle body_pair_handle = mContactManager.AddBodyPair(ioContactAllocator, *body1, *body2);
1090
- if (body_pair_handle == nullptr)
1091
- return; // Out of cache space
1092
-
1093
- // Create the query settings
1094
- CollideShapeSettings settings;
1095
- settings.mCollectFacesMode = ECollectFacesMode::CollectFaces;
1096
- settings.mActiveEdgeMode = mPhysicsSettings.mCheckActiveEdges? EActiveEdgeMode::CollideOnlyWithActive : EActiveEdgeMode::CollideWithAll;
1097
- settings.mMaxSeparationDistance = body1->IsSensor() || body2->IsSensor()? 0.0f : mPhysicsSettings.mSpeculativeContactDistance;
1098
- settings.mActiveEdgeMovementDirection = body1->GetLinearVelocity() - body2->GetLinearVelocity();
1099
-
1100
- // Create shape filter
1101
- SimShapeFilterWrapper shape_filter(mSimShapeFilter, body1);
1102
- shape_filter.SetBody2(body2);
1103
-
1104
- // Get transforms relative to body1
1105
- RVec3 offset = body1->GetCenterOfMassPosition();
1106
- Mat44 transform1 = Mat44::sRotation(body1->GetRotation());
1107
- Mat44 transform2 = body2->GetCenterOfMassTransform().PostTranslated(-offset).ToMat44();
1108
-
1109
- if (mPhysicsSettings.mUseManifoldReduction // Check global flag
1110
- && body1->GetUseManifoldReductionWithBody(*body2)) // Check body flag
1111
- {
1112
- // Version WITH contact manifold reduction
1113
-
1114
- class MyManifold : public ContactManifold
1115
- {
1116
- public:
1117
- Vec3 mFirstWorldSpaceNormal;
1118
- };
1119
-
1120
- // A temporary structure that allows us to keep track of the all manifolds between this body pair
1121
- using Manifolds = StaticArray<MyManifold, 32>;
1122
-
1123
- // Create collector
1124
- class ReductionCollideShapeCollector : public CollideShapeCollector
1125
- {
1126
- public:
1127
- ReductionCollideShapeCollector(PhysicsSystem *inSystem, const Body *inBody1, const Body *inBody2) :
1128
- mSystem(inSystem),
1129
- mBody1(inBody1),
1130
- mBody2(inBody2)
1131
- {
1132
- }
1133
-
1134
- virtual void AddHit(const CollideShapeResult &inResult) override
1135
- {
1136
- // The first body should be the one with the highest motion type
1137
- JPH_ASSERT(mBody1->GetMotionType() >= mBody2->GetMotionType());
1138
- JPH_ASSERT(!ShouldEarlyOut());
1139
-
1140
- // Test if we want to accept this hit
1141
- if (mValidateBodyPair)
1142
- {
1143
- switch (mSystem->mContactManager.ValidateContactPoint(*mBody1, *mBody2, mBody1->GetCenterOfMassPosition(), inResult))
1144
- {
1145
- case ValidateResult::AcceptContact:
1146
- // We're just accepting this one, nothing to do
1147
- break;
1148
-
1149
- case ValidateResult::AcceptAllContactsForThisBodyPair:
1150
- // Accept and stop calling the validate callback
1151
- mValidateBodyPair = false;
1152
- break;
1153
-
1154
- case ValidateResult::RejectContact:
1155
- // Skip this contact
1156
- return;
1157
-
1158
- case ValidateResult::RejectAllContactsForThisBodyPair:
1159
- // Skip this and early out
1160
- ForceEarlyOut();
1161
- return;
1162
- }
1163
- }
1164
-
1165
- // Calculate normal
1166
- Vec3 world_space_normal = inResult.mPenetrationAxis.Normalized();
1167
-
1168
- // Check if we can add it to an existing manifold
1169
- Manifolds::iterator manifold;
1170
- float contact_normal_cos_max_delta_rot = mSystem->mPhysicsSettings.mContactNormalCosMaxDeltaRotation;
1171
- for (manifold = mManifolds.begin(); manifold != mManifolds.end(); ++manifold)
1172
- if (world_space_normal.Dot(manifold->mFirstWorldSpaceNormal) >= contact_normal_cos_max_delta_rot)
1173
- {
1174
- // Update average normal
1175
- manifold->mWorldSpaceNormal += world_space_normal;
1176
- manifold->mPenetrationDepth = max(manifold->mPenetrationDepth, inResult.mPenetrationDepth);
1177
- break;
1178
- }
1179
- if (manifold == mManifolds.end())
1180
- {
1181
- // Check if array is full
1182
- if (mManifolds.size() == mManifolds.capacity())
1183
- {
1184
- // Full, find manifold with least amount of penetration
1185
- manifold = mManifolds.begin();
1186
- for (Manifolds::iterator m = mManifolds.begin() + 1; m < mManifolds.end(); ++m)
1187
- if (m->mPenetrationDepth < manifold->mPenetrationDepth)
1188
- manifold = m;
1189
-
1190
- // If this contacts penetration is smaller than the smallest manifold, we skip this contact
1191
- if (inResult.mPenetrationDepth < manifold->mPenetrationDepth)
1192
- return;
1193
-
1194
- // Replace the manifold
1195
- *manifold = { { mBody1->GetCenterOfMassPosition(), world_space_normal, inResult.mPenetrationDepth, inResult.mSubShapeID1, inResult.mSubShapeID2, { }, { } }, world_space_normal };
1196
- }
1197
- else
1198
- {
1199
- // Not full, create new manifold
1200
- mManifolds.push_back({ { mBody1->GetCenterOfMassPosition(), world_space_normal, inResult.mPenetrationDepth, inResult.mSubShapeID1, inResult.mSubShapeID2, { }, { } }, world_space_normal });
1201
- manifold = mManifolds.end() - 1;
1202
- }
1203
- }
1204
-
1205
- // Determine contact points
1206
- const PhysicsSettings &settings = mSystem->mPhysicsSettings;
1207
- ManifoldBetweenTwoFaces(inResult.mContactPointOn1, inResult.mContactPointOn2, inResult.mPenetrationAxis, settings.mSpeculativeContactDistance + settings.mManifoldTolerance, inResult.mShape1Face, inResult.mShape2Face, manifold->mRelativeContactPointsOn1, manifold->mRelativeContactPointsOn2 JPH_IF_DEBUG_RENDERER(, mBody1->GetCenterOfMassPosition()));
1208
-
1209
- // Prune if we have more than 32 points (this means we could run out of space in the next iteration)
1210
- if (manifold->mRelativeContactPointsOn1.size() > 32)
1211
- PruneContactPoints(manifold->mFirstWorldSpaceNormal, manifold->mRelativeContactPointsOn1, manifold->mRelativeContactPointsOn2 JPH_IF_DEBUG_RENDERER(, manifold->mBaseOffset));
1212
- }
1213
-
1214
- PhysicsSystem * mSystem;
1215
- const Body * mBody1;
1216
- const Body * mBody2;
1217
- bool mValidateBodyPair = true;
1218
- Manifolds mManifolds;
1219
- };
1220
- ReductionCollideShapeCollector collector(this, body1, body2);
1221
-
1222
- // Perform collision detection between the two shapes
1223
- mSimCollideBodyVsBody(*body1, *body2, transform1, transform2, settings, collector, shape_filter.GetFilter());
1224
-
1225
- // Add the contacts
1226
- for (ContactManifold &manifold : collector.mManifolds)
1227
- {
1228
- // Normalize the normal (is a sum of all normals from merged manifolds)
1229
- manifold.mWorldSpaceNormal = manifold.mWorldSpaceNormal.Normalized();
1230
-
1231
- // If we still have too many points, prune them now
1232
- if (manifold.mRelativeContactPointsOn1.size() > 4)
1233
- PruneContactPoints(manifold.mWorldSpaceNormal, manifold.mRelativeContactPointsOn1, manifold.mRelativeContactPointsOn2 JPH_IF_DEBUG_RENDERER(, manifold.mBaseOffset));
1234
-
1235
- // Actually add the contact points to the manager
1236
- constraint_created |= mContactManager.AddContactConstraint(ioContactAllocator, body_pair_handle, *body1, *body2, manifold);
1237
- }
1238
- }
1239
- else
1240
- {
1241
- // Version WITHOUT contact manifold reduction
1242
-
1243
- // Create collector
1244
- class NonReductionCollideShapeCollector : public CollideShapeCollector
1245
- {
1246
- public:
1247
- NonReductionCollideShapeCollector(PhysicsSystem *inSystem, ContactAllocator &ioContactAllocator, Body *inBody1, Body *inBody2, const ContactConstraintManager::BodyPairHandle &inPairHandle) :
1248
- mSystem(inSystem),
1249
- mContactAllocator(ioContactAllocator),
1250
- mBody1(inBody1),
1251
- mBody2(inBody2),
1252
- mBodyPairHandle(inPairHandle)
1253
- {
1254
- }
1255
-
1256
- virtual void AddHit(const CollideShapeResult &inResult) override
1257
- {
1258
- // The first body should be the one with the highest motion type
1259
- JPH_ASSERT(mBody1->GetMotionType() >= mBody2->GetMotionType());
1260
- JPH_ASSERT(!ShouldEarlyOut());
1261
-
1262
- // Test if we want to accept this hit
1263
- if (mValidateBodyPair)
1264
- {
1265
- switch (mSystem->mContactManager.ValidateContactPoint(*mBody1, *mBody2, mBody1->GetCenterOfMassPosition(), inResult))
1266
- {
1267
- case ValidateResult::AcceptContact:
1268
- // We're just accepting this one, nothing to do
1269
- break;
1270
-
1271
- case ValidateResult::AcceptAllContactsForThisBodyPair:
1272
- // Accept and stop calling the validate callback
1273
- mValidateBodyPair = false;
1274
- break;
1275
-
1276
- case ValidateResult::RejectContact:
1277
- // Skip this contact
1278
- return;
1279
-
1280
- case ValidateResult::RejectAllContactsForThisBodyPair:
1281
- // Skip this and early out
1282
- ForceEarlyOut();
1283
- return;
1284
- }
1285
- }
1286
-
1287
- // Determine contact points
1288
- ContactManifold manifold;
1289
- manifold.mBaseOffset = mBody1->GetCenterOfMassPosition();
1290
- const PhysicsSettings &settings = mSystem->mPhysicsSettings;
1291
- ManifoldBetweenTwoFaces(inResult.mContactPointOn1, inResult.mContactPointOn2, inResult.mPenetrationAxis, settings.mSpeculativeContactDistance + settings.mManifoldTolerance, inResult.mShape1Face, inResult.mShape2Face, manifold.mRelativeContactPointsOn1, manifold.mRelativeContactPointsOn2 JPH_IF_DEBUG_RENDERER(, manifold.mBaseOffset));
1292
-
1293
- // Calculate normal
1294
- manifold.mWorldSpaceNormal = inResult.mPenetrationAxis.Normalized();
1295
-
1296
- // Store penetration depth
1297
- manifold.mPenetrationDepth = inResult.mPenetrationDepth;
1298
-
1299
- // Prune if we have more than 4 points
1300
- if (manifold.mRelativeContactPointsOn1.size() > 4)
1301
- PruneContactPoints(manifold.mWorldSpaceNormal, manifold.mRelativeContactPointsOn1, manifold.mRelativeContactPointsOn2 JPH_IF_DEBUG_RENDERER(, manifold.mBaseOffset));
1302
-
1303
- // Set other properties
1304
- manifold.mSubShapeID1 = inResult.mSubShapeID1;
1305
- manifold.mSubShapeID2 = inResult.mSubShapeID2;
1306
-
1307
- // Actually add the contact points to the manager
1308
- mConstraintCreated |= mSystem->mContactManager.AddContactConstraint(mContactAllocator, mBodyPairHandle, *mBody1, *mBody2, manifold);
1309
- }
1310
-
1311
- PhysicsSystem * mSystem;
1312
- ContactAllocator & mContactAllocator;
1313
- Body * mBody1;
1314
- Body * mBody2;
1315
- ContactConstraintManager::BodyPairHandle mBodyPairHandle;
1316
- bool mValidateBodyPair = true;
1317
- bool mConstraintCreated = false;
1318
- };
1319
- NonReductionCollideShapeCollector collector(this, ioContactAllocator, body1, body2, body_pair_handle);
1320
-
1321
- // Perform collision detection between the two shapes
1322
- mSimCollideBodyVsBody(*body1, *body2, transform1, transform2, settings, collector, shape_filter.GetFilter());
1323
-
1324
- constraint_created = collector.mConstraintCreated;
1325
- }
1326
-
1327
- #ifdef JPH_TRACK_SIMULATION_STATS
1328
- // Track time spent processing collision for this body pair
1329
- uint64 num_ticks = GetProcessorTickCount() - start_ticks;
1330
- if (body1->GetMotionType() > body2->GetMotionType())
1331
- {
1332
- // Assign all ticks to the body with the higher motion type
1333
- body1->GetMotionProperties()->GetSimulationStats().mNarrowPhaseTicks.fetch_add(num_ticks, memory_order_relaxed);
1334
- }
1335
- else
1336
- {
1337
- // When two bodies with the same motion type are involved, we give both bodies half the ticks
1338
- JPH_ASSERT(body1->GetMotionType() == body2->GetMotionType());
1339
- num_ticks /= 2;
1340
- body1->GetMotionProperties()->GetSimulationStats().mNarrowPhaseTicks.fetch_add(num_ticks, memory_order_relaxed);
1341
- body1->GetMotionProperties()->GetSimulationStats().mNarrowPhaseTicks.fetch_add(num_ticks, memory_order_relaxed);
1342
- }
1343
- #endif
1344
- }
1345
-
1346
- // If a contact constraint was created, we need to do some extra work
1347
- if (constraint_created)
1348
- {
1349
- // Wake up sleeping bodies
1350
- BodyID body_ids[2];
1351
- int num_bodies = 0;
1352
- if (body1->IsDynamic() && !body1->IsActive())
1353
- body_ids[num_bodies++] = body1->GetID();
1354
- if (body2->IsDynamic() && !body2->IsActive())
1355
- body_ids[num_bodies++] = body2->GetID();
1356
- if (num_bodies > 0)
1357
- mBodyManager.ActivateBodies(body_ids, num_bodies);
1358
-
1359
- // Link the two bodies
1360
- mIslandBuilder.LinkBodies(body1->GetIndexInActiveBodiesInternal(), body2->GetIndexInActiveBodiesInternal());
1361
- }
1362
- }
1363
-
1364
- void PhysicsSystem::JobFinalizeIslands(PhysicsUpdateContext *ioContext)
1365
- {
1366
- #ifdef JPH_ENABLE_ASSERTS
1367
- // We only touch island data
1368
- BodyAccess::Grant grant(BodyAccess::EAccess::None, BodyAccess::EAccess::None);
1369
- #endif
1370
-
1371
- // Finish collecting the islands, at this point the active body list doesn't change so it's safe to access
1372
- mIslandBuilder.Finalize(mBodyManager.GetActiveBodiesUnsafe(EBodyType::RigidBody), mBodyManager.GetNumActiveBodies(EBodyType::RigidBody), mContactManager.GetNumConstraints(), ioContext->mTempAllocator);
1373
-
1374
- // Prepare the large island splitter
1375
- if (mPhysicsSettings.mUseLargeIslandSplitter)
1376
- mLargeIslandSplitter.Prepare(mIslandBuilder, mBodyManager.GetNumActiveBodies(EBodyType::RigidBody), ioContext->mTempAllocator);
1377
- }
1378
-
1379
- void PhysicsSystem::JobBodySetIslandIndex()
1380
- {
1381
- #ifdef JPH_ENABLE_ASSERTS
1382
- // We only touch island data
1383
- BodyAccess::Grant grant(BodyAccess::EAccess::None, BodyAccess::EAccess::None);
1384
- #endif
1385
-
1386
- // Loop through the result and tag all bodies with an island index
1387
- for (uint32 island_idx = 0, n = mIslandBuilder.GetNumIslands(); island_idx < n; ++island_idx)
1388
- {
1389
- BodyID *body_start, *body_end;
1390
- mIslandBuilder.GetBodiesInIsland(island_idx, body_start, body_end);
1391
- for (const BodyID *body = body_start; body < body_end; ++body)
1392
- mBodyManager.GetBody(*body).GetMotionProperties()->SetIslandIndexInternal(island_idx);
1393
- }
1394
- }
1395
-
1396
- JPH_SUPPRESS_WARNING_PUSH
1397
- JPH_CLANG_SUPPRESS_WARNING("-Wundefined-func-template") // ConstraintManager::sWarmStartVelocityConstraints / ContactConstraintManager::WarmStartVelocityConstraints is instantiated in the cpp file
1398
-
1399
- void PhysicsSystem::JobSolveVelocityConstraints(PhysicsUpdateContext *ioContext, PhysicsUpdateContext::Step *ioStep)
1400
- {
1401
- #ifdef JPH_ENABLE_ASSERTS
1402
- // We update velocities and need to read positions to do so
1403
- BodyAccess::Grant grant(BodyAccess::EAccess::ReadWrite, BodyAccess::EAccess::Read);
1404
- #endif
1405
-
1406
- float delta_time = ioContext->mStepDeltaTime;
1407
- Constraint **active_constraints = ioContext->mActiveConstraints;
1408
-
1409
- // Only the first step to correct for the delta time difference in the previous update
1410
- float warm_start_impulse_ratio = ioStep->mIsFirst? ioContext->mWarmStartImpulseRatio : 1.0f;
1411
-
1412
- bool check_islands = true, check_split_islands = mPhysicsSettings.mUseLargeIslandSplitter;
1413
- for (;;)
1414
- {
1415
- // First try to get work from large islands
1416
- if (check_split_islands)
1417
- {
1418
- bool first_iteration;
1419
- uint split_island_index;
1420
- uint32 *constraints_begin, *constraints_end, *contacts_begin, *contacts_end;
1421
- switch (mLargeIslandSplitter.FetchNextBatch(split_island_index, constraints_begin, constraints_end, contacts_begin, contacts_end, first_iteration))
1422
- {
1423
- case LargeIslandSplitter::EStatus::BatchRetrieved:
1424
- {
1425
- #ifdef JPH_TRACK_SIMULATION_STATS
1426
- uint64 start_tick = GetProcessorTickCount();
1427
- #endif
1428
-
1429
- if (first_iteration)
1430
- {
1431
- // Iteration 0 is used to warm start the batch (we added 1 to the number of iterations in LargeIslandSplitter::SplitIsland)
1432
- DummyCalculateSolverSteps dummy;
1433
- ConstraintManager::sWarmStartVelocityConstraints(active_constraints, constraints_begin, constraints_end, warm_start_impulse_ratio, dummy);
1434
- mContactManager.WarmStartVelocityConstraints(contacts_begin, contacts_end, warm_start_impulse_ratio, dummy);
1435
- }
1436
- else
1437
- {
1438
- // Solve velocity constraints
1439
- ConstraintManager::sSolveVelocityConstraints(active_constraints, constraints_begin, constraints_end, delta_time);
1440
- mContactManager.SolveVelocityConstraints(contacts_begin, contacts_end);
1441
- }
1442
-
1443
- // Mark the batch as processed
1444
- bool last_iteration, final_batch;
1445
- mLargeIslandSplitter.MarkBatchProcessed(split_island_index, constraints_begin, constraints_end, contacts_begin, contacts_end, last_iteration, final_batch);
1446
-
1447
- // Save back the lambdas in the contact cache for the warm start of the next physics update
1448
- if (last_iteration)
1449
- mContactManager.StoreAppliedImpulses(contacts_begin, contacts_end);
1450
-
1451
- #ifdef JPH_TRACK_SIMULATION_STATS
1452
- uint64 num_ticks = GetProcessorTickCount() - start_tick;
1453
- mIslandBuilder.GetIslandStats(mLargeIslandSplitter.GetIslandIndex(split_island_index)).mVelocityConstraintTicks.fetch_add(num_ticks, memory_order_relaxed);
1454
- #endif
1455
-
1456
- // We processed work, loop again
1457
- continue;
1458
- }
1459
-
1460
- case LargeIslandSplitter::EStatus::WaitingForBatch:
1461
- break;
1462
-
1463
- case LargeIslandSplitter::EStatus::AllBatchesDone:
1464
- check_split_islands = false;
1465
- break;
1466
- }
1467
- }
1468
-
1469
- // If that didn't succeed try to process an island
1470
- if (check_islands)
1471
- {
1472
- // Next island
1473
- uint32 island_idx = ioStep->mSolveVelocityConstraintsNextIsland++;
1474
- if (island_idx >= mIslandBuilder.GetNumIslands())
1475
- {
1476
- // We processed all islands, stop checking islands
1477
- check_islands = false;
1478
- continue;
1479
- }
1480
-
1481
- JPH_PROFILE("Island");
1482
-
1483
- // Get iterators for this island
1484
- uint32 *constraints_begin, *constraints_end, *contacts_begin, *contacts_end;
1485
- bool has_constraints = mIslandBuilder.GetConstraintsInIsland(island_idx, constraints_begin, constraints_end);
1486
- bool has_contacts = mIslandBuilder.GetContactsInIsland(island_idx, contacts_begin, contacts_end);
1487
-
1488
- // If we don't have any contacts or constraints, we know that none of the following islands have any contacts or constraints
1489
- // (because they're sorted by most constraints first). This means we're done.
1490
- if (!has_contacts && !has_constraints)
1491
- {
1492
- #ifdef JPH_ENABLE_ASSERTS
1493
- // Validate our assumption that the next islands don't have any constraints or contacts
1494
- for (; island_idx < mIslandBuilder.GetNumIslands(); ++island_idx)
1495
- {
1496
- JPH_ASSERT(!mIslandBuilder.GetConstraintsInIsland(island_idx, constraints_begin, constraints_end));
1497
- JPH_ASSERT(!mIslandBuilder.GetContactsInIsland(island_idx, contacts_begin, contacts_end));
1498
- }
1499
- #endif // JPH_ENABLE_ASSERTS
1500
-
1501
- check_islands = false;
1502
- continue;
1503
- }
1504
-
1505
- #ifdef JPH_TRACK_SIMULATION_STATS
1506
- uint64 start_tick = GetProcessorTickCount();
1507
- #endif
1508
-
1509
- // Sorting is costly but needed for a deterministic simulation, allow the user to turn this off
1510
- if (mPhysicsSettings.mDeterministicSimulation)
1511
- {
1512
- // Sort constraints to give a deterministic simulation
1513
- ConstraintManager::sSortConstraints(active_constraints, constraints_begin, constraints_end);
1514
-
1515
- // Sort contacts to give a deterministic simulation
1516
- mContactManager.SortContacts(contacts_begin, contacts_end);
1517
- }
1518
-
1519
- // Split up large islands
1520
- #ifdef JPH_TRACK_SIMULATION_STATS
1521
- bool is_large_island = true;
1522
- #endif
1523
- CalculateSolverSteps steps_calculator(mPhysicsSettings);
1524
- if (!mPhysicsSettings.mUseLargeIslandSplitter
1525
- || !mLargeIslandSplitter.SplitIsland(island_idx, mIslandBuilder, mBodyManager, mContactManager, active_constraints, steps_calculator))
1526
- {
1527
- #ifdef JPH_TRACK_SIMULATION_STATS
1528
- is_large_island = false;
1529
- #endif
1530
-
1531
- // We didn't create a split, just run the solver now for this entire island. Begin by warm starting.
1532
- ConstraintManager::sWarmStartVelocityConstraints(active_constraints, constraints_begin, constraints_end, warm_start_impulse_ratio, steps_calculator);
1533
- mContactManager.WarmStartVelocityConstraints(contacts_begin, contacts_end, warm_start_impulse_ratio, steps_calculator);
1534
- steps_calculator.Finalize();
1535
-
1536
- // Store the number of position steps for later
1537
- mIslandBuilder.SetNumPositionSteps(island_idx, steps_calculator.GetNumPositionSteps());
1538
-
1539
- // Solve velocity constraints
1540
- for (uint velocity_step = 0; velocity_step < steps_calculator.GetNumVelocitySteps(); ++velocity_step)
1541
- {
1542
- bool applied_impulse = ConstraintManager::sSolveVelocityConstraints(active_constraints, constraints_begin, constraints_end, delta_time);
1543
- applied_impulse |= mContactManager.SolveVelocityConstraints(contacts_begin, contacts_end);
1544
- if (!applied_impulse)
1545
- break;
1546
- }
1547
-
1548
- // Save back the lambdas in the contact cache for the warm start of the next physics update
1549
- mContactManager.StoreAppliedImpulses(contacts_begin, contacts_end);
1550
- }
1551
-
1552
- #ifdef JPH_TRACK_SIMULATION_STATS
1553
- uint64 num_ticks = GetProcessorTickCount() - start_tick;
1554
- IslandBuilder::IslandStats &stats = mIslandBuilder.GetIslandStats(island_idx);
1555
- stats.mNumVelocitySteps = (uint8)steps_calculator.GetNumVelocitySteps();
1556
- stats.mNumPositionSteps = (uint8)steps_calculator.GetNumPositionSteps();
1557
- stats.mVelocityConstraintTicks.fetch_add(num_ticks, memory_order_relaxed);
1558
- stats.mIsLargeIsland = is_large_island;
1559
- #endif
1560
-
1561
- // We processed work, loop again
1562
- continue;
1563
- }
1564
-
1565
- if (check_islands)
1566
- {
1567
- // If there are islands, we don't need to wait and can pick up new work
1568
- continue;
1569
- }
1570
- else if (check_split_islands)
1571
- {
1572
- // If there are split islands, but we didn't do any work, give up a time slice
1573
- std::this_thread::yield();
1574
- }
1575
- else
1576
- {
1577
- // No more work
1578
- break;
1579
- }
1580
- }
1581
- }
1582
-
1583
- JPH_SUPPRESS_WARNING_POP
1584
-
1585
- void PhysicsSystem::JobPreIntegrateVelocity(PhysicsUpdateContext *ioContext, PhysicsUpdateContext::Step *ioStep)
1586
- {
1587
- // Reserve enough space for all bodies that may need a cast
1588
- TempAllocator *temp_allocator = ioContext->mTempAllocator;
1589
- JPH_ASSERT(ioStep->mCCDBodies == nullptr);
1590
- ioStep->mCCDBodiesCapacity = mBodyManager.GetNumActiveCCDBodies();
1591
- ioStep->mCCDBodies = (CCDBody *)temp_allocator->Allocate(ioStep->mCCDBodiesCapacity * sizeof(CCDBody));
1592
-
1593
- // Initialize the mapping table between active body and CCD body
1594
- JPH_ASSERT(ioStep->mActiveBodyToCCDBody == nullptr);
1595
- ioStep->mNumActiveBodyToCCDBody = mBodyManager.GetNumActiveBodies(EBodyType::RigidBody);
1596
- ioStep->mActiveBodyToCCDBody = (int *)temp_allocator->Allocate(ioStep->mNumActiveBodyToCCDBody * sizeof(int));
1597
-
1598
- // Prepare the split island builder for solving the position constraints
1599
- mLargeIslandSplitter.PrepareForSolvePositions();
1600
- }
1601
-
1602
- void PhysicsSystem::JobIntegrateVelocity(const PhysicsUpdateContext *ioContext, PhysicsUpdateContext::Step *ioStep)
1603
- {
1604
- #ifdef JPH_ENABLE_ASSERTS
1605
- // We update positions and need velocity to do so, we also clamp velocities so need to write to them
1606
- BodyAccess::Grant grant(BodyAccess::EAccess::ReadWrite, BodyAccess::EAccess::ReadWrite);
1607
- #endif
1608
-
1609
- float delta_time = ioContext->mStepDeltaTime;
1610
- const BodyID *active_bodies = mBodyManager.GetActiveBodiesUnsafe(EBodyType::RigidBody);
1611
- uint32 num_active_bodies = mBodyManager.GetNumActiveBodies(EBodyType::RigidBody);
1612
- uint32 num_active_bodies_after_find_collisions = ioStep->mActiveBodyReadIdx;
1613
-
1614
- // We can move bodies that are not part of an island. In this case we need to notify the broadphase of the movement.
1615
- static constexpr int cBodiesBatch = 64;
1616
- BodyID *bodies_to_update_bounds = (BodyID *)JPH_STACK_ALLOC(cBodiesBatch * sizeof(BodyID));
1617
- int num_bodies_to_update_bounds = 0;
1618
-
1619
- for (;;)
1620
- {
1621
- // Atomically fetch a batch of bodies
1622
- uint32 active_body_idx = ioStep->mIntegrateVelocityReadIdx.fetch_add(cIntegrateVelocityBatchSize);
1623
- if (active_body_idx >= num_active_bodies)
1624
- break;
1625
-
1626
- // Calculate the end of the batch
1627
- uint32 active_body_idx_end = min(num_active_bodies, active_body_idx + cIntegrateVelocityBatchSize);
1628
-
1629
- // Process the batch
1630
- while (active_body_idx < active_body_idx_end)
1631
- {
1632
- // Update the positions using an Symplectic Euler step (which integrates using the updated velocity v1' rather
1633
- // than the original velocity v1):
1634
- // x1' = x1 + h * v1'
1635
- // At this point the active bodies list does not change, so it is safe to access the array.
1636
- BodyID body_id = active_bodies[active_body_idx];
1637
- Body &body = mBodyManager.GetBody(body_id);
1638
- MotionProperties *mp = body.GetMotionProperties();
1639
-
1640
- JPH_DET_LOG("JobIntegrateVelocity: id: " << body_id << " v: " << body.GetLinearVelocity() << " w: " << body.GetAngularVelocity());
1641
-
1642
- // Clamp velocities (not for kinematic bodies)
1643
- if (body.IsDynamic())
1644
- {
1645
- mp->ClampLinearVelocity();
1646
- mp->ClampAngularVelocity();
1647
- }
1648
-
1649
- // Update the rotation of the body according to the angular velocity
1650
- // For motion type discrete we need to do this anyway, for motion type linear cast we have multiple choices
1651
- // 1. Rotate the body first and then sweep
1652
- // 2. First sweep and then rotate the body at the end
1653
- // 3. Pick some in between rotation (e.g. half way), then sweep and finally rotate the remainder
1654
- // (1) has some clear advantages as when a long thin body hits a surface away from the center of mass, this will result in a large angular velocity and a limited reduction in linear velocity.
1655
- // When simulation the rotation first before doing the translation, the body will be able to rotate away from the contact point allowing the center of mass to approach the surface. When using
1656
- // approach (2) in this case what will happen is that we will immediately detect the same collision again (the body has not rotated and the body was already colliding at the end of the previous
1657
- // time step) resulting in a lot of stolen time and the body appearing to be frozen in an unnatural pose (like it is glued at an angle to the surface). (2) obviously has some negative side effects
1658
- // too as simulating the rotation first may cause it to tunnel through a small object that the linear cast might have otherwise detected. In any case a linear cast is not good for detecting
1659
- // tunneling due to angular rotation, so we don't care about that too much (you'd need a full cast to take angular effects into account).
1660
- body.AddRotationStep(body.GetAngularVelocity() * delta_time);
1661
-
1662
- // Get delta position
1663
- Vec3 delta_pos = body.GetLinearVelocity() * delta_time;
1664
-
1665
- // If the position should be updated (or if it is delayed because of CCD)
1666
- bool update_position = true;
1667
-
1668
- switch (mp->GetMotionQuality())
1669
- {
1670
- case EMotionQuality::Discrete:
1671
- // No additional collision checking to be done
1672
- break;
1673
-
1674
- case EMotionQuality::LinearCast:
1675
- if (body.IsDynamic() // Kinematic bodies cannot be stopped
1676
- && !body.IsSensor()) // We don't support CCD sensors
1677
- {
1678
- // Determine inner radius (the smallest sphere that fits into the shape)
1679
- float inner_radius = body.GetShape()->GetInnerRadius();
1680
- JPH_ASSERT(inner_radius > 0.0f, "The shape has no inner radius, this makes the shape unsuitable for the linear cast motion quality as we cannot move it without risking tunneling.");
1681
-
1682
- // Measure translation in this step and check if it above the threshold to perform a linear cast
1683
- float linear_cast_threshold_sq = Square(mPhysicsSettings.mLinearCastThreshold * inner_radius);
1684
- if (delta_pos.LengthSq() > linear_cast_threshold_sq)
1685
- {
1686
- // This body needs a cast
1687
- uint32 ccd_body_idx = ioStep->mNumCCDBodies++;
1688
- JPH_ASSERT(active_body_idx < ioStep->mNumActiveBodyToCCDBody);
1689
- ioStep->mActiveBodyToCCDBody[active_body_idx] = ccd_body_idx;
1690
- new (&ioStep->mCCDBodies[ccd_body_idx]) CCDBody(body_id, delta_pos, linear_cast_threshold_sq, min(mPhysicsSettings.mPenetrationSlop, mPhysicsSettings.mLinearCastMaxPenetration * inner_radius));
1691
-
1692
- update_position = false;
1693
- }
1694
- }
1695
- break;
1696
- }
1697
-
1698
- if (update_position)
1699
- {
1700
- // Move the body now
1701
- body.AddPositionStep(delta_pos);
1702
-
1703
- // If the body was activated due to an earlier CCD step it will have an index in the active
1704
- // body list that it higher than the highest one we processed during FindCollisions
1705
- // which means it hasn't been assigned an island and will not be updated by an island
1706
- // this means that we need to update its bounds manually
1707
- if (mp->GetIndexInActiveBodiesInternal() >= num_active_bodies_after_find_collisions)
1708
- {
1709
- body.CalculateWorldSpaceBoundsInternal();
1710
- bodies_to_update_bounds[num_bodies_to_update_bounds++] = body.GetID();
1711
- if (num_bodies_to_update_bounds == cBodiesBatch)
1712
- {
1713
- // Buffer full, flush now
1714
- mBroadPhase->NotifyBodiesAABBChanged(bodies_to_update_bounds, num_bodies_to_update_bounds, false);
1715
- num_bodies_to_update_bounds = 0;
1716
- }
1717
- }
1718
-
1719
- // We did not create a CCD body
1720
- ioStep->mActiveBodyToCCDBody[active_body_idx] = -1;
1721
- }
1722
-
1723
- active_body_idx++;
1724
- }
1725
- }
1726
-
1727
- // Notify change bounds on requested bodies
1728
- if (num_bodies_to_update_bounds > 0)
1729
- mBroadPhase->NotifyBodiesAABBChanged(bodies_to_update_bounds, num_bodies_to_update_bounds, false);
1730
- }
1731
-
1732
- void PhysicsSystem::JobPostIntegrateVelocity(PhysicsUpdateContext *ioContext, PhysicsUpdateContext::Step *ioStep) const
1733
- {
1734
- // Validate that our reservations were correct
1735
- JPH_ASSERT(ioStep->mNumCCDBodies <= mBodyManager.GetNumActiveCCDBodies());
1736
-
1737
- if (ioStep->mNumCCDBodies == 0)
1738
- {
1739
- // No continuous collision detection jobs -> kick the next job ourselves
1740
- ioStep->mContactRemovedCallbacks.RemoveDependency();
1741
- }
1742
- else
1743
- {
1744
- // Run the continuous collision detection jobs
1745
- int num_continuous_collision_jobs = min(int(ioStep->mNumCCDBodies + cNumCCDBodiesPerJob - 1) / cNumCCDBodiesPerJob, ioContext->GetMaxConcurrency());
1746
- ioStep->mResolveCCDContacts.AddDependency(num_continuous_collision_jobs);
1747
- ioStep->mContactRemovedCallbacks.AddDependency(num_continuous_collision_jobs - 1); // Already had 1 dependency
1748
- for (int i = 0; i < num_continuous_collision_jobs; ++i)
1749
- {
1750
- JobHandle job = ioContext->mJobSystem->CreateJob("FindCCDContacts", cColorFindCCDContacts, [ioContext, ioStep]()
1751
- {
1752
- ioContext->mPhysicsSystem->JobFindCCDContacts(ioContext, ioStep);
1753
-
1754
- ioStep->mResolveCCDContacts.RemoveDependency();
1755
- ioStep->mContactRemovedCallbacks.RemoveDependency();
1756
- });
1757
- ioContext->mBarrier->AddJob(job);
1758
- }
1759
- }
1760
- }
1761
-
1762
- // Helper function to calculate the motion of a body during this CCD step
1763
- inline static Vec3 sCalculateBodyMotion(const Body &inBody, float inDeltaTime)
1764
- {
1765
- // If the body is linear casting, the body has not yet moved so we need to calculate its motion
1766
- if (inBody.IsDynamic() && inBody.GetMotionProperties()->GetMotionQuality() == EMotionQuality::LinearCast)
1767
- return inDeltaTime * inBody.GetLinearVelocity();
1768
-
1769
- // Body has already moved, so we don't need to correct for anything
1770
- return Vec3::sZero();
1771
- }
1772
-
1773
- // Helper function that finds the CCD body corresponding to a body (if it exists)
1774
- inline static PhysicsUpdateContext::Step::CCDBody *sGetCCDBody(const Body &inBody, PhysicsUpdateContext::Step *inStep)
1775
- {
1776
- // Only rigid bodies can have a CCD body
1777
- if (!inBody.IsRigidBody())
1778
- return nullptr;
1779
-
1780
- // If the body has no motion properties it cannot have a CCD body
1781
- const MotionProperties *motion_properties = inBody.GetMotionPropertiesUnchecked();
1782
- if (motion_properties == nullptr)
1783
- return nullptr;
1784
-
1785
- // If it is not active it cannot have a CCD body
1786
- uint32 active_index = motion_properties->GetIndexInActiveBodiesInternal();
1787
- if (active_index == Body::cInactiveIndex)
1788
- return nullptr;
1789
-
1790
- // Check if the active body has a corresponding CCD body
1791
- JPH_ASSERT(active_index < inStep->mNumActiveBodyToCCDBody); // Ensure that the body has a mapping to CCD body
1792
- int ccd_index = inStep->mActiveBodyToCCDBody[active_index];
1793
- if (ccd_index < 0)
1794
- return nullptr;
1795
-
1796
- PhysicsUpdateContext::Step::CCDBody *ccd_body = &inStep->mCCDBodies[ccd_index];
1797
- JPH_ASSERT(ccd_body->mBodyID1 == inBody.GetID(), "We found the wrong CCD body!");
1798
- return ccd_body;
1799
- }
1800
-
1801
- void PhysicsSystem::JobFindCCDContacts(const PhysicsUpdateContext *ioContext, PhysicsUpdateContext::Step *ioStep)
1802
- {
1803
- #ifdef JPH_ENABLE_ASSERTS
1804
- // We only read positions, but the validate callback may read body positions and velocities
1805
- BodyAccess::Grant grant(BodyAccess::EAccess::Read, BodyAccess::EAccess::Read);
1806
- #endif
1807
-
1808
- // Allocation context for allocating new contact points
1809
- ContactAllocator contact_allocator(mContactManager.GetContactAllocator());
1810
-
1811
- // Settings
1812
- ShapeCastSettings settings;
1813
- settings.mUseShrunkenShapeAndConvexRadius = true;
1814
- settings.mBackFaceModeTriangles = EBackFaceMode::IgnoreBackFaces;
1815
- settings.mBackFaceModeConvex = EBackFaceMode::IgnoreBackFaces;
1816
- settings.mReturnDeepestPoint = true;
1817
- settings.mCollectFacesMode = ECollectFacesMode::CollectFaces;
1818
- settings.mActiveEdgeMode = mPhysicsSettings.mCheckActiveEdges? EActiveEdgeMode::CollideOnlyWithActive : EActiveEdgeMode::CollideWithAll;
1819
-
1820
- for (;;)
1821
- {
1822
- // Fetch the next body to cast
1823
- uint32 idx = ioStep->mNextCCDBody++;
1824
- if (idx >= ioStep->mNumCCDBodies)
1825
- break;
1826
- CCDBody &ccd_body = ioStep->mCCDBodies[idx];
1827
- const Body &body = mBodyManager.GetBody(ccd_body.mBodyID1);
1828
-
1829
- // Filter out layers
1830
- DefaultBroadPhaseLayerFilter broadphase_layer_filter = GetDefaultBroadPhaseLayerFilter(body.GetObjectLayer());
1831
- DefaultObjectLayerFilter object_layer_filter = GetDefaultLayerFilter(body.GetObjectLayer());
1832
-
1833
- #ifdef JPH_DEBUG_RENDERER
1834
- // Draw start and end shape of cast
1835
- if (sDrawMotionQualityLinearCast)
1836
- {
1837
- RMat44 com = body.GetCenterOfMassTransform();
1838
- body.GetShape()->Draw(DebugRenderer::sInstance, com, Vec3::sOne(), Color::sGreen, false, true);
1839
- DebugRenderer::sInstance->DrawArrow(com.GetTranslation(), com.GetTranslation() + ccd_body.mDeltaPosition, Color::sGreen, 0.1f);
1840
- body.GetShape()->Draw(DebugRenderer::sInstance, com.PostTranslated(ccd_body.mDeltaPosition), Vec3::sOne(), Color::sRed, false, true);
1841
- }
1842
- #endif // JPH_DEBUG_RENDERER
1843
-
1844
- // Create a collector that will find the maximum distance allowed to travel while not penetrating more than 'max penetration'
1845
- class CCDNarrowPhaseCollector : public CastShapeCollector
1846
- {
1847
- public:
1848
- CCDNarrowPhaseCollector(const BodyManager &inBodyManager, ContactConstraintManager &inContactConstraintManager, CCDBody &inCCDBody, ShapeCastResult &inResult, float inDeltaTime) :
1849
- mBodyManager(inBodyManager),
1850
- mContactConstraintManager(inContactConstraintManager),
1851
- mCCDBody(inCCDBody),
1852
- mResult(inResult),
1853
- mDeltaTime(inDeltaTime)
1854
- {
1855
- }
1856
-
1857
- virtual void AddHit(const ShapeCastResult &inResult) override
1858
- {
1859
- JPH_PROFILE_FUNCTION();
1860
-
1861
- // Check if this is a possible earlier hit than the one before
1862
- float fraction = inResult.mFraction;
1863
- if (fraction < mCCDBody.mFractionPlusSlop)
1864
- {
1865
- // Normalize normal
1866
- Vec3 normal = inResult.mPenetrationAxis.Normalized();
1867
-
1868
- // Calculate how much we can add to the fraction to penetrate the collision point by mMaxPenetration.
1869
- // Note that the normal is pointing towards body 2!
1870
- // Let the extra distance that we can travel along delta_pos be 'dist': mMaxPenetration / dist = cos(angle between normal and delta_pos) = normal . delta_pos / |delta_pos|
1871
- // <=> dist = mMaxPenetration * |delta_pos| / normal . delta_pos
1872
- // Converting to a faction: delta_fraction = dist / |delta_pos| = mLinearCastTreshold / normal . delta_pos
1873
- float denominator = normal.Dot(mCCDBody.mDeltaPosition);
1874
- if (denominator > mCCDBody.mMaxPenetration) // Avoid dividing by zero, if extra hit fraction > 1 there's also no point in continuing
1875
- {
1876
- float fraction_plus_slop = fraction + mCCDBody.mMaxPenetration / denominator;
1877
- if (fraction_plus_slop < mCCDBody.mFractionPlusSlop)
1878
- {
1879
- const Body &body2 = mBodyManager.GetBody(inResult.mBodyID2);
1880
-
1881
- // Check if we've already accepted all hits from this body
1882
- if (mValidateBodyPair)
1883
- {
1884
- // Validate the contact result
1885
- const Body &body1 = mBodyManager.GetBody(mCCDBody.mBodyID1);
1886
- ValidateResult validate_result = mContactConstraintManager.ValidateContactPoint(body1, body2, body1.GetCenterOfMassPosition(), inResult); // Note that the center of mass of body 1 is the start of the sweep and is used as base offset below
1887
- switch (validate_result)
1888
- {
1889
- case ValidateResult::AcceptContact:
1890
- // Just continue
1891
- break;
1892
-
1893
- case ValidateResult::AcceptAllContactsForThisBodyPair:
1894
- // Accept this and all following contacts from this body
1895
- mValidateBodyPair = false;
1896
- break;
1897
-
1898
- case ValidateResult::RejectContact:
1899
- return;
1900
-
1901
- case ValidateResult::RejectAllContactsForThisBodyPair:
1902
- // Reject this and all following contacts from this body
1903
- mRejectAll = true;
1904
- ForceEarlyOut();
1905
- return;
1906
- }
1907
- }
1908
-
1909
- // This is the earliest hit so far, store it
1910
- mCCDBody.mContactNormal = normal;
1911
- mCCDBody.mBodyID2 = inResult.mBodyID2;
1912
- mCCDBody.mSubShapeID2 = inResult.mSubShapeID2;
1913
- mCCDBody.mFraction = fraction;
1914
- mCCDBody.mFractionPlusSlop = fraction_plus_slop;
1915
- mResult = inResult;
1916
-
1917
- // Result was assuming body 2 is not moving, but it is, so we need to correct for it
1918
- Vec3 movement2 = fraction * sCalculateBodyMotion(body2, mDeltaTime);
1919
- if (!movement2.IsNearZero())
1920
- {
1921
- mResult.mContactPointOn1 += movement2;
1922
- mResult.mContactPointOn2 += movement2;
1923
- for (Vec3 &v : mResult.mShape1Face)
1924
- v += movement2;
1925
- for (Vec3 &v : mResult.mShape2Face)
1926
- v += movement2;
1927
- }
1928
-
1929
- // Update early out fraction
1930
- UpdateEarlyOutFraction(fraction_plus_slop);
1931
- }
1932
- }
1933
- }
1934
- }
1935
-
1936
- bool mValidateBodyPair; ///< If we still have to call the ValidateContactPoint for this body pair
1937
- bool mRejectAll; ///< Reject all further contacts between this body pair
1938
-
1939
- private:
1940
- const BodyManager & mBodyManager;
1941
- ContactConstraintManager & mContactConstraintManager;
1942
- CCDBody & mCCDBody;
1943
- ShapeCastResult & mResult;
1944
- float mDeltaTime;
1945
- BodyID mAcceptedBodyID;
1946
- };
1947
-
1948
- // Narrowphase collector
1949
- ShapeCastResult cast_shape_result;
1950
- CCDNarrowPhaseCollector np_collector(mBodyManager, mContactManager, ccd_body, cast_shape_result, ioContext->mStepDeltaTime);
1951
-
1952
- // This collector wraps the narrowphase collector and collects the closest hit
1953
- class CCDBroadPhaseCollector : public CastShapeBodyCollector
1954
- {
1955
- public:
1956
- CCDBroadPhaseCollector(const CCDBody &inCCDBody, const Body &inBody1, const RShapeCast &inShapeCast, ShapeCastSettings &inShapeCastSettings, SimShapeFilterWrapper &inShapeFilter, CCDNarrowPhaseCollector &ioCollector, const BodyManager &inBodyManager, PhysicsUpdateContext::Step *inStep, float inDeltaTime) :
1957
- mCCDBody(inCCDBody),
1958
- mBody1(inBody1),
1959
- mBody1Extent(inShapeCast.mShapeWorldBounds.GetExtent()),
1960
- mShapeCast(inShapeCast),
1961
- mShapeCastSettings(inShapeCastSettings),
1962
- mShapeFilter(inShapeFilter),
1963
- mCollector(ioCollector),
1964
- mBodyManager(inBodyManager),
1965
- mStep(inStep),
1966
- mDeltaTime(inDeltaTime)
1967
- {
1968
- }
1969
-
1970
- virtual void AddHit(const BroadPhaseCastResult &inResult) override
1971
- {
1972
- JPH_PROFILE_FUNCTION();
1973
-
1974
- JPH_ASSERT(inResult.mFraction <= GetEarlyOutFraction(), "This hit should not have been passed on to the collector");
1975
-
1976
- // Test if we're colliding with ourselves
1977
- if (mBody1.GetID() == inResult.mBodyID)
1978
- return;
1979
-
1980
- // Avoid treating duplicates, if both bodies are doing CCD then only consider collision if body ID < other body ID
1981
- const Body &body2 = mBodyManager.GetBody(inResult.mBodyID);
1982
- const CCDBody *ccd_body2 = sGetCCDBody(body2, mStep);
1983
- if (ccd_body2 != nullptr && mCCDBody.mBodyID1 > ccd_body2->mBodyID1)
1984
- return;
1985
-
1986
- // Test group filter
1987
- if (!mBody1.GetCollisionGroup().CanCollide(body2.GetCollisionGroup()))
1988
- return;
1989
-
1990
- // TODO: For now we ignore sensors
1991
- if (body2.IsSensor())
1992
- return;
1993
-
1994
- // Get relative movement of these two bodies
1995
- Vec3 direction = mShapeCast.mDirection - sCalculateBodyMotion(body2, mDeltaTime);
1996
-
1997
- // Test if the remaining movement is less than our movement threshold
1998
- if (direction.LengthSq() < mCCDBody.mLinearCastThresholdSq)
1999
- return;
2000
-
2001
- // Get the bounds of 2, widen it by the extent of 1 and test a ray to see if it hits earlier than the current early out fraction
2002
- AABox bounds = body2.GetWorldSpaceBounds();
2003
- bounds.mMin -= mBody1Extent;
2004
- bounds.mMax += mBody1Extent;
2005
- float hit_fraction = RayAABox(Vec3(mShapeCast.mCenterOfMassStart.GetTranslation()), RayInvDirection(direction), bounds.mMin, bounds.mMax);
2006
- if (hit_fraction > GetPositiveEarlyOutFraction()) // If early out fraction <= 0, we have the possibility of finding a deeper hit so we need to clamp the early out fraction
2007
- return;
2008
-
2009
- // Reset collector (this is a new body pair)
2010
- mCollector.ResetEarlyOutFraction(GetEarlyOutFraction());
2011
- mCollector.mValidateBodyPair = true;
2012
- mCollector.mRejectAll = false;
2013
-
2014
- // Set body ID on shape filter
2015
- mShapeFilter.SetBody2(&body2);
2016
-
2017
- // Provide direction as hint for the active edges algorithm
2018
- mShapeCastSettings.mActiveEdgeMovementDirection = direction;
2019
-
2020
- // Do narrow phase collision check
2021
- RShapeCast relative_cast(mShapeCast.mShape, mShapeCast.mScale, mShapeCast.mCenterOfMassStart, direction, mShapeCast.mShapeWorldBounds);
2022
- body2.GetTransformedShape().CastShape(relative_cast, mShapeCastSettings, mShapeCast.mCenterOfMassStart.GetTranslation(), mCollector, mShapeFilter.GetFilter());
2023
-
2024
- // Update early out fraction based on narrow phase collector
2025
- if (!mCollector.mRejectAll)
2026
- UpdateEarlyOutFraction(mCollector.GetEarlyOutFraction());
2027
- }
2028
-
2029
- const CCDBody & mCCDBody;
2030
- const Body & mBody1;
2031
- Vec3 mBody1Extent;
2032
- RShapeCast mShapeCast;
2033
- ShapeCastSettings & mShapeCastSettings;
2034
- SimShapeFilterWrapper & mShapeFilter;
2035
- CCDNarrowPhaseCollector & mCollector;
2036
- const BodyManager & mBodyManager;
2037
- PhysicsUpdateContext::Step *mStep;
2038
- float mDeltaTime;
2039
- };
2040
-
2041
- // Create shape filter
2042
- SimShapeFilterWrapper shape_filter(mSimShapeFilter, &body);
2043
-
2044
- #ifdef JPH_TRACK_SIMULATION_STATS
2045
- uint64 start_tick = GetProcessorTickCount();
2046
- #endif
2047
-
2048
- // Check if we collide with any other body. Note that we use the non-locking interface as we know the broadphase cannot be modified at this point.
2049
- RShapeCast shape_cast(body.GetShape(), Vec3::sOne(), body.GetCenterOfMassTransform(), ccd_body.mDeltaPosition);
2050
- CCDBroadPhaseCollector bp_collector(ccd_body, body, shape_cast, settings, shape_filter, np_collector, mBodyManager, ioStep, ioContext->mStepDeltaTime);
2051
- mBroadPhase->CastAABoxNoLock({ shape_cast.mShapeWorldBounds, shape_cast.mDirection }, bp_collector, broadphase_layer_filter, object_layer_filter);
2052
-
2053
- #ifdef JPH_TRACK_SIMULATION_STATS
2054
- uint64 num_ticks = GetProcessorTickCount() - start_tick;
2055
- const_cast<MotionProperties::SimulationStats &>(body.GetMotionPropertiesUnchecked()->GetSimulationStats()).mCCDTicks.fetch_add(num_ticks, memory_order_relaxed);
2056
- #endif
2057
-
2058
- // Check if there was a hit
2059
- if (ccd_body.mFractionPlusSlop < 1.0f)
2060
- {
2061
- const Body &body2 = mBodyManager.GetBody(ccd_body.mBodyID2);
2062
-
2063
- // Determine contact manifold
2064
- ContactManifold manifold;
2065
- manifold.mBaseOffset = shape_cast.mCenterOfMassStart.GetTranslation();
2066
- ManifoldBetweenTwoFaces(cast_shape_result.mContactPointOn1, cast_shape_result.mContactPointOn2, cast_shape_result.mPenetrationAxis, mPhysicsSettings.mManifoldTolerance, cast_shape_result.mShape1Face, cast_shape_result.mShape2Face, manifold.mRelativeContactPointsOn1, manifold.mRelativeContactPointsOn2 JPH_IF_DEBUG_RENDERER(, manifold.mBaseOffset));
2067
- manifold.mSubShapeID1 = cast_shape_result.mSubShapeID1;
2068
- manifold.mSubShapeID2 = cast_shape_result.mSubShapeID2;
2069
- manifold.mPenetrationDepth = cast_shape_result.mPenetrationDepth;
2070
- manifold.mWorldSpaceNormal = ccd_body.mContactNormal;
2071
-
2072
- // Call contact point callbacks
2073
- mContactManager.OnCCDContactAdded(contact_allocator, body, body2, manifold, ccd_body.mContactSettings);
2074
-
2075
- if (ccd_body.mContactSettings.mIsSensor)
2076
- {
2077
- // If this is a sensor, we don't want to solve the contact
2078
- ccd_body.mFractionPlusSlop = 1.0f;
2079
- ccd_body.mBodyID2 = BodyID();
2080
- }
2081
- else
2082
- {
2083
- // Calculate the average position from the manifold (this will result in the same impulse applied as when we apply impulses to all contact points)
2084
- if (manifold.mRelativeContactPointsOn2.size() > 1)
2085
- {
2086
- Vec3 average_contact_point = Vec3::sZero();
2087
- for (const Vec3 &v : manifold.mRelativeContactPointsOn2)
2088
- average_contact_point += v;
2089
- average_contact_point /= (float)manifold.mRelativeContactPointsOn2.size();
2090
- ccd_body.mContactPointOn2 = manifold.mBaseOffset + average_contact_point;
2091
- }
2092
- else
2093
- ccd_body.mContactPointOn2 = manifold.mBaseOffset + cast_shape_result.mContactPointOn2;
2094
- }
2095
- }
2096
- }
2097
-
2098
- // Collect information from the contact allocator and accumulate it in the step.
2099
- sFinalizeContactAllocator(*ioStep, contact_allocator);
2100
- }
2101
-
2102
- void PhysicsSystem::JobResolveCCDContacts(PhysicsUpdateContext *ioContext, PhysicsUpdateContext::Step *ioStep)
2103
- {
2104
- #ifdef JPH_ENABLE_ASSERTS
2105
- // Read/write body access
2106
- BodyAccess::Grant grant(BodyAccess::EAccess::ReadWrite, BodyAccess::EAccess::ReadWrite);
2107
-
2108
- // We activate bodies that we collide with
2109
- BodyManager::GrantActiveBodiesAccess grant_active(true, false);
2110
- #endif
2111
-
2112
- uint32 num_active_bodies_after_find_collisions = ioStep->mActiveBodyReadIdx;
2113
- TempAllocator *temp_allocator = ioContext->mTempAllocator;
2114
-
2115
- // Check if there's anything to do
2116
- uint num_ccd_bodies = ioStep->mNumCCDBodies;
2117
- if (num_ccd_bodies > 0)
2118
- {
2119
- // Sort on fraction so that we process earliest collisions first
2120
- // This is needed to make the simulation deterministic and also to be able to stop contact processing
2121
- // between body pairs if an earlier hit was found involving the body by another CCD body
2122
- // (if it's body ID < this CCD body's body ID - see filtering logic in CCDBroadPhaseCollector)
2123
- CCDBody **sorted_ccd_bodies = (CCDBody **)temp_allocator->Allocate(num_ccd_bodies * sizeof(CCDBody *));
2124
- JPH_SCOPE_EXIT([temp_allocator, sorted_ccd_bodies, num_ccd_bodies]{ temp_allocator->Free(sorted_ccd_bodies, num_ccd_bodies * sizeof(CCDBody *)); });
2125
- {
2126
- JPH_PROFILE("Sort");
2127
-
2128
- // We don't want to copy the entire struct (it's quite big), so we create a pointer array first
2129
- CCDBody *src_ccd_bodies = ioStep->mCCDBodies;
2130
- CCDBody **dst_ccd_bodies = sorted_ccd_bodies;
2131
- CCDBody **dst_ccd_bodies_end = dst_ccd_bodies + num_ccd_bodies;
2132
- while (dst_ccd_bodies < dst_ccd_bodies_end)
2133
- *(dst_ccd_bodies++) = src_ccd_bodies++;
2134
-
2135
- // Which we then sort
2136
- QuickSort(sorted_ccd_bodies, sorted_ccd_bodies + num_ccd_bodies, [](const CCDBody *inBody1, const CCDBody *inBody2)
2137
- {
2138
- if (inBody1->mFractionPlusSlop != inBody2->mFractionPlusSlop)
2139
- return inBody1->mFractionPlusSlop < inBody2->mFractionPlusSlop;
2140
-
2141
- return inBody1->mBodyID1 < inBody2->mBodyID1;
2142
- });
2143
- }
2144
-
2145
- // We can collide with bodies that are not active, we track them here so we can activate them in one go at the end.
2146
- // This is also needed because we can't modify the active body array while we iterate it.
2147
- static constexpr int cBodiesBatch = 64;
2148
- BodyID *bodies_to_activate = (BodyID *)JPH_STACK_ALLOC(cBodiesBatch * sizeof(BodyID));
2149
- int num_bodies_to_activate = 0;
2150
-
2151
- // We can move bodies that are not part of an island. In this case we need to notify the broadphase of the movement.
2152
- BodyID *bodies_to_update_bounds = (BodyID *)JPH_STACK_ALLOC(cBodiesBatch * sizeof(BodyID));
2153
- int num_bodies_to_update_bounds = 0;
2154
-
2155
- for (uint i = 0; i < num_ccd_bodies; ++i)
2156
- {
2157
- const CCDBody *ccd_body = sorted_ccd_bodies[i];
2158
- Body &body1 = mBodyManager.GetBody(ccd_body->mBodyID1);
2159
- MotionProperties *body_mp = body1.GetMotionProperties();
2160
-
2161
- // If there was a hit
2162
- if (!ccd_body->mBodyID2.IsInvalid())
2163
- {
2164
- Body &body2 = mBodyManager.GetBody(ccd_body->mBodyID2);
2165
-
2166
- // Determine if the other body has a CCD body
2167
- CCDBody *ccd_body2 = sGetCCDBody(body2, ioStep);
2168
- if (ccd_body2 != nullptr)
2169
- {
2170
- JPH_ASSERT(ccd_body2->mBodyID2 != ccd_body->mBodyID1, "If we collided with another body, that other body should have ignored collisions with us!");
2171
-
2172
- // Check if the other body found a hit that is further away
2173
- if (ccd_body2->mFraction > ccd_body->mFraction)
2174
- {
2175
- // Reset the colliding body of the other CCD body. The other body will shorten its distance traveled and will not do any collision response (we'll do that).
2176
- // This means that at this point we have triggered a contact point add/persist for our further hit by accident for the other body.
2177
- // We accept this as calling the contact point callbacks here would require persisting the manifolds up to this point and doing the callbacks single threaded.
2178
- ccd_body2->mBodyID2 = BodyID();
2179
- ccd_body2->mFractionPlusSlop = ccd_body->mFraction;
2180
- }
2181
- }
2182
-
2183
- // If the other body moved less than us before hitting something, we're not colliding with it so we again have triggered contact point add/persist callbacks by accident.
2184
- // We'll just move to the collision position anyway (as that's the last position we know is good), but we won't do any collision response.
2185
- if (ccd_body2 == nullptr || ccd_body2->mFraction >= ccd_body->mFraction)
2186
- {
2187
- const ContactSettings &contact_settings = ccd_body->mContactSettings;
2188
-
2189
- // Calculate contact point velocity for body 1
2190
- Vec3 r1_plus_u = Vec3(ccd_body->mContactPointOn2 - (body1.GetCenterOfMassPosition() + ccd_body->mFraction * ccd_body->mDeltaPosition));
2191
- Vec3 v1 = body1.GetPointVelocityCOM(r1_plus_u);
2192
-
2193
- // Calculate inverse mass for body 1
2194
- float inv_m1 = contact_settings.mInvMassScale1 * body_mp->GetInverseMass();
2195
-
2196
- if (body2.IsRigidBody())
2197
- {
2198
- // Calculate contact point velocity for body 2
2199
- Vec3 r2 = Vec3(ccd_body->mContactPointOn2 - body2.GetCenterOfMassPosition());
2200
- Vec3 v2 = body2.GetPointVelocityCOM(r2);
2201
-
2202
- // Calculate relative contact velocity
2203
- Vec3 relative_velocity = v2 - v1;
2204
- float normal_velocity = relative_velocity.Dot(ccd_body->mContactNormal);
2205
-
2206
- // Calculate velocity bias due to restitution
2207
- float normal_velocity_bias;
2208
- if (contact_settings.mCombinedRestitution > 0.0f && normal_velocity < -mPhysicsSettings.mMinVelocityForRestitution)
2209
- normal_velocity_bias = contact_settings.mCombinedRestitution * normal_velocity;
2210
- else
2211
- normal_velocity_bias = 0.0f;
2212
-
2213
- // Get inverse mass of body 2
2214
- float inv_m2 = body2.GetMotionPropertiesUnchecked() != nullptr? contact_settings.mInvMassScale2 * body2.GetMotionPropertiesUnchecked()->GetInverseMassUnchecked() : 0.0f;
2215
-
2216
- // Solve contact constraint
2217
- AxisConstraintPart contact_constraint;
2218
- contact_constraint.CalculateConstraintPropertiesWithMassOverride(body1, inv_m1, contact_settings.mInvInertiaScale1, r1_plus_u, body2, inv_m2, contact_settings.mInvInertiaScale2, r2, ccd_body->mContactNormal, normal_velocity_bias);
2219
- contact_constraint.SolveVelocityConstraintWithMassOverride(body1, inv_m1, body2, inv_m2, ccd_body->mContactNormal, -FLT_MAX, FLT_MAX);
2220
-
2221
- // Apply friction
2222
- if (contact_settings.mCombinedFriction > 0.0f)
2223
- {
2224
- // Calculate friction direction by removing normal velocity from the relative velocity
2225
- Vec3 friction_direction = relative_velocity - normal_velocity * ccd_body->mContactNormal;
2226
- float friction_direction_len_sq = friction_direction.LengthSq();
2227
- if (friction_direction_len_sq > 1.0e-12f)
2228
- {
2229
- // Normalize friction direction
2230
- friction_direction /= sqrt(friction_direction_len_sq);
2231
-
2232
- // Calculate max friction impulse
2233
- float max_lambda_f = contact_settings.mCombinedFriction * contact_constraint.GetTotalLambda();
2234
-
2235
- AxisConstraintPart friction;
2236
- friction.CalculateConstraintPropertiesWithMassOverride(body1, inv_m1, contact_settings.mInvInertiaScale1, r1_plus_u, body2, inv_m2, contact_settings.mInvInertiaScale2, r2, friction_direction);
2237
- friction.SolveVelocityConstraintWithMassOverride(body1, inv_m1, body2, inv_m2, friction_direction, -max_lambda_f, max_lambda_f);
2238
- }
2239
- }
2240
-
2241
- // Clamp velocity of body 2
2242
- if (body2.IsDynamic())
2243
- {
2244
- MotionProperties *body2_mp = body2.GetMotionProperties();
2245
- body2_mp->ClampLinearVelocity();
2246
- body2_mp->ClampAngularVelocity();
2247
- }
2248
- }
2249
- else
2250
- {
2251
- SoftBodyMotionProperties *soft_mp = static_cast<SoftBodyMotionProperties *>(body2.GetMotionProperties());
2252
- const SoftBodyShape *soft_shape = static_cast<const SoftBodyShape *>(body2.GetShape());
2253
-
2254
- // Convert the sub shape ID of the soft body to a face
2255
- uint32 face_idx = soft_shape->GetFaceIndex(ccd_body->mSubShapeID2);
2256
- const SoftBodyMotionProperties::Face &face = soft_mp->GetFace(face_idx);
2257
-
2258
- // Get vertices of the face
2259
- SoftBodyMotionProperties::Vertex &vtx0 = soft_mp->GetVertex(face.mVertex[0]);
2260
- SoftBodyMotionProperties::Vertex &vtx1 = soft_mp->GetVertex(face.mVertex[1]);
2261
- SoftBodyMotionProperties::Vertex &vtx2 = soft_mp->GetVertex(face.mVertex[2]);
2262
-
2263
- // Inverse mass of the face
2264
- float vtx0_mass = vtx0.mInvMass > 0.0f? 1.0f / vtx0.mInvMass : 1.0e10f;
2265
- float vtx1_mass = vtx1.mInvMass > 0.0f? 1.0f / vtx1.mInvMass : 1.0e10f;
2266
- float vtx2_mass = vtx2.mInvMass > 0.0f? 1.0f / vtx2.mInvMass : 1.0e10f;
2267
- float inv_m2 = 1.0f / (vtx0_mass + vtx1_mass + vtx2_mass);
2268
-
2269
- // Calculate barycentric coordinates of the contact point on the soft body's face
2270
- float u, v, w;
2271
- RMat44 inv_body2_transform = body2.GetInverseCenterOfMassTransform();
2272
- Vec3 local_contact = Vec3(inv_body2_transform * ccd_body->mContactPointOn2);
2273
- ClosestPoint::GetBaryCentricCoordinates(vtx0.mPosition - local_contact, vtx1.mPosition - local_contact, vtx2.mPosition - local_contact, u, v, w);
2274
-
2275
- // Calculate contact point velocity for the face
2276
- Vec3 v2 = inv_body2_transform.Multiply3x3Transposed(u * vtx0.mVelocity + v * vtx1.mVelocity + w * vtx2.mVelocity);
2277
- float normal_velocity = (v2 - v1).Dot(ccd_body->mContactNormal);
2278
-
2279
- // Calculate velocity bias due to restitution
2280
- float normal_velocity_bias;
2281
- if (contact_settings.mCombinedRestitution > 0.0f && normal_velocity < -mPhysicsSettings.mMinVelocityForRestitution)
2282
- normal_velocity_bias = contact_settings.mCombinedRestitution * normal_velocity;
2283
- else
2284
- normal_velocity_bias = 0.0f;
2285
-
2286
- // Calculate resulting velocity change (the math here is similar to AxisConstraintPart but without an inertia term for body 2 as we treat it as a point mass)
2287
- Vec3 r1_plus_u_x_n = r1_plus_u.Cross(ccd_body->mContactNormal);
2288
- Vec3 invi1_r1_plus_u_x_n = contact_settings.mInvInertiaScale1 * body1.GetInverseInertia().Multiply3x3(r1_plus_u_x_n);
2289
- float jv = r1_plus_u_x_n.Dot(body_mp->GetAngularVelocity()) - normal_velocity - normal_velocity_bias;
2290
- float inv_effective_mass = inv_m1 + inv_m2 + invi1_r1_plus_u_x_n.Dot(r1_plus_u_x_n);
2291
- float lambda = jv / inv_effective_mass;
2292
- body_mp->SubLinearVelocityStep((lambda * inv_m1) * ccd_body->mContactNormal);
2293
- body_mp->SubAngularVelocityStep(lambda * invi1_r1_plus_u_x_n);
2294
- Vec3 delta_v2 = inv_body2_transform.Multiply3x3(lambda * ccd_body->mContactNormal);
2295
- vtx0.mVelocity += delta_v2 * vtx0.mInvMass;
2296
- vtx1.mVelocity += delta_v2 * vtx1.mInvMass;
2297
- vtx2.mVelocity += delta_v2 * vtx2.mInvMass;
2298
- }
2299
-
2300
- // Clamp velocity of body 1
2301
- body_mp->ClampLinearVelocity();
2302
- body_mp->ClampAngularVelocity();
2303
-
2304
- // Activate the 2nd body if it is not already active
2305
- if (body2.IsDynamic() && !body2.IsActive())
2306
- {
2307
- bodies_to_activate[num_bodies_to_activate++] = ccd_body->mBodyID2;
2308
- if (num_bodies_to_activate == cBodiesBatch)
2309
- {
2310
- // Batch is full, activate now
2311
- mBodyManager.ActivateBodies(bodies_to_activate, num_bodies_to_activate);
2312
- num_bodies_to_activate = 0;
2313
- }
2314
- }
2315
-
2316
- #ifdef JPH_DEBUG_RENDERER
2317
- if (sDrawMotionQualityLinearCast)
2318
- {
2319
- // Draw the collision location
2320
- RMat44 collision_transform = body1.GetCenterOfMassTransform().PostTranslated(ccd_body->mFraction * ccd_body->mDeltaPosition);
2321
- body1.GetShape()->Draw(DebugRenderer::sInstance, collision_transform, Vec3::sOne(), Color::sYellow, false, true);
2322
-
2323
- // Draw the collision location + slop
2324
- RMat44 collision_transform_plus_slop = body1.GetCenterOfMassTransform().PostTranslated(ccd_body->mFractionPlusSlop * ccd_body->mDeltaPosition);
2325
- body1.GetShape()->Draw(DebugRenderer::sInstance, collision_transform_plus_slop, Vec3::sOne(), Color::sOrange, false, true);
2326
-
2327
- // Draw contact normal
2328
- DebugRenderer::sInstance->DrawArrow(ccd_body->mContactPointOn2, ccd_body->mContactPointOn2 - ccd_body->mContactNormal, Color::sYellow, 0.1f);
2329
-
2330
- // Draw post contact velocity
2331
- DebugRenderer::sInstance->DrawArrow(collision_transform.GetTranslation(), collision_transform.GetTranslation() + body1.GetLinearVelocity(), Color::sOrange, 0.1f);
2332
- DebugRenderer::sInstance->DrawArrow(collision_transform.GetTranslation(), collision_transform.GetTranslation() + body1.GetAngularVelocity(), Color::sPurple, 0.1f);
2333
- }
2334
- #endif // JPH_DEBUG_RENDERER
2335
- }
2336
- }
2337
-
2338
- // Update body position
2339
- body1.AddPositionStep(ccd_body->mDeltaPosition * ccd_body->mFractionPlusSlop);
2340
-
2341
- // If the body was activated due to an earlier CCD step it will have an index in the active
2342
- // body list that it higher than the highest one we processed during FindCollisions
2343
- // which means it hasn't been assigned an island and will not be updated by an island
2344
- // this means that we need to update its bounds manually
2345
- if (body_mp->GetIndexInActiveBodiesInternal() >= num_active_bodies_after_find_collisions)
2346
- {
2347
- body1.CalculateWorldSpaceBoundsInternal();
2348
- bodies_to_update_bounds[num_bodies_to_update_bounds++] = body1.GetID();
2349
- if (num_bodies_to_update_bounds == cBodiesBatch)
2350
- {
2351
- // Buffer full, flush now
2352
- mBroadPhase->NotifyBodiesAABBChanged(bodies_to_update_bounds, num_bodies_to_update_bounds, false);
2353
- num_bodies_to_update_bounds = 0;
2354
- }
2355
- }
2356
- }
2357
-
2358
- // Activate the requested bodies
2359
- if (num_bodies_to_activate > 0)
2360
- mBodyManager.ActivateBodies(bodies_to_activate, num_bodies_to_activate);
2361
-
2362
- // Notify change bounds on requested bodies
2363
- if (num_bodies_to_update_bounds > 0)
2364
- mBroadPhase->NotifyBodiesAABBChanged(bodies_to_update_bounds, num_bodies_to_update_bounds, false);
2365
- }
2366
-
2367
- // Ensure we free the CCD bodies array now, will not call the destructor!
2368
- temp_allocator->Free(ioStep->mActiveBodyToCCDBody, ioStep->mNumActiveBodyToCCDBody * sizeof(int));
2369
- ioStep->mActiveBodyToCCDBody = nullptr;
2370
- ioStep->mNumActiveBodyToCCDBody = 0;
2371
- temp_allocator->Free(ioStep->mCCDBodies, ioStep->mCCDBodiesCapacity * sizeof(CCDBody));
2372
- ioStep->mCCDBodies = nullptr;
2373
- ioStep->mCCDBodiesCapacity = 0;
2374
- }
2375
-
2376
- void PhysicsSystem::JobContactRemovedCallbacks(const PhysicsUpdateContext::Step *ioStep)
2377
- {
2378
- #ifdef JPH_ENABLE_ASSERTS
2379
- // We don't touch any bodies
2380
- BodyAccess::Grant grant(BodyAccess::EAccess::None, BodyAccess::EAccess::None);
2381
- #endif
2382
-
2383
- // Reset the Body::EFlags::InvalidateContactCache flag for all bodies
2384
- mBodyManager.ValidateContactCacheForAllBodies();
2385
-
2386
- // Finalize the contact cache (this swaps the read and write versions of the contact cache)
2387
- // Trigger all contact removed callbacks by looking at last step contact points that have not been flagged as reused
2388
- mContactManager.FinalizeContactCacheAndCallContactPointRemovedCallbacks(ioStep->mNumBodyPairs, ioStep->mNumManifolds);
2389
- }
2390
-
2391
- class PhysicsSystem::BodiesToSleep : public NonCopyable
2392
- {
2393
- public:
2394
- static constexpr int cBodiesToSleepSize = 512;
2395
- static constexpr int cMaxBodiesToPutInBuffer = 128;
2396
-
2397
- inline BodiesToSleep(BodyManager &inBodyManager, BodyID *inBodiesToSleepBuffer) : mBodyManager(inBodyManager), mBodiesToSleepBuffer(inBodiesToSleepBuffer), mBodiesToSleepCur(inBodiesToSleepBuffer) { }
2398
-
2399
- inline ~BodiesToSleep()
2400
- {
2401
- // Flush the bodies to sleep buffer
2402
- int num_bodies_in_buffer = int(mBodiesToSleepCur - mBodiesToSleepBuffer);
2403
- if (num_bodies_in_buffer > 0)
2404
- mBodyManager.DeactivateBodies(mBodiesToSleepBuffer, num_bodies_in_buffer);
2405
- }
2406
-
2407
- inline void PutToSleep(const BodyID *inBegin, const BodyID *inEnd)
2408
- {
2409
- int num_bodies_to_sleep = int(inEnd - inBegin);
2410
- if (num_bodies_to_sleep > cMaxBodiesToPutInBuffer)
2411
- {
2412
- // Too many bodies, deactivate immediately
2413
- mBodyManager.DeactivateBodies(inBegin, num_bodies_to_sleep);
2414
- }
2415
- else
2416
- {
2417
- // Check if there's enough space in the bodies to sleep buffer
2418
- int num_bodies_in_buffer = int(mBodiesToSleepCur - mBodiesToSleepBuffer);
2419
- if (num_bodies_in_buffer + num_bodies_to_sleep > cBodiesToSleepSize)
2420
- {
2421
- // Flush the bodies to sleep buffer
2422
- mBodyManager.DeactivateBodies(mBodiesToSleepBuffer, num_bodies_in_buffer);
2423
- mBodiesToSleepCur = mBodiesToSleepBuffer;
2424
- }
2425
-
2426
- // Copy the bodies in the buffer
2427
- memcpy(mBodiesToSleepCur, inBegin, num_bodies_to_sleep * sizeof(BodyID));
2428
- mBodiesToSleepCur += num_bodies_to_sleep;
2429
- }
2430
- }
2431
-
2432
- private:
2433
- BodyManager & mBodyManager;
2434
- BodyID * mBodiesToSleepBuffer;
2435
- BodyID * mBodiesToSleepCur;
2436
- };
2437
-
2438
- void PhysicsSystem::CheckSleepAndUpdateBounds(uint32 inIslandIndex, const PhysicsUpdateContext *ioContext, const PhysicsUpdateContext::Step *ioStep, BodiesToSleep &ioBodiesToSleep)
2439
- {
2440
- // Get the bodies that belong to this island
2441
- BodyID *bodies_begin, *bodies_end;
2442
- mIslandBuilder.GetBodiesInIsland(inIslandIndex, bodies_begin, bodies_end);
2443
-
2444
- // Only check sleeping in the last step
2445
- // Also resets force and torque used during the apply gravity phase
2446
- if (ioStep->mIsLast)
2447
- {
2448
- JPH_PROFILE("Check Sleeping");
2449
-
2450
- static_assert(int(ECanSleep::CannotSleep) == 0 && int(ECanSleep::CanSleep) == 1, "Loop below makes this assumption");
2451
- int all_can_sleep = mPhysicsSettings.mAllowSleeping? int(ECanSleep::CanSleep) : int(ECanSleep::CannotSleep);
2452
-
2453
- float time_before_sleep = mPhysicsSettings.mTimeBeforeSleep;
2454
- float max_movement = mPhysicsSettings.mPointVelocitySleepThreshold * time_before_sleep;
2455
-
2456
- for (const BodyID *body_id = bodies_begin; body_id < bodies_end; ++body_id)
2457
- {
2458
- Body &body = mBodyManager.GetBody(*body_id);
2459
-
2460
- // Update bounding box
2461
- body.CalculateWorldSpaceBoundsInternal();
2462
-
2463
- // Update sleeping
2464
- all_can_sleep &= int(body.UpdateSleepStateInternal(ioContext->mStepDeltaTime, max_movement, time_before_sleep));
2465
-
2466
- // Reset force and torque
2467
- MotionProperties *mp = body.GetMotionProperties();
2468
- mp->ResetForce();
2469
- mp->ResetTorque();
2470
- }
2471
-
2472
- // If all bodies indicate they can sleep we can deactivate them
2473
- if (all_can_sleep == int(ECanSleep::CanSleep))
2474
- ioBodiesToSleep.PutToSleep(bodies_begin, bodies_end);
2475
- }
2476
- else
2477
- {
2478
- JPH_PROFILE("Update Bounds");
2479
-
2480
- // Update bounding box only for all other steps
2481
- for (const BodyID *body_id = bodies_begin; body_id < bodies_end; ++body_id)
2482
- {
2483
- Body &body = mBodyManager.GetBody(*body_id);
2484
- body.CalculateWorldSpaceBoundsInternal();
2485
- }
2486
- }
2487
-
2488
- // Notify broadphase of changed objects (find ccd contacts can do linear casts in the next step, so we need to do this every step)
2489
- // Note: Shuffles the BodyID's around!!!
2490
- mBroadPhase->NotifyBodiesAABBChanged(bodies_begin, int(bodies_end - bodies_begin), false);
2491
- }
2492
-
2493
- void PhysicsSystem::JobSolvePositionConstraints(PhysicsUpdateContext *ioContext, PhysicsUpdateContext::Step *ioStep)
2494
- {
2495
- #ifdef JPH_ENABLE_ASSERTS
2496
- // We fix up position errors
2497
- BodyAccess::Grant grant(BodyAccess::EAccess::None, BodyAccess::EAccess::ReadWrite);
2498
-
2499
- // Can only deactivate bodies
2500
- BodyManager::GrantActiveBodiesAccess grant_active(false, true);
2501
- #endif
2502
-
2503
- float delta_time = ioContext->mStepDeltaTime;
2504
- float baumgarte = mPhysicsSettings.mBaumgarte;
2505
- Constraint **active_constraints = ioContext->mActiveConstraints;
2506
-
2507
- // Keep a buffer of bodies that need to go to sleep in order to not constantly lock the active bodies mutex and create contention between all solving threads
2508
- BodiesToSleep bodies_to_sleep(mBodyManager, (BodyID *)JPH_STACK_ALLOC(BodiesToSleep::cBodiesToSleepSize * sizeof(BodyID)));
2509
-
2510
- bool check_islands = true, check_split_islands = mPhysicsSettings.mUseLargeIslandSplitter;
2511
- for (;;)
2512
- {
2513
- // First try to get work from large islands
2514
- if (check_split_islands)
2515
- {
2516
- bool first_iteration;
2517
- uint split_island_index;
2518
- uint32 *constraints_begin, *constraints_end, *contacts_begin, *contacts_end;
2519
- switch (mLargeIslandSplitter.FetchNextBatch(split_island_index, constraints_begin, constraints_end, contacts_begin, contacts_end, first_iteration))
2520
- {
2521
- case LargeIslandSplitter::EStatus::BatchRetrieved:
2522
- {
2523
- #ifdef JPH_TRACK_SIMULATION_STATS
2524
- uint64 start_tick = GetProcessorTickCount();
2525
- #endif
2526
-
2527
- // Solve the batch
2528
- ConstraintManager::sSolvePositionConstraints(active_constraints, constraints_begin, constraints_end, delta_time, baumgarte);
2529
- mContactManager.SolvePositionConstraints(contacts_begin, contacts_end);
2530
-
2531
- // Mark the batch as processed
2532
- bool last_iteration, final_batch;
2533
- mLargeIslandSplitter.MarkBatchProcessed(split_island_index, constraints_begin, constraints_end, contacts_begin, contacts_end, last_iteration, final_batch);
2534
-
2535
- // The final batch will update all bounds and check sleeping
2536
- if (final_batch)
2537
- CheckSleepAndUpdateBounds(mLargeIslandSplitter.GetIslandIndex(split_island_index), ioContext, ioStep, bodies_to_sleep);
2538
-
2539
- #ifdef JPH_TRACK_SIMULATION_STATS
2540
- uint64 num_ticks = GetProcessorTickCount() - start_tick;
2541
- mIslandBuilder.GetIslandStats(mLargeIslandSplitter.GetIslandIndex(split_island_index)).mPositionConstraintTicks.fetch_add(num_ticks, memory_order_relaxed);
2542
- #endif
2543
-
2544
- // We processed work, loop again
2545
- continue;
2546
- }
2547
-
2548
- case LargeIslandSplitter::EStatus::WaitingForBatch:
2549
- break;
2550
-
2551
- case LargeIslandSplitter::EStatus::AllBatchesDone:
2552
- check_split_islands = false;
2553
- break;
2554
- }
2555
- }
2556
-
2557
- // If that didn't succeed try to process an island
2558
- if (check_islands)
2559
- {
2560
- // Next island
2561
- uint32 island_idx = ioStep->mSolvePositionConstraintsNextIsland++;
2562
- if (island_idx >= mIslandBuilder.GetNumIslands())
2563
- {
2564
- // We processed all islands, stop checking islands
2565
- check_islands = false;
2566
- continue;
2567
- }
2568
-
2569
- JPH_PROFILE("Island");
2570
-
2571
- // Get iterators for this island
2572
- uint32 *constraints_begin, *constraints_end, *contacts_begin, *contacts_end;
2573
- mIslandBuilder.GetConstraintsInIsland(island_idx, constraints_begin, constraints_end);
2574
- mIslandBuilder.GetContactsInIsland(island_idx, contacts_begin, contacts_end);
2575
-
2576
- // If this island is a large island, it will be picked up as a batch and we don't need to do anything here
2577
- uint num_items = uint(constraints_end - constraints_begin) + uint(contacts_end - contacts_begin);
2578
- if (mPhysicsSettings.mUseLargeIslandSplitter
2579
- && num_items >= LargeIslandSplitter::cLargeIslandTreshold)
2580
- continue;
2581
-
2582
- #ifdef JPH_TRACK_SIMULATION_STATS
2583
- uint64 start_tick = GetProcessorTickCount();
2584
- #endif
2585
-
2586
- // Check if this island needs solving
2587
- if (num_items > 0)
2588
- {
2589
- // Iterate
2590
- uint num_position_steps = mIslandBuilder.GetNumPositionSteps(island_idx);
2591
- for (uint position_step = 0; position_step < num_position_steps; ++position_step)
2592
- {
2593
- bool applied_impulse = ConstraintManager::sSolvePositionConstraints(active_constraints, constraints_begin, constraints_end, delta_time, baumgarte);
2594
- applied_impulse |= mContactManager.SolvePositionConstraints(contacts_begin, contacts_end);
2595
- if (!applied_impulse)
2596
- break;
2597
- }
2598
- }
2599
-
2600
- #ifdef JPH_TRACK_SIMULATION_STATS
2601
- // Accumulate time spent in solving position constraints
2602
- uint64 solve_position_ticks = GetProcessorTickCount();
2603
- IslandBuilder::IslandStats &stats = mIslandBuilder.GetIslandStats(island_idx);
2604
- stats.mPositionConstraintTicks.fetch_add(solve_position_ticks - start_tick, memory_order_relaxed);
2605
- #endif
2606
-
2607
- // After solving we will update all bounds and check sleeping
2608
- CheckSleepAndUpdateBounds(island_idx, ioContext, ioStep, bodies_to_sleep);
2609
-
2610
- #ifdef JPH_TRACK_SIMULATION_STATS
2611
- // Accumulate time spent in updating bounding box
2612
- stats.mUpdateBoundsTicks.fetch_add(GetProcessorTickCount() - solve_position_ticks, memory_order_relaxed);
2613
- #endif
2614
-
2615
- // We processed work, loop again
2616
- continue;
2617
- }
2618
-
2619
- if (check_islands)
2620
- {
2621
- // If there are islands, we don't need to wait and can pick up new work
2622
- continue;
2623
- }
2624
- else if (check_split_islands)
2625
- {
2626
- // If there are split islands, but we didn't do any work, give up a time slice
2627
- std::this_thread::yield();
2628
- }
2629
- else
2630
- {
2631
- // No more work
2632
- break;
2633
- }
2634
- }
2635
- }
2636
-
2637
- void PhysicsSystem::JobSoftBodyPrepare(PhysicsUpdateContext *ioContext, PhysicsUpdateContext::Step *ioStep)
2638
- {
2639
- JPH_PROFILE_FUNCTION();
2640
-
2641
- {
2642
- #ifdef JPH_ENABLE_ASSERTS
2643
- // Reading soft body positions
2644
- BodyAccess::Grant grant(BodyAccess::EAccess::None, BodyAccess::EAccess::Read);
2645
- #endif
2646
-
2647
- // Get the active soft bodies
2648
- BodyIDVector active_bodies;
2649
- mBodyManager.GetActiveBodies(EBodyType::SoftBody, active_bodies);
2650
-
2651
- // Quit if there are no active soft bodies
2652
- if (active_bodies.empty())
2653
- {
2654
- // Kick the next step
2655
- if (ioStep->mStartNextStep.IsValid())
2656
- ioStep->mStartNextStep.RemoveDependency();
2657
- return;
2658
- }
2659
-
2660
- // Sort to get a deterministic update order
2661
- QuickSort(active_bodies.begin(), active_bodies.end());
2662
-
2663
- // Allocate soft body contexts
2664
- ioContext->mNumSoftBodies = (uint)active_bodies.size();
2665
- ioContext->mSoftBodyUpdateContexts = (SoftBodyUpdateContext *)ioContext->mTempAllocator->Allocate(ioContext->mNumSoftBodies * sizeof(SoftBodyUpdateContext));
2666
-
2667
- // Initialize soft body contexts
2668
- for (SoftBodyUpdateContext *sb_ctx = ioContext->mSoftBodyUpdateContexts, *sb_ctx_end = ioContext->mSoftBodyUpdateContexts + ioContext->mNumSoftBodies; sb_ctx < sb_ctx_end; ++sb_ctx)
2669
- {
2670
- new (sb_ctx) SoftBodyUpdateContext;
2671
- Body &body = mBodyManager.GetBody(active_bodies[sb_ctx - ioContext->mSoftBodyUpdateContexts]);
2672
- SoftBodyMotionProperties *mp = static_cast<SoftBodyMotionProperties *>(body.GetMotionProperties());
2673
- mp->InitializeUpdateContext(ioContext->mStepDeltaTime, body, *this, *sb_ctx);
2674
- }
2675
- }
2676
-
2677
- // We're ready to collide the first soft body
2678
- ioContext->mSoftBodyToCollide.store(0, memory_order_release);
2679
-
2680
- // Determine number of jobs to spawn
2681
- int num_soft_body_jobs = ioContext->GetMaxConcurrency();
2682
-
2683
- // Create finalize job
2684
- ioStep->mSoftBodyFinalize = ioContext->mJobSystem->CreateJob("SoftBodyFinalize", cColorSoftBodyFinalize, [ioContext, ioStep]()
2685
- {
2686
- ioContext->mPhysicsSystem->JobSoftBodyFinalize(ioContext);
2687
-
2688
- // Kick the next step
2689
- if (ioStep->mStartNextStep.IsValid())
2690
- ioStep->mStartNextStep.RemoveDependency();
2691
- }, num_soft_body_jobs); // depends on: soft body simulate
2692
- ioContext->mBarrier->AddJob(ioStep->mSoftBodyFinalize);
2693
-
2694
- // Create simulate jobs
2695
- ioStep->mSoftBodySimulate.resize(num_soft_body_jobs);
2696
- for (int i = 0; i < num_soft_body_jobs; ++i)
2697
- ioStep->mSoftBodySimulate[i] = ioContext->mJobSystem->CreateJob("SoftBodySimulate", cColorSoftBodySimulate, [ioStep, i]()
2698
- {
2699
- ioStep->mContext->mPhysicsSystem->JobSoftBodySimulate(ioStep->mContext, i);
2700
-
2701
- ioStep->mSoftBodyFinalize.RemoveDependency();
2702
- }, num_soft_body_jobs); // depends on: soft body collide
2703
- ioContext->mBarrier->AddJobs(ioStep->mSoftBodySimulate.data(), ioStep->mSoftBodySimulate.size());
2704
-
2705
- // Create collision jobs
2706
- ioStep->mSoftBodyCollide.resize(num_soft_body_jobs);
2707
- for (int i = 0; i < num_soft_body_jobs; ++i)
2708
- ioStep->mSoftBodyCollide[i] = ioContext->mJobSystem->CreateJob("SoftBodyCollide", cColorSoftBodyCollide, [ioContext, ioStep]()
2709
- {
2710
- ioContext->mPhysicsSystem->JobSoftBodyCollide(ioContext);
2711
-
2712
- for (const JobHandle &h : ioStep->mSoftBodySimulate)
2713
- h.RemoveDependency();
2714
- }); // depends on: nothing
2715
- ioContext->mBarrier->AddJobs(ioStep->mSoftBodyCollide.data(), ioStep->mSoftBodyCollide.size());
2716
- }
2717
-
2718
- void PhysicsSystem::JobSoftBodyCollide(PhysicsUpdateContext *ioContext) const
2719
- {
2720
- #ifdef JPH_ENABLE_ASSERTS
2721
- // Reading rigid body positions and velocities
2722
- BodyAccess::Grant grant(BodyAccess::EAccess::Read, BodyAccess::EAccess::Read);
2723
- #endif
2724
-
2725
- for (;;)
2726
- {
2727
- // Fetch the next soft body
2728
- uint sb_idx = ioContext->mSoftBodyToCollide.fetch_add(1, std::memory_order_acquire);
2729
- if (sb_idx >= ioContext->mNumSoftBodies)
2730
- break;
2731
-
2732
- // Do a broadphase check
2733
- SoftBodyUpdateContext &sb_ctx = ioContext->mSoftBodyUpdateContexts[sb_idx];
2734
- sb_ctx.mMotionProperties->DetermineCollidingShapes(sb_ctx, *this, GetBodyLockInterfaceNoLock());
2735
- }
2736
- }
2737
-
2738
- void PhysicsSystem::JobSoftBodySimulate(PhysicsUpdateContext *ioContext, uint inThreadIndex) const
2739
- {
2740
- #ifdef JPH_ENABLE_ASSERTS
2741
- // Updating velocities of soft bodies, allow the contact listener to read the soft body state
2742
- BodyAccess::Grant grant(BodyAccess::EAccess::ReadWrite, BodyAccess::EAccess::Read);
2743
- #endif
2744
-
2745
- // Calculate at which body we start to distribute the workload across the threads
2746
- uint num_soft_bodies = ioContext->mNumSoftBodies;
2747
- uint start_idx = inThreadIndex * num_soft_bodies / ioContext->GetMaxConcurrency();
2748
-
2749
- // Keep running partial updates until everything has been updated
2750
- uint status;
2751
- do
2752
- {
2753
- // Reset status
2754
- status = 0;
2755
-
2756
- // Update all soft bodies
2757
- for (uint i = 0; i < num_soft_bodies; ++i)
2758
- {
2759
- // Fetch the soft body context
2760
- SoftBodyUpdateContext &sb_ctx = ioContext->mSoftBodyUpdateContexts[(start_idx + i) % num_soft_bodies];
2761
-
2762
- // To avoid trashing the cache too much, we prefer to stick to one soft body until we cannot progress it any further
2763
- uint sb_status;
2764
- do
2765
- {
2766
- sb_status = (uint)sb_ctx.mMotionProperties->ParallelUpdate(sb_ctx, mPhysicsSettings);
2767
- status |= sb_status;
2768
- } while (sb_status == (uint)SoftBodyMotionProperties::EStatus::DidWork);
2769
- }
2770
-
2771
- // If we didn't perform any work, yield the thread so that something else can run
2772
- if (!(status & (uint)SoftBodyMotionProperties::EStatus::DidWork))
2773
- std::this_thread::yield();
2774
- }
2775
- while (status != (uint)SoftBodyMotionProperties::EStatus::Done);
2776
- }
2777
-
2778
- void PhysicsSystem::JobSoftBodyFinalize(PhysicsUpdateContext *ioContext)
2779
- {
2780
- #ifdef JPH_ENABLE_ASSERTS
2781
- // Updating rigid body velocities and soft body positions / velocities
2782
- BodyAccess::Grant grant(BodyAccess::EAccess::ReadWrite, BodyAccess::EAccess::ReadWrite);
2783
-
2784
- // Can activate and deactivate bodies
2785
- BodyManager::GrantActiveBodiesAccess grant_active(true, true);
2786
- #endif
2787
-
2788
- static constexpr int cBodiesBatch = 64;
2789
- BodyID *bodies_to_update_bounds = (BodyID *)JPH_STACK_ALLOC(cBodiesBatch * sizeof(BodyID));
2790
- int num_bodies_to_update_bounds = 0;
2791
- BodyID *bodies_to_put_to_sleep = (BodyID *)JPH_STACK_ALLOC(cBodiesBatch * sizeof(BodyID));
2792
- int num_bodies_to_put_to_sleep = 0;
2793
-
2794
- for (SoftBodyUpdateContext *sb_ctx = ioContext->mSoftBodyUpdateContexts, *sb_ctx_end = ioContext->mSoftBodyUpdateContexts + ioContext->mNumSoftBodies; sb_ctx < sb_ctx_end; ++sb_ctx)
2795
- {
2796
- // Apply the rigid body velocity deltas
2797
- sb_ctx->mMotionProperties->UpdateRigidBodyVelocities(*sb_ctx, GetBodyInterfaceNoLock());
2798
-
2799
- // Update the position
2800
- sb_ctx->mBody->SetPositionAndRotationInternal(sb_ctx->mBody->GetPosition() + sb_ctx->mDeltaPosition, sb_ctx->mBody->GetRotation(), false);
2801
-
2802
- BodyID id = sb_ctx->mBody->GetID();
2803
- bodies_to_update_bounds[num_bodies_to_update_bounds++] = id;
2804
- if (num_bodies_to_update_bounds == cBodiesBatch)
2805
- {
2806
- // Buffer full, flush now
2807
- mBroadPhase->NotifyBodiesAABBChanged(bodies_to_update_bounds, num_bodies_to_update_bounds, false);
2808
- num_bodies_to_update_bounds = 0;
2809
- }
2810
-
2811
- if (sb_ctx->mCanSleep == ECanSleep::CanSleep)
2812
- {
2813
- // This body should go to sleep
2814
- bodies_to_put_to_sleep[num_bodies_to_put_to_sleep++] = id;
2815
- if (num_bodies_to_put_to_sleep == cBodiesBatch)
2816
- {
2817
- mBodyManager.DeactivateBodies(bodies_to_put_to_sleep, num_bodies_to_put_to_sleep);
2818
- num_bodies_to_put_to_sleep = 0;
2819
- }
2820
- }
2821
- }
2822
-
2823
- // Notify change bounds on requested bodies
2824
- if (num_bodies_to_update_bounds > 0)
2825
- mBroadPhase->NotifyBodiesAABBChanged(bodies_to_update_bounds, num_bodies_to_update_bounds, false);
2826
-
2827
- // Notify bodies to go to sleep
2828
- if (num_bodies_to_put_to_sleep > 0)
2829
- mBodyManager.DeactivateBodies(bodies_to_put_to_sleep, num_bodies_to_put_to_sleep);
2830
-
2831
- // Free soft body contexts
2832
- ioContext->mTempAllocator->Free(ioContext->mSoftBodyUpdateContexts, ioContext->mNumSoftBodies * sizeof(SoftBodyUpdateContext));
2833
- }
2834
-
2835
- void PhysicsSystem::SaveState(StateRecorder &inStream, EStateRecorderState inState, const StateRecorderFilter *inFilter) const
2836
- {
2837
- JPH_PROFILE_FUNCTION();
2838
-
2839
- inStream.Write(inState);
2840
-
2841
- if (uint8(inState) & uint8(EStateRecorderState::Global))
2842
- {
2843
- inStream.Write(mPreviousStepDeltaTime);
2844
- inStream.Write(mGravity);
2845
- }
2846
-
2847
- if (uint8(inState) & uint8(EStateRecorderState::Bodies))
2848
- mBodyManager.SaveState(inStream, inFilter);
2849
-
2850
- if (uint8(inState) & uint8(EStateRecorderState::Contacts))
2851
- mContactManager.SaveState(inStream, inFilter);
2852
-
2853
- if (uint8(inState) & uint8(EStateRecorderState::Constraints))
2854
- mConstraintManager.SaveState(inStream, inFilter);
2855
- }
2856
-
2857
- bool PhysicsSystem::RestoreState(StateRecorder &inStream, const StateRecorderFilter *inFilter)
2858
- {
2859
- JPH_PROFILE_FUNCTION();
2860
-
2861
- EStateRecorderState state = EStateRecorderState::All; // Set this value for validation. If a partial state is saved, validation will not work anyway.
2862
- inStream.Read(state);
2863
-
2864
- if (uint8(state) & uint8(EStateRecorderState::Global))
2865
- {
2866
- inStream.Read(mPreviousStepDeltaTime);
2867
- inStream.Read(mGravity);
2868
- }
2869
-
2870
- if (uint8(state) & uint8(EStateRecorderState::Bodies))
2871
- {
2872
- if (!mBodyManager.RestoreState(inStream))
2873
- return false;
2874
-
2875
- // Update bounding boxes for all bodies in the broadphase
2876
- if (inStream.IsLastPart())
2877
- {
2878
- Array<BodyID> bodies;
2879
- for (const Body *b : mBodyManager.GetBodies())
2880
- if (BodyManager::sIsValidBodyPointer(b) && b->IsInBroadPhase())
2881
- bodies.push_back(b->GetID());
2882
- if (!bodies.empty())
2883
- mBroadPhase->NotifyBodiesAABBChanged(&bodies[0], (int)bodies.size());
2884
- }
2885
- }
2886
-
2887
- if (uint8(state) & uint8(EStateRecorderState::Contacts))
2888
- {
2889
- if (!mContactManager.RestoreState(inStream, inFilter))
2890
- return false;
2891
- }
2892
-
2893
- if (uint8(state) & uint8(EStateRecorderState::Constraints))
2894
- {
2895
- if (!mConstraintManager.RestoreState(inStream))
2896
- return false;
2897
- }
2898
-
2899
- return true;
2900
- }
2901
-
2902
- void PhysicsSystem::SaveBodyState(const Body &inBody, StateRecorder &inStream) const
2903
- {
2904
- mBodyManager.SaveBodyState(inBody, inStream);
2905
- }
2906
-
2907
- void PhysicsSystem::RestoreBodyState(Body &ioBody, StateRecorder &inStream)
2908
- {
2909
- mBodyManager.RestoreBodyState(ioBody, inStream);
2910
-
2911
- BodyID id = ioBody.GetID();
2912
- mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
2913
- }
2914
-
2915
- JPH_NAMESPACE_END