@zephyr3d/scene 0.7.0 → 0.8.0

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 (368) hide show
  1. package/dist/animation/animation.js +4 -33
  2. package/dist/animation/animation.js.map +1 -1
  3. package/dist/animation/animationset.js +24 -11
  4. package/dist/animation/animationset.js.map +1 -1
  5. package/dist/animation/animationtrack.js +1 -0
  6. package/dist/animation/animationtrack.js.map +1 -1
  7. package/dist/animation/eulerrotationtrack.js +0 -1
  8. package/dist/animation/eulerrotationtrack.js.map +1 -1
  9. package/dist/animation/ik/ccd_solver.js +372 -0
  10. package/dist/animation/ik/ccd_solver.js.map +1 -0
  11. package/dist/animation/ik/fabrik_solver.js +399 -0
  12. package/dist/animation/ik/fabrik_solver.js.map +1 -0
  13. package/dist/animation/ik/ik_angle_constraint.js +181 -0
  14. package/dist/animation/ik/ik_angle_constraint.js.map +1 -0
  15. package/dist/animation/ik/ik_chain.js +163 -0
  16. package/dist/animation/ik/ik_chain.js.map +1 -0
  17. package/dist/animation/ik/ik_chain_builder.js +68 -0
  18. package/dist/animation/ik/ik_chain_builder.js.map +1 -0
  19. package/dist/animation/ik/ik_constraint.js +25 -0
  20. package/dist/animation/ik/ik_constraint.js.map +1 -0
  21. package/dist/animation/ik/ik_pole_constraint.js +123 -0
  22. package/dist/animation/ik/ik_pole_constraint.js.map +1 -0
  23. package/dist/animation/ik/ik_solver.js +48 -0
  24. package/dist/animation/ik/ik_solver.js.map +1 -0
  25. package/dist/animation/ik/ik_track.js +96 -0
  26. package/dist/animation/ik/ik_track.js.map +1 -0
  27. package/dist/animation/ik/ik_utils.js +270 -0
  28. package/dist/animation/ik/ik_utils.js.map +1 -0
  29. package/dist/animation/ik/two_bone_ik_solver.js +332 -0
  30. package/dist/animation/ik/two_bone_ik_solver.js.map +1 -0
  31. package/dist/animation/ik_modifier.js +61 -0
  32. package/dist/animation/ik_modifier.js.map +1 -0
  33. package/dist/animation/ik_postprocessor.js +71 -0
  34. package/dist/animation/ik_postprocessor.js.map +1 -0
  35. package/dist/animation/manual_transform_processor.js +156 -0
  36. package/dist/animation/manual_transform_processor.js.map +1 -0
  37. package/dist/animation/morphtarget.js +7 -1
  38. package/dist/animation/morphtarget.js.map +1 -1
  39. package/dist/animation/morphtrack.js +3 -3
  40. package/dist/animation/morphtrack.js.map +1 -1
  41. package/dist/animation/proptrack.js +37 -41
  42. package/dist/animation/proptrack.js.map +1 -1
  43. package/dist/animation/rotationtrack.js +0 -1
  44. package/dist/animation/rotationtrack.js.map +1 -1
  45. package/dist/animation/scaletrack.js +0 -1
  46. package/dist/animation/scaletrack.js.map +1 -1
  47. package/dist/animation/skeleton.js +57 -60
  48. package/dist/animation/skeleton.js.map +1 -1
  49. package/dist/animation/skeleton_modifier.js +38 -0
  50. package/dist/animation/skeleton_modifier.js.map +1 -0
  51. package/dist/animation/skeleton_postprocessor.js +50 -0
  52. package/dist/animation/skeleton_postprocessor.js.map +1 -0
  53. package/dist/animation/spring/multi_chain_spring_system.js +503 -0
  54. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -0
  55. package/dist/animation/spring/spring_chain.js +103 -0
  56. package/dist/animation/spring/spring_chain.js.map +1 -0
  57. package/dist/animation/spring/spring_collider.js +247 -0
  58. package/dist/animation/spring/spring_collider.js.map +1 -0
  59. package/dist/animation/spring/spring_constraint.js +21 -0
  60. package/dist/animation/spring/spring_constraint.js.map +1 -0
  61. package/dist/animation/spring/spring_particle.js +20 -0
  62. package/dist/animation/spring/spring_particle.js.map +1 -0
  63. package/dist/animation/spring/spring_system.js +526 -0
  64. package/dist/animation/spring/spring_system.js.map +1 -0
  65. package/dist/animation/spring_modifier.js +45 -0
  66. package/dist/animation/spring_modifier.js.map +1 -0
  67. package/dist/animation/spring_postprocessor.js +54 -0
  68. package/dist/animation/spring_postprocessor.js.map +1 -0
  69. package/dist/animation/translationtrack.js +0 -1
  70. package/dist/animation/translationtrack.js.map +1 -1
  71. package/dist/app/api.js +13 -4
  72. package/dist/app/api.js.map +1 -1
  73. package/dist/app/app.js +13 -1
  74. package/dist/app/app.js.map +1 -1
  75. package/dist/app/engine.js +33 -45
  76. package/dist/app/engine.js.map +1 -1
  77. package/dist/app/inputmgr.js.map +1 -1
  78. package/dist/app/runtimescript.js.map +1 -1
  79. package/dist/app/screen.js +318 -0
  80. package/dist/app/screen.js.map +1 -0
  81. package/dist/app/scriptingsystem.js +10 -6
  82. package/dist/app/scriptingsystem.js.map +1 -1
  83. package/dist/app/scriptregistry.js +11 -22
  84. package/dist/app/scriptregistry.js.map +1 -1
  85. package/dist/asset/assetmanager.js +79 -58
  86. package/dist/asset/assetmanager.js.map +1 -1
  87. package/dist/asset/builtin.js +5 -5
  88. package/dist/asset/builtin.js.map +1 -1
  89. package/dist/asset/loaders/dds/dds.js +6 -2
  90. package/dist/asset/loaders/dds/dds.js.map +1 -1
  91. package/dist/asset/loaders/dds/dds_loader.js +1 -1
  92. package/dist/asset/loaders/dds/dds_loader.js.map +1 -1
  93. package/dist/asset/loaders/gltf/gltf_loader.js +14 -6
  94. package/dist/asset/loaders/gltf/gltf_loader.js.map +1 -1
  95. package/dist/asset/loaders/gltf/helpers.js +6 -2
  96. package/dist/asset/loaders/gltf/helpers.js.map +1 -1
  97. package/dist/asset/loaders/hdr/hdr.js +22 -15
  98. package/dist/asset/loaders/hdr/hdr.js.map +1 -1
  99. package/dist/asset/loaders/image/tga_Loader.js +2 -1
  100. package/dist/asset/loaders/image/tga_Loader.js.map +1 -1
  101. package/dist/asset/loaders/image/webimage_loader.js.map +1 -1
  102. package/dist/asset/loaders/loader.js +2 -2
  103. package/dist/asset/loaders/loader.js.map +1 -1
  104. package/dist/asset/model.js +9 -5
  105. package/dist/asset/model.js.map +1 -1
  106. package/dist/blitter/bilateralblur.js.map +1 -1
  107. package/dist/blitter/blitter.js +9 -11
  108. package/dist/blitter/blitter.js.map +1 -1
  109. package/dist/blitter/box.js +0 -1
  110. package/dist/blitter/box.js.map +1 -1
  111. package/dist/blitter/copy.js.map +1 -1
  112. package/dist/blitter/gaussianblur.js.map +1 -1
  113. package/dist/camera/base.js +1 -3
  114. package/dist/camera/base.js.map +1 -1
  115. package/dist/camera/camera.js +121 -37
  116. package/dist/camera/camera.js.map +1 -1
  117. package/dist/camera/fps.js +19 -17
  118. package/dist/camera/fps.js.map +1 -1
  119. package/dist/camera/orbit.js +45 -43
  120. package/dist/camera/orbit.js.map +1 -1
  121. package/dist/camera/orthocamera.js +27 -21
  122. package/dist/camera/orthocamera.js.map +1 -1
  123. package/dist/camera/perspectivecamera.js +28 -19
  124. package/dist/camera/perspectivecamera.js.map +1 -1
  125. package/dist/index.d.ts +15802 -15577
  126. package/dist/index.js +33 -11
  127. package/dist/index.js.map +1 -1
  128. package/dist/material/blinn.js.map +1 -1
  129. package/dist/material/grassmaterial.js.map +1 -1
  130. package/dist/material/lambert.js.map +1 -1
  131. package/dist/material/material.js +11 -5
  132. package/dist/material/material.js.map +1 -1
  133. package/dist/material/meshmaterial.js +10 -9
  134. package/dist/material/meshmaterial.js.map +1 -1
  135. package/dist/material/mixins/albedocolor.js.map +1 -1
  136. package/dist/material/mixins/foliage.js.map +1 -1
  137. package/dist/material/mixins/lightmodel/blinnphong.js +66 -4
  138. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  139. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  140. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +7 -0
  141. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  142. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  143. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  144. package/dist/material/mixins/lit.js +3 -3
  145. package/dist/material/mixins/lit.js.map +1 -1
  146. package/dist/material/mixins/pbr/brdf.js.map +1 -1
  147. package/dist/material/mixins/pbr/common.js.map +1 -1
  148. package/dist/material/mixins/texture.js +3 -0
  149. package/dist/material/mixins/texture.js.map +1 -1
  150. package/dist/material/mixins/vertexcolor.js.map +1 -1
  151. package/dist/material/particle.js.map +1 -1
  152. package/dist/material/pbrblueprint.js +180 -22
  153. package/dist/material/pbrblueprint.js.map +1 -1
  154. package/dist/material/pbrmr.js.map +1 -1
  155. package/dist/material/pbrsg.js.map +1 -1
  156. package/dist/material/shader/helper.js +41 -56
  157. package/dist/material/shader/helper.js.map +1 -1
  158. package/dist/material/sprite.js +301 -0
  159. package/dist/material/sprite.js.map +1 -0
  160. package/dist/material/sprite3d.js +301 -0
  161. package/dist/material/sprite3d.js.map +1 -0
  162. package/dist/material/sprite3d_std.js +116 -0
  163. package/dist/material/sprite3d_std.js.map +1 -0
  164. package/dist/material/sprite3dblueprint.js +235 -0
  165. package/dist/material/sprite3dblueprint.js.map +1 -0
  166. package/dist/material/sprite_std.js +116 -0
  167. package/dist/material/sprite_std.js.map +1 -0
  168. package/dist/material/spriteblueprint.js +235 -0
  169. package/dist/material/spriteblueprint.js.map +1 -0
  170. package/dist/material/terrain-cm.js +0 -1
  171. package/dist/material/terrain-cm.js.map +1 -1
  172. package/dist/material/unlit.js.map +1 -1
  173. package/dist/material/water.js.map +1 -1
  174. package/dist/posteffect/bloom.js.map +1 -1
  175. package/dist/posteffect/compositor.js.map +1 -1
  176. package/dist/posteffect/fxaa.js.map +1 -1
  177. package/dist/posteffect/grayscale.js.map +1 -1
  178. package/dist/posteffect/motionblur.js.map +1 -1
  179. package/dist/posteffect/posteffect.js.map +1 -1
  180. package/dist/posteffect/sao.js.map +1 -1
  181. package/dist/posteffect/ssr.js +7 -5
  182. package/dist/posteffect/ssr.js.map +1 -1
  183. package/dist/posteffect/taa.js.map +1 -1
  184. package/dist/posteffect/tonemap.js.map +1 -1
  185. package/dist/render/abuffer_oit.js +8 -6
  186. package/dist/render/abuffer_oit.js.map +1 -1
  187. package/dist/render/clipmap.js +0 -10
  188. package/dist/render/clipmap.js.map +1 -1
  189. package/dist/render/cluster_light.js +4 -4
  190. package/dist/render/cluster_light.js.map +1 -1
  191. package/dist/render/cull_visitor.js +15 -17
  192. package/dist/render/cull_visitor.js.map +1 -1
  193. package/dist/render/depthpass.js +3 -4
  194. package/dist/render/depthpass.js.map +1 -1
  195. package/dist/render/drawable.js +15 -0
  196. package/dist/render/drawable.js.map +1 -0
  197. package/dist/render/drawable_mixin.js +8 -4
  198. package/dist/render/drawable_mixin.js.map +1 -1
  199. package/dist/render/envlight.js.map +1 -1
  200. package/dist/render/fbm_wavegenerator.js +3 -1
  201. package/dist/render/fbm_wavegenerator.js.map +1 -1
  202. package/dist/render/fft_wavegenerator.js +67 -64
  203. package/dist/render/fft_wavegenerator.js.map +1 -1
  204. package/dist/render/fullscreenquad.js.map +1 -1
  205. package/dist/render/gerstner_wavegenerator.js +3 -1
  206. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  207. package/dist/render/globalbindgroup_allocator.js +3 -1
  208. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  209. package/dist/render/hzb.js +1 -2
  210. package/dist/render/hzb.js.map +1 -1
  211. package/dist/render/lightpass.js +13 -13
  212. package/dist/render/lightpass.js.map +1 -1
  213. package/dist/render/objectcolorpass.js +4 -7
  214. package/dist/render/objectcolorpass.js.map +1 -1
  215. package/dist/render/primitive.js +4 -5
  216. package/dist/render/primitive.js.map +1 -1
  217. package/dist/render/render_queue.js +10 -5
  218. package/dist/render/render_queue.js.map +1 -1
  219. package/dist/render/renderer.js +16 -22
  220. package/dist/render/renderer.js.map +1 -1
  221. package/dist/render/renderpass.js +27 -52
  222. package/dist/render/renderpass.js.map +1 -1
  223. package/dist/render/rendertarget.js +5 -0
  224. package/dist/render/rendertarget.js.map +1 -0
  225. package/dist/render/screenrendertarget.js +56 -0
  226. package/dist/render/screenrendertarget.js.map +1 -0
  227. package/dist/render/shadowmap_pass.js +4 -5
  228. package/dist/render/shadowmap_pass.js.map +1 -1
  229. package/dist/render/sky.js +16 -14
  230. package/dist/render/sky.js.map +1 -1
  231. package/dist/render/weightedblended_oit.js.map +1 -1
  232. package/dist/scene/basesprite.js +296 -0
  233. package/dist/scene/basesprite.js.map +1 -0
  234. package/dist/scene/batchgroup.js +4 -2
  235. package/dist/scene/batchgroup.js.map +1 -1
  236. package/dist/scene/environment.js +9 -10
  237. package/dist/scene/environment.js.map +1 -1
  238. package/dist/scene/graph_node.js.map +1 -1
  239. package/dist/scene/light.js +22 -4
  240. package/dist/scene/light.js.map +1 -1
  241. package/dist/scene/mesh.js +96 -26
  242. package/dist/scene/mesh.js.map +1 -1
  243. package/dist/scene/octree.js.map +1 -1
  244. package/dist/scene/particlesys.js +25 -22
  245. package/dist/scene/particlesys.js.map +1 -1
  246. package/dist/scene/raycast_visitor.js +0 -16
  247. package/dist/scene/raycast_visitor.js.map +1 -1
  248. package/dist/scene/scene.js +7 -4
  249. package/dist/scene/scene.js.map +1 -1
  250. package/dist/scene/scene_node.js +20 -35
  251. package/dist/scene/scene_node.js.map +1 -1
  252. package/dist/scene/sprite.js +18 -0
  253. package/dist/scene/sprite.js.map +1 -0
  254. package/dist/scene/sprite3d.js +18 -0
  255. package/dist/scene/sprite3d.js.map +1 -0
  256. package/dist/scene/terrain-cm/grass.js +5 -4
  257. package/dist/scene/terrain-cm/grass.js.map +1 -1
  258. package/dist/scene/terrain-cm/grassmaterial.js +3 -1
  259. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  260. package/dist/scene/terrain-cm/terrain-cm.js +65 -48
  261. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  262. package/dist/scene/water.js +35 -30
  263. package/dist/scene/water.js.map +1 -1
  264. package/dist/shaders/atmosphere.js +17 -29
  265. package/dist/shaders/atmosphere.js.map +1 -1
  266. package/dist/shaders/fog.js.map +1 -1
  267. package/dist/shaders/misc.js.map +1 -1
  268. package/dist/shaders/noise.js.map +1 -1
  269. package/dist/shaders/pbr.js.map +1 -1
  270. package/dist/shaders/shadow.js.map +1 -1
  271. package/dist/shaders/ssr.js.map +1 -1
  272. package/dist/shaders/temporal.js.map +1 -1
  273. package/dist/shaders/water.js.map +1 -1
  274. package/dist/shadow/esm.js +1 -1
  275. package/dist/shadow/esm.js.map +1 -1
  276. package/dist/shadow/pcf_opt.js.map +1 -1
  277. package/dist/shadow/pcf_pd.js.map +1 -1
  278. package/dist/shadow/shader.js +3 -1
  279. package/dist/shadow/shader.js.map +1 -1
  280. package/dist/shadow/shadow_impl.js.map +1 -1
  281. package/dist/shadow/shadowmapper.js +6 -18
  282. package/dist/shadow/shadowmapper.js.map +1 -1
  283. package/dist/shadow/ssm.js.map +1 -1
  284. package/dist/shadow/vsm.js.map +1 -1
  285. package/dist/shapes/box.js +9 -3
  286. package/dist/shapes/box.js.map +1 -1
  287. package/dist/shapes/cylinder.js +2 -2
  288. package/dist/shapes/cylinder.js.map +1 -1
  289. package/dist/shapes/plane.js +2 -2
  290. package/dist/shapes/plane.js.map +1 -1
  291. package/dist/shapes/shape.js +2 -1
  292. package/dist/shapes/shape.js.map +1 -1
  293. package/dist/shapes/sphere.js +2 -2
  294. package/dist/shapes/sphere.js.map +1 -1
  295. package/dist/shapes/tetrahedron.js +5 -6
  296. package/dist/shapes/tetrahedron.js.map +1 -1
  297. package/dist/shapes/torus.js +2 -2
  298. package/dist/shapes/torus.js.map +1 -1
  299. package/dist/utility/aabbtree.js +1 -1
  300. package/dist/utility/aabbtree.js.map +1 -1
  301. package/dist/utility/blueprint/common/constants.js +578 -104
  302. package/dist/utility/blueprint/common/constants.js.map +1 -1
  303. package/dist/utility/blueprint/common/math.js +471 -9
  304. package/dist/utility/blueprint/common/math.js.map +1 -1
  305. package/dist/utility/blueprint/common.js +1 -1
  306. package/dist/utility/blueprint/common.js.map +1 -1
  307. package/dist/utility/blueprint/material/func.js +9 -5
  308. package/dist/utility/blueprint/material/func.js.map +1 -1
  309. package/dist/utility/blueprint/material/inputs.js.map +1 -1
  310. package/dist/utility/blueprint/material/ir.js +288 -80
  311. package/dist/utility/blueprint/material/ir.js.map +1 -1
  312. package/dist/utility/blueprint/material/pbr.js +92 -4
  313. package/dist/utility/blueprint/material/pbr.js.map +1 -1
  314. package/dist/utility/blueprint/material/texture.js +62 -45
  315. package/dist/utility/blueprint/material/texture.js.map +1 -1
  316. package/dist/utility/blueprint/node.js +28 -1
  317. package/dist/utility/blueprint/node.js.map +1 -1
  318. package/dist/utility/bounding_volume.js.map +1 -1
  319. package/dist/utility/debug.js.map +1 -1
  320. package/dist/utility/draco/decoder.js.map +1 -1
  321. package/dist/utility/misc.js +1 -1
  322. package/dist/utility/misc.js.map +1 -1
  323. package/dist/utility/panorama.js.map +1 -1
  324. package/dist/utility/pmrem.js.map +1 -1
  325. package/dist/utility/rendermipmap.js.map +1 -1
  326. package/dist/utility/serialization/json.js +19 -15
  327. package/dist/utility/serialization/json.js.map +1 -1
  328. package/dist/utility/serialization/manager.js +89 -22
  329. package/dist/utility/serialization/manager.js.map +1 -1
  330. package/dist/utility/serialization/scene/animation.js +44 -41
  331. package/dist/utility/serialization/scene/animation.js.map +1 -1
  332. package/dist/utility/serialization/scene/batch.js +4 -3
  333. package/dist/utility/serialization/scene/batch.js.map +1 -1
  334. package/dist/utility/serialization/scene/camera.js +97 -9
  335. package/dist/utility/serialization/scene/camera.js.map +1 -1
  336. package/dist/utility/serialization/scene/common.js +102 -28
  337. package/dist/utility/serialization/scene/common.js.map +1 -1
  338. package/dist/utility/serialization/scene/light.js +14 -12
  339. package/dist/utility/serialization/scene/light.js.map +1 -1
  340. package/dist/utility/serialization/scene/material.js +216 -26
  341. package/dist/utility/serialization/scene/material.js.map +1 -1
  342. package/dist/utility/serialization/scene/mesh.js +71 -100
  343. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  344. package/dist/utility/serialization/scene/misc.js +3 -2
  345. package/dist/utility/serialization/scene/misc.js.map +1 -1
  346. package/dist/utility/serialization/scene/node.js +42 -9
  347. package/dist/utility/serialization/scene/node.js.map +1 -1
  348. package/dist/utility/serialization/scene/particle.js +7 -5
  349. package/dist/utility/serialization/scene/particle.js.map +1 -1
  350. package/dist/utility/serialization/scene/primitive.js +18 -15
  351. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  352. package/dist/utility/serialization/scene/scene.js +3 -2
  353. package/dist/utility/serialization/scene/scene.js.map +1 -1
  354. package/dist/utility/serialization/scene/sprite.js +164 -0
  355. package/dist/utility/serialization/scene/sprite.js.map +1 -0
  356. package/dist/utility/serialization/scene/terrain.js +8 -6
  357. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  358. package/dist/utility/serialization/scene/water.js +11 -9
  359. package/dist/utility/serialization/scene/water.js.map +1 -1
  360. package/dist/utility/serialization/types.js +6 -0
  361. package/dist/utility/serialization/types.js.map +1 -0
  362. package/dist/utility/shprojector.js.map +1 -1
  363. package/dist/utility/textures/ggxlut.js.map +1 -1
  364. package/dist/utility/textures/gradientnoise.js.map +1 -1
  365. package/dist/utility/textures/randomnoise.js.map +1 -1
  366. package/dist/values.js +14 -14
  367. package/dist/values.js.map +1 -1
  368. package/package.json +80 -80
@@ -0,0 +1,526 @@
1
+ import { Vector3, Quaternion } from '@zephyr3d/base';
2
+ import { IKUtils } from '../ik/ik_utils.js';
3
+ import { updateColliderFromNode, resolvePlaneCollision, resolveCapsuleCollision, resolveSphereCollision } from './spring_collider.js';
4
+
5
+ /**
6
+ * Physics engine for spring-based particle simulation
7
+ * Uses Verlet integration and iterative constraint solving
8
+ *
9
+ * @public
10
+ */ class SpringSystem {
11
+ _chain;
12
+ _iterations;
13
+ _gravity;
14
+ _wind;
15
+ _enableInertialForces;
16
+ _centrifugalScale;
17
+ _coriolisScale;
18
+ _colliders;
19
+ _solver;
20
+ constructor(chain, options){
21
+ this._chain = chain;
22
+ this._iterations = options?.iterations ?? 5;
23
+ this._gravity = options?.gravity?.clone() ?? new Vector3(0, -9.8, 0);
24
+ this._wind = options?.wind?.clone() ?? new Vector3(0, 0, 0);
25
+ this._enableInertialForces = options?.enableInertialForces ?? true;
26
+ this._centrifugalScale = options?.centrifugalScale ?? 1.0;
27
+ this._coriolisScale = options?.coriolisScale ?? 1.0;
28
+ this._colliders = [];
29
+ this._solver = options?.solver ?? 'verlet';
30
+ }
31
+ /**
32
+ * Updates the physics simulation
33
+ * @param deltaTime - Time step in seconds
34
+ */ update(deltaTime) {
35
+ // Clamp deltaTime to prevent instability
36
+ const dt = Math.min(deltaTime, 0.033); // Max 30 FPS
37
+ // Step 1: Save all particle positions before updating
38
+ if (this._enableInertialForces) {
39
+ for (const p of this._chain.particles){
40
+ p.lastFramePosition.set(p.position);
41
+ }
42
+ }
43
+ // Step 2: Update fixed particles from their scene nodes
44
+ this.updateFixedParticles();
45
+ // Step 3: Calculate global rotation parameters
46
+ let rotationCenter = null;
47
+ let angularVelocity = null;
48
+ if (this._enableInertialForces && dt > 0.0001) {
49
+ const result = this.calculateGlobalRotation(dt);
50
+ rotationCenter = result.center;
51
+ angularVelocity = result.omega;
52
+ }
53
+ // Step 4: Verlet integration with inertial forces
54
+ for(let i = 0; i < this._chain.particles.length; i++){
55
+ const p = this._chain.particles[i];
56
+ if (p.fixed) {
57
+ continue;
58
+ }
59
+ // Calculate velocity (implicit in Verlet)
60
+ const velocity = Vector3.sub(p.position, p.prevPosition, new Vector3());
61
+ velocity.scaleBy(p.damping);
62
+ // Apply external forces (gravity + wind)
63
+ const acceleration = Vector3.add(this._gravity, this._wind, new Vector3());
64
+ // Apply inertial forces from rotating reference frame
65
+ if (this._enableInertialForces && rotationCenter && angularVelocity) {
66
+ const inertialAccel = this.calculateInertialAcceleration(p, rotationCenter, angularVelocity, velocity, this._centrifugalScale, this._coriolisScale);
67
+ Vector3.add(acceleration, inertialAccel, acceleration);
68
+ }
69
+ const positionDelta = Vector3.scale(acceleration, dt * dt, new Vector3());
70
+ Vector3.add(velocity, positionDelta, velocity);
71
+ // Update position
72
+ p.prevPosition.set(p.position);
73
+ Vector3.add(p.position, velocity, p.position);
74
+ }
75
+ // Step 5: Iteratively solve constraints
76
+ if (this._solver === 'xpbd') {
77
+ // Reset Lagrange multipliers at the start of each time step
78
+ for (const constraint of this._chain.constraints){
79
+ constraint.lambda = 0;
80
+ }
81
+ }
82
+ for(let iter = 0; iter < this._iterations; iter++){
83
+ for (const constraint of this._chain.constraints){
84
+ if (this._solver === 'xpbd') {
85
+ this.solveConstraintXPBD(constraint, dt);
86
+ } else {
87
+ this.solveConstraint(constraint);
88
+ }
89
+ }
90
+ // Apply collision constraints
91
+ this.solveCollisions();
92
+ }
93
+ }
94
+ /**
95
+ * Updates fixed particles to match their scene node positions
96
+ */ updateFixedParticles() {
97
+ for (const particle of this._chain.particles){
98
+ if (particle.node && particle.fixed) {
99
+ const worldMatrix = particle.node.worldMatrix;
100
+ const worldPos = new Vector3(worldMatrix.m03, worldMatrix.m13, worldMatrix.m23);
101
+ particle.position.set(worldPos);
102
+ particle.prevPosition.set(worldPos);
103
+ // Maintain position history for rotation center estimation
104
+ if (this._enableInertialForces) {
105
+ if (!particle.positionHistory) {
106
+ particle.positionHistory = [];
107
+ }
108
+ particle.positionHistory.push(worldPos.clone());
109
+ // Keep only last 5 frames
110
+ if (particle.positionHistory.length > 5) {
111
+ particle.positionHistory.shift();
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ /**
118
+ * Calculates global rotation parameters from fixed particle movements
119
+ * Uses position history to estimate rotation center
120
+ */ calculateGlobalRotation(dt) {
121
+ // Collect fixed particles with movement
122
+ const fixedParticles = [];
123
+ const velocities = [];
124
+ for (const p of this._chain.particles){
125
+ if (!p.fixed) {
126
+ continue;
127
+ }
128
+ const velocity = Vector3.sub(p.position, p.lastFramePosition, new Vector3());
129
+ velocity.scaleBy(1.0 / dt);
130
+ if (velocity.magnitudeSq > 0.001) {
131
+ fixedParticles.push(p);
132
+ velocities.push(velocity);
133
+ }
134
+ }
135
+ if (fixedParticles.length === 0) {
136
+ return {
137
+ center: new Vector3(0, 0, 0),
138
+ omega: new Vector3(0, 0, 0)
139
+ };
140
+ }
141
+ // Estimate rotation center using position history
142
+ let center;
143
+ if (fixedParticles.length === 1) {
144
+ // Single fixed particle: use position history to estimate rotation center
145
+ center = this.estimateRotationCenterFromHistory(fixedParticles[0], velocities[0]);
146
+ } else {
147
+ // Multiple fixed particles: use their average position
148
+ center = new Vector3(0, 0, 0);
149
+ for (const p of fixedParticles){
150
+ Vector3.add(center, p.position, center);
151
+ }
152
+ center.scaleBy(1.0 / fixedParticles.length);
153
+ }
154
+ // Estimate angular velocity
155
+ let sumOmega = new Vector3(0, 0, 0);
156
+ let count = 0;
157
+ for(let i = 0; i < fixedParticles.length; i++){
158
+ const r = Vector3.sub(fixedParticles[i].position, center, new Vector3());
159
+ const v = velocities[i];
160
+ const rLengthSq = r.magnitudeSq;
161
+ if (rLengthSq > 0.0001) {
162
+ // ω = (r × v) / |r|²
163
+ const omega = Vector3.cross(r, v, new Vector3());
164
+ omega.scaleBy(1.0 / rLengthSq);
165
+ Vector3.add(sumOmega, omega, sumOmega);
166
+ count++;
167
+ }
168
+ }
169
+ if (count > 0) {
170
+ sumOmega.scaleBy(1.0 / count);
171
+ }
172
+ return {
173
+ center,
174
+ omega: sumOmega
175
+ };
176
+ }
177
+ /**
178
+ * Estimates rotation center from a single particle's position history
179
+ * Uses circular motion fitting
180
+ */ estimateRotationCenterFromHistory(particle, currentVelocity) {
181
+ const history = particle.positionHistory;
182
+ if (!history || history.length < 3) {
183
+ // Not enough history: estimate using velocity perpendicular direction
184
+ // Assume rotation center is perpendicular to velocity
185
+ // Use a default radius based on velocity magnitude
186
+ const speed = currentVelocity.magnitude;
187
+ if (speed < 0.001) {
188
+ return particle.position.clone();
189
+ }
190
+ // Estimate radius: for typical character rotation, assume ~0.5-1.0m radius
191
+ const estimatedRadius = Math.max(0.5, speed * 0.5);
192
+ // Direction perpendicular to velocity (in the plane of motion)
193
+ // We need to guess which perpendicular direction - use cross product with up vector
194
+ const up = new Vector3(0, 1, 0);
195
+ const perpDir = Vector3.cross(currentVelocity, up, new Vector3());
196
+ if (perpDir.magnitudeSq < 0.0001) {
197
+ // Velocity is vertical, use another perpendicular
198
+ perpDir.set(new Vector3(1, 0, 0));
199
+ } else {
200
+ perpDir.inplaceNormalize();
201
+ }
202
+ // Rotation center is perpendicular to velocity
203
+ const center = Vector3.add(particle.position, Vector3.scale(perpDir, estimatedRadius, new Vector3()), new Vector3());
204
+ return center;
205
+ }
206
+ // Fit a circle through the last 3 positions
207
+ // Use positions at indices: 0 (oldest), middle, last (newest)
208
+ const p1 = history[0];
209
+ const p2 = history[Math.floor(history.length / 2)];
210
+ const p3 = history[history.length - 1];
211
+ // Calculate circle center from 3 points
212
+ const center = this.calculateCircleCenter(p1, p2, p3);
213
+ return center;
214
+ }
215
+ /**
216
+ * Calculates the center of a circle passing through 3 points
217
+ * Uses perpendicular bisector method
218
+ */ calculateCircleCenter(p1, p2, p3) {
219
+ // Midpoints
220
+ const mid12 = Vector3.scale(Vector3.add(p1, p2, new Vector3()), 0.5, new Vector3());
221
+ const mid23 = Vector3.scale(Vector3.add(p2, p3, new Vector3()), 0.5, new Vector3());
222
+ // Direction vectors
223
+ const dir12 = Vector3.sub(p2, p1, new Vector3());
224
+ const dir23 = Vector3.sub(p3, p2, new Vector3());
225
+ // Normal vectors (perpendicular bisectors)
226
+ // For 3D, we need to find perpendiculars in the plane of the three points
227
+ const normal = Vector3.cross(dir12, dir23, new Vector3());
228
+ if (normal.magnitudeSq < 0.0001) {
229
+ // Points are collinear, return midpoint
230
+ return Vector3.scale(Vector3.add(Vector3.add(p1, p2, new Vector3()), p3, new Vector3()), 1.0 / 3.0, new Vector3());
231
+ }
232
+ normal.inplaceNormalize();
233
+ // Perpendicular to dir12 in the plane
234
+ const perp12 = Vector3.cross(dir12, normal, new Vector3()).inplaceNormalize();
235
+ // Perpendicular to dir23 in the plane
236
+ const perp23 = Vector3.cross(dir23, normal, new Vector3()).inplaceNormalize();
237
+ // Find intersection of two lines:
238
+ // Line 1: mid12 + t * perp12
239
+ // Line 2: mid23 + s * perp23
240
+ // Solve: mid12 + t * perp12 = mid23 + s * perp23
241
+ const diff = Vector3.sub(mid23, mid12, new Vector3());
242
+ // Use 2D projection for simplicity (project onto plane perpendicular to normal)
243
+ // Solve in the plane: t * perp12 - s * perp23 = diff
244
+ // Use least squares or pick the dominant components
245
+ const det = perp12.x * perp23.y - perp12.y * perp23.x;
246
+ if (Math.abs(det) > 0.0001) {
247
+ const t = (diff.x * perp23.y - diff.y * perp23.x) / det;
248
+ const center = Vector3.add(mid12, Vector3.scale(perp12, t, new Vector3()), new Vector3());
249
+ return center;
250
+ }
251
+ // Fallback: use centroid
252
+ return Vector3.scale(Vector3.add(Vector3.add(p1, p2, new Vector3()), p3, new Vector3()), 1.0 / 3.0, new Vector3());
253
+ }
254
+ /**
255
+ * Calculates inertial acceleration for a particle in a rotating reference frame
256
+ */ calculateInertialAcceleration(particle, rotationCenter, angularVelocity, particleVelocity, centrifugalScale, coriolisScale) {
257
+ // Vector from rotation center to particle
258
+ const r = Vector3.sub(particle.position, rotationCenter, new Vector3());
259
+ // Centrifugal acceleration: a_centrifugal = ω × (ω × r)
260
+ const omegaCrossR = Vector3.cross(angularVelocity, r, new Vector3());
261
+ const centrifugalAccel = Vector3.cross(angularVelocity, omegaCrossR, new Vector3());
262
+ centrifugalAccel.scaleBy(centrifugalScale);
263
+ // Coriolis acceleration: a_coriolis = -2ω × v_relative
264
+ // v_relative is the particle's velocity in the rotating frame
265
+ // Use the velocity passed in (already calculated from prevPosition)
266
+ const coriolisAccel = Vector3.cross(angularVelocity, particleVelocity, new Vector3());
267
+ coriolisAccel.scaleBy(-2 * coriolisScale);
268
+ // Total inertial acceleration
269
+ const totalAccel = Vector3.add(centrifugalAccel, coriolisAccel, new Vector3());
270
+ return totalAccel;
271
+ }
272
+ /**
273
+ * Solves a single spring constraint using XPBD (Extended Position-Based Dynamics).
274
+ *
275
+ * Reference: Müller et al., "Detailed Rigid Body Simulation with Extended Position Based Dynamics", 2020.
276
+ *
277
+ * The XPBD correction for a distance constraint C(x) = |x_b - x_a| - L is:
278
+ * α̃ = compliance / dt² (scaled compliance)
279
+ * Δλ = (-C - α̃·λ) / (w_a + w_b + α̃)
280
+ * λ += Δλ
281
+ * Δx_a = -w_a · Δλ · n̂
282
+ * Δx_b = +w_b · Δλ · n̂
283
+ * where w = 1/mass (0 for fixed particles), n̂ = unit vector from a to b.
284
+ */ solveConstraintXPBD(constraint, dt) {
285
+ const pA = this._chain.particles[constraint.particleA];
286
+ const pB = this._chain.particles[constraint.particleB];
287
+ const wA = pA.fixed ? 0 : 1.0 / pA.mass;
288
+ const wB = pB.fixed ? 0 : 1.0 / pB.mass;
289
+ const wSum = wA + wB;
290
+ if (wSum < 1e-10) {
291
+ return;
292
+ }
293
+ const delta = Vector3.sub(pB.position, pA.position, new Vector3());
294
+ const currentLength = delta.magnitude;
295
+ if (currentLength < 0.0001) {
296
+ return;
297
+ }
298
+ // Constraint value C = currentLength - restLength
299
+ const C = currentLength - constraint.restLength;
300
+ // Scaled compliance: α̃ = compliance / dt²
301
+ const alphaTilde = constraint.compliance / (dt * dt);
302
+ // XPBD Lagrange multiplier update
303
+ const deltaLambda = (-C - alphaTilde * constraint.lambda) / (wSum + alphaTilde);
304
+ constraint.lambda += deltaLambda;
305
+ // Correction direction (unit vector from A to B)
306
+ const n = Vector3.scale(delta, 1.0 / currentLength, new Vector3());
307
+ if (!pA.fixed) {
308
+ // Δx_a = -w_a · Δλ · n̂
309
+ Vector3.add(pA.position, Vector3.scale(n, -wA * deltaLambda, new Vector3()), pA.position);
310
+ }
311
+ if (!pB.fixed) {
312
+ // Δx_b = +w_b · Δλ · n̂
313
+ Vector3.add(pB.position, Vector3.scale(n, wB * deltaLambda, new Vector3()), pB.position);
314
+ }
315
+ }
316
+ /**
317
+ * Solves a single spring constraint (Verlet / PBD)
318
+ */ solveConstraint(constraint) {
319
+ const pA = this._chain.particles[constraint.particleA];
320
+ const pB = this._chain.particles[constraint.particleB];
321
+ // Calculate current distance
322
+ const delta = Vector3.sub(pB.position, pA.position, new Vector3());
323
+ const currentLength = delta.magnitude;
324
+ if (currentLength < 0.0001) {
325
+ return;
326
+ } // Avoid division by zero
327
+ // Calculate correction
328
+ const diff = (currentLength - constraint.restLength) / currentLength;
329
+ const correction = Vector3.scale(delta, diff * constraint.stiffness * 0.5, new Vector3());
330
+ // Apply correction (considering mass and fixed state)
331
+ if (!pA.fixed) {
332
+ Vector3.add(pA.position, correction, pA.position);
333
+ }
334
+ if (!pB.fixed) {
335
+ Vector3.sub(pB.position, correction, pB.position);
336
+ }
337
+ }
338
+ /**
339
+ * Solves collisions for all particles
340
+ */ solveCollisions() {
341
+ // Update dynamic colliders from their nodes
342
+ for (const collider of this._colliders){
343
+ if (collider.node) {
344
+ updateColliderFromNode(collider);
345
+ }
346
+ }
347
+ // Check each particle against all colliders
348
+ for (const particle of this._chain.particles){
349
+ if (particle.fixed) {
350
+ continue; // Skip fixed particles
351
+ }
352
+ for (const collider of this._colliders){
353
+ if (!collider.enabled) {
354
+ continue;
355
+ }
356
+ switch(collider.type){
357
+ case 'sphere':
358
+ resolveSphereCollision(particle.position, collider);
359
+ break;
360
+ case 'capsule':
361
+ resolveCapsuleCollision(particle.position, collider);
362
+ break;
363
+ case 'plane':
364
+ resolvePlaneCollision(particle.position, collider);
365
+ break;
366
+ }
367
+ }
368
+ }
369
+ }
370
+ /**
371
+ * Applies simulation results to scene nodes
372
+ * @param weight - Blend weight [0-1] (default: 1.0)
373
+ */ applyToNodes(weight = 1.0) {
374
+ for(let i = 0; i < this._chain.particles.length - 1; i++){
375
+ const particle = this._chain.particles[i];
376
+ const nextParticle = this._chain.particles[i + 1];
377
+ const node = particle.node;
378
+ // Skip if no node
379
+ if (!node) {
380
+ continue;
381
+ }
382
+ // Get current bone direction from node's world matrix (before physics)
383
+ // This reflects the current animation/skeleton state
384
+ const currentBonePos = new Vector3(node.worldMatrix.m03, node.worldMatrix.m13, node.worldMatrix.m23);
385
+ const nextNode = nextParticle.node;
386
+ if (!nextNode) {
387
+ continue;
388
+ }
389
+ const nextBonePos = new Vector3(nextNode.worldMatrix.m03, nextNode.worldMatrix.m13, nextNode.worldMatrix.m23);
390
+ const originalDir = Vector3.sub(nextBonePos, currentBonePos, new Vector3());
391
+ // Get current bone rotation from node's world matrix
392
+ const currentBoneRotation = new Quaternion();
393
+ node.worldMatrix.decompose(null, currentBoneRotation, null);
394
+ // Calculate new direction from physics simulation
395
+ const newDir = Vector3.sub(nextParticle.position, particle.position, new Vector3());
396
+ // Calculate rotation needed to align original direction to new direction
397
+ const deltaRotation = new Quaternion();
398
+ IKUtils.fromToRotation(originalDir, newDir, deltaRotation);
399
+ // Calculate new world rotation
400
+ let worldRotation = Quaternion.multiply(deltaRotation, currentBoneRotation, new Quaternion());
401
+ // Blend with current rotation based on weight
402
+ if (weight < 1) {
403
+ Quaternion.slerp(currentBoneRotation, worldRotation, weight, worldRotation);
404
+ }
405
+ // Convert world rotation to local rotation (relative to parent)
406
+ const parent = node.parent;
407
+ if (parent) {
408
+ const parentWorldRotation = new Quaternion();
409
+ parent.worldMatrix.decompose(null, parentWorldRotation, null);
410
+ // localRotation = conjugate(parentWorldRotation) * worldRotation
411
+ const parentInvRotation = Quaternion.conjugate(parentWorldRotation, new Quaternion());
412
+ const localRotation = Quaternion.multiply(parentInvRotation, worldRotation, new Quaternion());
413
+ node.rotation = localRotation;
414
+ } else {
415
+ // Root node has no parent, world rotation is local rotation
416
+ node.rotation = worldRotation;
417
+ }
418
+ }
419
+ }
420
+ /**
421
+ * Resets the simulation to initial state
422
+ */ reset() {
423
+ this._chain.reset();
424
+ }
425
+ /**
426
+ * Gets the spring chain
427
+ */ get chain() {
428
+ return this._chain;
429
+ }
430
+ /**
431
+ * Gets the current gravity
432
+ */ get gravity() {
433
+ return this._gravity;
434
+ }
435
+ set gravity(gravity) {
436
+ this._gravity.set(gravity);
437
+ }
438
+ /**
439
+ * Gets the current wind
440
+ */ get wind() {
441
+ return this._wind;
442
+ }
443
+ set wind(wind) {
444
+ this._wind.set(wind);
445
+ }
446
+ /**
447
+ * Gets the number of iterations
448
+ */ get iterations() {
449
+ return this._iterations;
450
+ }
451
+ set iterations(count) {
452
+ this._iterations = Math.max(1, count);
453
+ }
454
+ /**
455
+ * Gets whether inertial forces are enabled
456
+ */ get enableInertialForces() {
457
+ return this._enableInertialForces;
458
+ }
459
+ set enableInertialForces(enabled) {
460
+ this._enableInertialForces = enabled;
461
+ }
462
+ /**
463
+ * Gets the centrifugal force scale
464
+ */ get centrifugalScale() {
465
+ return this._centrifugalScale;
466
+ }
467
+ set centrifugalScale(scale) {
468
+ this._centrifugalScale = Math.max(0, scale);
469
+ }
470
+ /**
471
+ * Gets the Coriolis force scale
472
+ */ get coriolisScale() {
473
+ return this._coriolisScale;
474
+ }
475
+ /**
476
+ * Sets the Coriolis force scale
477
+ */ set coriolisScale(scale) {
478
+ this._coriolisScale = Math.max(0, scale);
479
+ }
480
+ /**
481
+ * Gets the constraint solver type
482
+ */ get solver() {
483
+ return this._solver;
484
+ }
485
+ /**
486
+ * Sets the constraint solver type.
487
+ * Switching to 'xpbd' resets all Lagrange multipliers.
488
+ */ set solver(type) {
489
+ if (this._solver !== type) {
490
+ this._solver = type;
491
+ if (type === 'xpbd') {
492
+ for (const c of this._chain.constraints){
493
+ c.lambda = 0;
494
+ }
495
+ }
496
+ }
497
+ }
498
+ /**
499
+ * Adds a collider to the system
500
+ */ addCollider(collider) {
501
+ this._colliders.push(collider);
502
+ }
503
+ /**
504
+ * Removes a collider from the system
505
+ */ removeCollider(collider) {
506
+ const index = this._colliders.indexOf(collider);
507
+ if (index >= 0) {
508
+ this._colliders.splice(index, 1);
509
+ return true;
510
+ }
511
+ return false;
512
+ }
513
+ /**
514
+ * Clears all colliders
515
+ */ clearColliders() {
516
+ this._colliders = [];
517
+ }
518
+ /**
519
+ * Gets all colliders
520
+ */ get colliders() {
521
+ return this._colliders;
522
+ }
523
+ }
524
+
525
+ export { SpringSystem };
526
+ //# sourceMappingURL=spring_system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spring_system.js","sources":["../../../src/animation/spring/spring_system.ts"],"sourcesContent":["import { Vector3, Quaternion } from '@zephyr3d/base';\r\nimport type { SpringChain } from './spring_chain';\r\nimport { IKUtils } from '../ik/ik_utils';\r\nimport type { SpringCollider } from './spring_collider';\r\nimport {\r\n resolveSphereCollision,\r\n resolveCapsuleCollision,\r\n resolvePlaneCollision,\r\n updateColliderFromNode\r\n} from './spring_collider';\r\n\r\n/**\r\n * Options for creating a SpringSystem\r\n *\r\n * @public\r\n */\r\nexport interface SpringSystemOptions {\r\n /** Number of constraint solver iterations (default: 5) */\r\n iterations?: number;\r\n /** Gravity force vector (default: (0, -9.8, 0)) */\r\n gravity?: Vector3;\r\n /** Wind force vector (default: (0, 0, 0)) */\r\n wind?: Vector3;\r\n /** Enable inertial forces (centrifugal/Coriolis) when root rotates (default: true) */\r\n enableInertialForces?: boolean;\r\n /** Centrifugal force multiplier (default: 1.0) */\r\n centrifugalScale?: number;\r\n /** Coriolis force multiplier (default: 1.0) */\r\n coriolisScale?: number;\r\n /**\r\n * Constraint solver type (default: 'verlet').\r\n * - 'verlet': Classic Verlet integration with iterative position correction.\r\n * stiffness [0-1] controls correction strength per iteration.\r\n * - 'xpbd': Extended Position-Based Dynamics (Müller et al. 2020).\r\n * Uses compliance (inverse stiffness in m/N) for physically correct,\r\n * iteration-count-independent constraint solving.\r\n */\r\n solver?: 'verlet' | 'xpbd';\r\n}\r\n\r\n/**\r\n * Physics engine for spring-based particle simulation\r\n * Uses Verlet integration and iterative constraint solving\r\n *\r\n * @public\r\n */\r\nexport class SpringSystem {\r\n private _chain: SpringChain;\r\n private _iterations: number;\r\n private _gravity: Vector3;\r\n private _wind: Vector3;\r\n private _enableInertialForces: boolean;\r\n private _centrifugalScale: number;\r\n private _coriolisScale: number;\r\n private _colliders: SpringCollider[];\r\n private _solver: 'verlet' | 'xpbd';\r\n\r\n constructor(chain: SpringChain, options?: SpringSystemOptions) {\r\n this._chain = chain;\r\n this._iterations = options?.iterations ?? 5;\r\n this._gravity = options?.gravity?.clone() ?? new Vector3(0, -9.8, 0);\r\n this._wind = options?.wind?.clone() ?? new Vector3(0, 0, 0);\r\n this._enableInertialForces = options?.enableInertialForces ?? true;\r\n this._centrifugalScale = options?.centrifugalScale ?? 1.0;\r\n this._coriolisScale = options?.coriolisScale ?? 1.0;\r\n this._colliders = [];\r\n this._solver = options?.solver ?? 'verlet';\r\n }\r\n\r\n /**\r\n * Updates the physics simulation\r\n * @param deltaTime - Time step in seconds\r\n */\r\n update(deltaTime: number): void {\r\n // Clamp deltaTime to prevent instability\r\n const dt = Math.min(deltaTime, 0.033); // Max 30 FPS\r\n\r\n // Step 1: Save all particle positions before updating\r\n if (this._enableInertialForces) {\r\n for (const p of this._chain.particles) {\r\n p.lastFramePosition.set(p.position);\r\n }\r\n }\r\n\r\n // Step 2: Update fixed particles from their scene nodes\r\n this.updateFixedParticles();\r\n\r\n // Step 3: Calculate global rotation parameters\r\n let rotationCenter: Vector3 | null = null;\r\n let angularVelocity: Vector3 | null = null;\r\n\r\n if (this._enableInertialForces && dt > 0.0001) {\r\n const result = this.calculateGlobalRotation(dt);\r\n rotationCenter = result.center;\r\n angularVelocity = result.omega;\r\n }\r\n\r\n // Step 4: Verlet integration with inertial forces\r\n for (let i = 0; i < this._chain.particles.length; i++) {\r\n const p = this._chain.particles[i];\r\n if (p.fixed) {\r\n continue;\r\n }\r\n\r\n // Calculate velocity (implicit in Verlet)\r\n const velocity = Vector3.sub(p.position, p.prevPosition, new Vector3());\r\n velocity.scaleBy(p.damping);\r\n\r\n // Apply external forces (gravity + wind)\r\n const acceleration = Vector3.add(this._gravity, this._wind, new Vector3());\r\n\r\n // Apply inertial forces from rotating reference frame\r\n if (this._enableInertialForces && rotationCenter && angularVelocity) {\r\n const inertialAccel = this.calculateInertialAcceleration(\r\n p,\r\n rotationCenter,\r\n angularVelocity,\r\n velocity,\r\n this._centrifugalScale,\r\n this._coriolisScale\r\n );\r\n Vector3.add(acceleration, inertialAccel, acceleration);\r\n }\r\n\r\n const positionDelta = Vector3.scale(acceleration, dt * dt, new Vector3());\r\n Vector3.add(velocity, positionDelta, velocity);\r\n\r\n // Update position\r\n p.prevPosition.set(p.position);\r\n Vector3.add(p.position, velocity, p.position);\r\n }\r\n\r\n // Step 5: Iteratively solve constraints\r\n if (this._solver === 'xpbd') {\r\n // Reset Lagrange multipliers at the start of each time step\r\n for (const constraint of this._chain.constraints) {\r\n constraint.lambda = 0;\r\n }\r\n }\r\n for (let iter = 0; iter < this._iterations; iter++) {\r\n for (const constraint of this._chain.constraints) {\r\n if (this._solver === 'xpbd') {\r\n this.solveConstraintXPBD(constraint, dt);\r\n } else {\r\n this.solveConstraint(constraint);\r\n }\r\n }\r\n\r\n // Apply collision constraints\r\n this.solveCollisions();\r\n }\r\n }\r\n\r\n /**\r\n * Updates fixed particles to match their scene node positions\r\n */\r\n private updateFixedParticles(): void {\r\n for (const particle of this._chain.particles) {\r\n if (particle.node && particle.fixed) {\r\n const worldMatrix = particle.node.worldMatrix;\r\n const worldPos = new Vector3(worldMatrix.m03, worldMatrix.m13, worldMatrix.m23);\r\n particle.position.set(worldPos);\r\n particle.prevPosition.set(worldPos);\r\n\r\n // Maintain position history for rotation center estimation\r\n if (this._enableInertialForces) {\r\n if (!particle.positionHistory) {\r\n particle.positionHistory = [];\r\n }\r\n particle.positionHistory.push(worldPos.clone());\r\n // Keep only last 5 frames\r\n if (particle.positionHistory.length > 5) {\r\n particle.positionHistory.shift();\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Calculates global rotation parameters from fixed particle movements\r\n * Uses position history to estimate rotation center\r\n */\r\n private calculateGlobalRotation(dt: number): { center: Vector3; omega: Vector3 } {\r\n // Collect fixed particles with movement\r\n const fixedParticles: any[] = [];\r\n const velocities: Vector3[] = [];\r\n\r\n for (const p of this._chain.particles) {\r\n if (!p.fixed) {\r\n continue;\r\n }\r\n\r\n const velocity = Vector3.sub(p.position, p.lastFramePosition, new Vector3());\r\n velocity.scaleBy(1.0 / dt);\r\n\r\n if (velocity.magnitudeSq > 0.001) {\r\n fixedParticles.push(p);\r\n velocities.push(velocity);\r\n }\r\n }\r\n\r\n if (fixedParticles.length === 0) {\r\n return { center: new Vector3(0, 0, 0), omega: new Vector3(0, 0, 0) };\r\n }\r\n\r\n // Estimate rotation center using position history\r\n let center: Vector3;\r\n\r\n if (fixedParticles.length === 1) {\r\n // Single fixed particle: use position history to estimate rotation center\r\n center = this.estimateRotationCenterFromHistory(fixedParticles[0], velocities[0]);\r\n } else {\r\n // Multiple fixed particles: use their average position\r\n center = new Vector3(0, 0, 0);\r\n for (const p of fixedParticles) {\r\n Vector3.add(center, p.position, center);\r\n }\r\n center.scaleBy(1.0 / fixedParticles.length);\r\n }\r\n\r\n // Estimate angular velocity\r\n let sumOmega = new Vector3(0, 0, 0);\r\n let count = 0;\r\n\r\n for (let i = 0; i < fixedParticles.length; i++) {\r\n const r = Vector3.sub(fixedParticles[i].position, center, new Vector3());\r\n const v = velocities[i];\r\n const rLengthSq = r.magnitudeSq;\r\n\r\n if (rLengthSq > 0.0001) {\r\n // ω = (r × v) / |r|²\r\n const omega = Vector3.cross(r, v, new Vector3());\r\n omega.scaleBy(1.0 / rLengthSq);\r\n Vector3.add(sumOmega, omega, sumOmega);\r\n count++;\r\n }\r\n }\r\n\r\n if (count > 0) {\r\n sumOmega.scaleBy(1.0 / count);\r\n }\r\n\r\n return { center, omega: sumOmega };\r\n }\r\n\r\n /**\r\n * Estimates rotation center from a single particle's position history\r\n * Uses circular motion fitting\r\n */\r\n private estimateRotationCenterFromHistory(particle: any, currentVelocity: Vector3): Vector3 {\r\n const history = particle.positionHistory;\r\n if (!history || history.length < 3) {\r\n // Not enough history: estimate using velocity perpendicular direction\r\n // Assume rotation center is perpendicular to velocity\r\n // Use a default radius based on velocity magnitude\r\n const speed = currentVelocity.magnitude;\r\n if (speed < 0.001) {\r\n return particle.position.clone();\r\n }\r\n\r\n // Estimate radius: for typical character rotation, assume ~0.5-1.0m radius\r\n const estimatedRadius = Math.max(0.5, speed * 0.5);\r\n\r\n // Direction perpendicular to velocity (in the plane of motion)\r\n // We need to guess which perpendicular direction - use cross product with up vector\r\n const up = new Vector3(0, 1, 0);\r\n const perpDir = Vector3.cross(currentVelocity, up, new Vector3());\r\n\r\n if (perpDir.magnitudeSq < 0.0001) {\r\n // Velocity is vertical, use another perpendicular\r\n perpDir.set(new Vector3(1, 0, 0));\r\n } else {\r\n perpDir.inplaceNormalize();\r\n }\r\n\r\n // Rotation center is perpendicular to velocity\r\n const center = Vector3.add(\r\n particle.position,\r\n Vector3.scale(perpDir, estimatedRadius, new Vector3()),\r\n new Vector3()\r\n );\r\n return center;\r\n }\r\n\r\n // Fit a circle through the last 3 positions\r\n // Use positions at indices: 0 (oldest), middle, last (newest)\r\n const p1 = history[0];\r\n const p2 = history[Math.floor(history.length / 2)];\r\n const p3 = history[history.length - 1];\r\n\r\n // Calculate circle center from 3 points\r\n const center = this.calculateCircleCenter(p1, p2, p3);\r\n return center;\r\n }\r\n\r\n /**\r\n * Calculates the center of a circle passing through 3 points\r\n * Uses perpendicular bisector method\r\n */\r\n private calculateCircleCenter(p1: Vector3, p2: Vector3, p3: Vector3): Vector3 {\r\n // Midpoints\r\n const mid12 = Vector3.scale(Vector3.add(p1, p2, new Vector3()), 0.5, new Vector3());\r\n const mid23 = Vector3.scale(Vector3.add(p2, p3, new Vector3()), 0.5, new Vector3());\r\n\r\n // Direction vectors\r\n const dir12 = Vector3.sub(p2, p1, new Vector3());\r\n const dir23 = Vector3.sub(p3, p2, new Vector3());\r\n\r\n // Normal vectors (perpendicular bisectors)\r\n // For 3D, we need to find perpendiculars in the plane of the three points\r\n const normal = Vector3.cross(dir12, dir23, new Vector3());\r\n\r\n if (normal.magnitudeSq < 0.0001) {\r\n // Points are collinear, return midpoint\r\n return Vector3.scale(\r\n Vector3.add(Vector3.add(p1, p2, new Vector3()), p3, new Vector3()),\r\n 1.0 / 3.0,\r\n new Vector3()\r\n );\r\n }\r\n\r\n normal.inplaceNormalize();\r\n\r\n // Perpendicular to dir12 in the plane\r\n const perp12 = Vector3.cross(dir12, normal, new Vector3()).inplaceNormalize();\r\n\r\n // Perpendicular to dir23 in the plane\r\n const perp23 = Vector3.cross(dir23, normal, new Vector3()).inplaceNormalize();\r\n\r\n // Find intersection of two lines:\r\n // Line 1: mid12 + t * perp12\r\n // Line 2: mid23 + s * perp23\r\n // Solve: mid12 + t * perp12 = mid23 + s * perp23\r\n\r\n const diff = Vector3.sub(mid23, mid12, new Vector3());\r\n\r\n // Use 2D projection for simplicity (project onto plane perpendicular to normal)\r\n // Solve in the plane: t * perp12 - s * perp23 = diff\r\n // Use least squares or pick the dominant components\r\n\r\n const det = perp12.x * perp23.y - perp12.y * perp23.x;\r\n\r\n if (Math.abs(det) > 0.0001) {\r\n const t = (diff.x * perp23.y - diff.y * perp23.x) / det;\r\n const center = Vector3.add(mid12, Vector3.scale(perp12, t, new Vector3()), new Vector3());\r\n return center;\r\n }\r\n\r\n // Fallback: use centroid\r\n return Vector3.scale(\r\n Vector3.add(Vector3.add(p1, p2, new Vector3()), p3, new Vector3()),\r\n 1.0 / 3.0,\r\n new Vector3()\r\n );\r\n }\r\n\r\n /**\r\n * Calculates inertial acceleration for a particle in a rotating reference frame\r\n */\r\n private calculateInertialAcceleration(\r\n particle: any,\r\n rotationCenter: Vector3,\r\n angularVelocity: Vector3,\r\n particleVelocity: Vector3,\r\n centrifugalScale: number,\r\n coriolisScale: number\r\n ): Vector3 {\r\n // Vector from rotation center to particle\r\n const r = Vector3.sub(particle.position, rotationCenter, new Vector3());\r\n\r\n // Centrifugal acceleration: a_centrifugal = ω × (ω × r)\r\n const omegaCrossR = Vector3.cross(angularVelocity, r, new Vector3());\r\n const centrifugalAccel = Vector3.cross(angularVelocity, omegaCrossR, new Vector3());\r\n centrifugalAccel.scaleBy(centrifugalScale);\r\n\r\n // Coriolis acceleration: a_coriolis = -2ω × v_relative\r\n // v_relative is the particle's velocity in the rotating frame\r\n // Use the velocity passed in (already calculated from prevPosition)\r\n const coriolisAccel = Vector3.cross(angularVelocity, particleVelocity, new Vector3());\r\n coriolisAccel.scaleBy(-2.0 * coriolisScale);\r\n\r\n // Total inertial acceleration\r\n const totalAccel = Vector3.add(centrifugalAccel, coriolisAccel, new Vector3());\r\n return totalAccel;\r\n }\r\n\r\n /**\r\n * Solves a single spring constraint using XPBD (Extended Position-Based Dynamics).\r\n *\r\n * Reference: Müller et al., \"Detailed Rigid Body Simulation with Extended Position Based Dynamics\", 2020.\r\n *\r\n * The XPBD correction for a distance constraint C(x) = |x_b - x_a| - L is:\r\n * α̃ = compliance / dt² (scaled compliance)\r\n * Δλ = (-C - α̃·λ) / (w_a + w_b + α̃)\r\n * λ += Δλ\r\n * Δx_a = -w_a · Δλ · n̂\r\n * Δx_b = +w_b · Δλ · n̂\r\n * where w = 1/mass (0 for fixed particles), n̂ = unit vector from a to b.\r\n */\r\n private solveConstraintXPBD(constraint: any, dt: number): void {\r\n const pA = this._chain.particles[constraint.particleA];\r\n const pB = this._chain.particles[constraint.particleB];\r\n\r\n const wA = pA.fixed ? 0 : 1.0 / pA.mass;\r\n const wB = pB.fixed ? 0 : 1.0 / pB.mass;\r\n const wSum = wA + wB;\r\n if (wSum < 1e-10) {\r\n return;\r\n }\r\n\r\n const delta = Vector3.sub(pB.position, pA.position, new Vector3());\r\n const currentLength = delta.magnitude;\r\n if (currentLength < 0.0001) {\r\n return;\r\n }\r\n\r\n // Constraint value C = currentLength - restLength\r\n const C = currentLength - constraint.restLength;\r\n\r\n // Scaled compliance: α̃ = compliance / dt²\r\n const alphaTilde = constraint.compliance / (dt * dt);\r\n\r\n // XPBD Lagrange multiplier update\r\n const deltaLambda = (-C - alphaTilde * constraint.lambda) / (wSum + alphaTilde);\r\n constraint.lambda += deltaLambda;\r\n\r\n // Correction direction (unit vector from A to B)\r\n const n = Vector3.scale(delta, 1.0 / currentLength, new Vector3());\r\n\r\n if (!pA.fixed) {\r\n // Δx_a = -w_a · Δλ · n̂\r\n Vector3.add(pA.position, Vector3.scale(n, -wA * deltaLambda, new Vector3()), pA.position);\r\n }\r\n if (!pB.fixed) {\r\n // Δx_b = +w_b · Δλ · n̂\r\n Vector3.add(pB.position, Vector3.scale(n, wB * deltaLambda, new Vector3()), pB.position);\r\n }\r\n }\r\n\r\n /**\r\n * Solves a single spring constraint (Verlet / PBD)\r\n */\r\n private solveConstraint(constraint: any): void {\r\n const pA = this._chain.particles[constraint.particleA];\r\n const pB = this._chain.particles[constraint.particleB];\r\n\r\n // Calculate current distance\r\n const delta = Vector3.sub(pB.position, pA.position, new Vector3());\r\n const currentLength = delta.magnitude;\r\n\r\n if (currentLength < 0.0001) {\r\n return;\r\n } // Avoid division by zero\r\n\r\n // Calculate correction\r\n const diff = (currentLength - constraint.restLength) / currentLength;\r\n const correction = Vector3.scale(delta, diff * constraint.stiffness * 0.5, new Vector3());\r\n\r\n // Apply correction (considering mass and fixed state)\r\n if (!pA.fixed) {\r\n Vector3.add(pA.position, correction, pA.position);\r\n }\r\n if (!pB.fixed) {\r\n Vector3.sub(pB.position, correction, pB.position);\r\n }\r\n }\r\n\r\n /**\r\n * Solves collisions for all particles\r\n */\r\n private solveCollisions(): void {\r\n // Update dynamic colliders from their nodes\r\n for (const collider of this._colliders) {\r\n if (collider.node) {\r\n updateColliderFromNode(collider);\r\n }\r\n }\r\n\r\n // Check each particle against all colliders\r\n for (const particle of this._chain.particles) {\r\n if (particle.fixed) {\r\n continue; // Skip fixed particles\r\n }\r\n\r\n for (const collider of this._colliders) {\r\n if (!collider.enabled) {\r\n continue;\r\n }\r\n\r\n switch (collider.type) {\r\n case 'sphere':\r\n resolveSphereCollision(particle.position, collider as any);\r\n break;\r\n case 'capsule':\r\n resolveCapsuleCollision(particle.position, collider as any);\r\n break;\r\n case 'plane':\r\n resolvePlaneCollision(particle.position, collider as any);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Applies simulation results to scene nodes\r\n * @param weight - Blend weight [0-1] (default: 1.0)\r\n */\r\n applyToNodes(weight: number = 1.0): void {\r\n for (let i = 0; i < this._chain.particles.length - 1; i++) {\r\n const particle = this._chain.particles[i];\r\n const nextParticle = this._chain.particles[i + 1];\r\n const node = particle.node;\r\n\r\n // Skip if no node\r\n if (!node) {\r\n continue;\r\n }\r\n\r\n // Get current bone direction from node's world matrix (before physics)\r\n // This reflects the current animation/skeleton state\r\n const currentBonePos = new Vector3(node.worldMatrix.m03, node.worldMatrix.m13, node.worldMatrix.m23);\r\n\r\n const nextNode = nextParticle.node;\r\n if (!nextNode) {\r\n continue;\r\n }\r\n\r\n const nextBonePos = new Vector3(\r\n nextNode.worldMatrix.m03,\r\n nextNode.worldMatrix.m13,\r\n nextNode.worldMatrix.m23\r\n );\r\n const originalDir = Vector3.sub(nextBonePos, currentBonePos, new Vector3());\r\n\r\n // Get current bone rotation from node's world matrix\r\n const currentBoneRotation = new Quaternion();\r\n node.worldMatrix.decompose(null, currentBoneRotation, null);\r\n\r\n // Calculate new direction from physics simulation\r\n const newDir = Vector3.sub(nextParticle.position, particle.position, new Vector3());\r\n\r\n // Calculate rotation needed to align original direction to new direction\r\n const deltaRotation = new Quaternion();\r\n IKUtils.fromToRotation(originalDir, newDir, deltaRotation);\r\n\r\n // Calculate new world rotation\r\n let worldRotation = Quaternion.multiply(deltaRotation, currentBoneRotation, new Quaternion());\r\n\r\n // Blend with current rotation based on weight\r\n if (weight < 1) {\r\n Quaternion.slerp(currentBoneRotation, worldRotation, weight, worldRotation);\r\n }\r\n\r\n // Convert world rotation to local rotation (relative to parent)\r\n const parent = node.parent;\r\n if (parent) {\r\n const parentWorldRotation = new Quaternion();\r\n parent.worldMatrix.decompose(null, parentWorldRotation, null);\r\n\r\n // localRotation = conjugate(parentWorldRotation) * worldRotation\r\n const parentInvRotation = Quaternion.conjugate(parentWorldRotation, new Quaternion());\r\n const localRotation = Quaternion.multiply(parentInvRotation, worldRotation, new Quaternion());\r\n\r\n node.rotation = localRotation;\r\n } else {\r\n // Root node has no parent, world rotation is local rotation\r\n node.rotation = worldRotation;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Resets the simulation to initial state\r\n */\r\n reset(): void {\r\n this._chain.reset();\r\n }\r\n\r\n /**\r\n * Gets the spring chain\r\n */\r\n get chain(): SpringChain {\r\n return this._chain;\r\n }\r\n\r\n /**\r\n * Gets the current gravity\r\n */\r\n get gravity(): Vector3 {\r\n return this._gravity;\r\n }\r\n\r\n set gravity(gravity: Vector3) {\r\n this._gravity.set(gravity);\r\n }\r\n\r\n /**\r\n * Gets the current wind\r\n */\r\n get wind(): Vector3 {\r\n return this._wind;\r\n }\r\n\r\n set wind(wind: Vector3) {\r\n this._wind.set(wind);\r\n }\r\n\r\n /**\r\n * Gets the number of iterations\r\n */\r\n get iterations(): number {\r\n return this._iterations;\r\n }\r\n\r\n set iterations(count: number) {\r\n this._iterations = Math.max(1, count);\r\n }\r\n\r\n /**\r\n * Gets whether inertial forces are enabled\r\n */\r\n get enableInertialForces(): boolean {\r\n return this._enableInertialForces;\r\n }\r\n\r\n set enableInertialForces(enabled: boolean) {\r\n this._enableInertialForces = enabled;\r\n }\r\n\r\n /**\r\n * Gets the centrifugal force scale\r\n */\r\n get centrifugalScale(): number {\r\n return this._centrifugalScale;\r\n }\r\n\r\n set centrifugalScale(scale: number) {\r\n this._centrifugalScale = Math.max(0, scale);\r\n }\r\n\r\n /**\r\n * Gets the Coriolis force scale\r\n */\r\n get coriolisScale(): number {\r\n return this._coriolisScale;\r\n }\r\n\r\n /**\r\n * Sets the Coriolis force scale\r\n */\r\n set coriolisScale(scale: number) {\r\n this._coriolisScale = Math.max(0, scale);\r\n }\r\n\r\n /**\r\n * Gets the constraint solver type\r\n */\r\n get solver(): 'verlet' | 'xpbd' {\r\n return this._solver;\r\n }\r\n\r\n /**\r\n * Sets the constraint solver type.\r\n * Switching to 'xpbd' resets all Lagrange multipliers.\r\n */\r\n set solver(type: 'verlet' | 'xpbd') {\r\n if (this._solver !== type) {\r\n this._solver = type;\r\n if (type === 'xpbd') {\r\n for (const c of this._chain.constraints) {\r\n c.lambda = 0;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Adds a collider to the system\r\n */\r\n addCollider(collider: SpringCollider): void {\r\n this._colliders.push(collider);\r\n }\r\n\r\n /**\r\n * Removes a collider from the system\r\n */\r\n removeCollider(collider: SpringCollider): boolean {\r\n const index = this._colliders.indexOf(collider);\r\n if (index >= 0) {\r\n this._colliders.splice(index, 1);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Clears all colliders\r\n */\r\n clearColliders(): void {\r\n this._colliders = [];\r\n }\r\n\r\n /**\r\n * Gets all colliders\r\n */\r\n get colliders(): SpringCollider[] {\r\n return this._colliders;\r\n }\r\n}\r\n"],"names":["SpringSystem","_chain","_iterations","_gravity","_wind","_enableInertialForces","_centrifugalScale","_coriolisScale","_colliders","_solver","chain","options","iterations","gravity","clone","Vector3","wind","enableInertialForces","centrifugalScale","coriolisScale","solver","update","deltaTime","dt","Math","min","p","particles","lastFramePosition","set","position","updateFixedParticles","rotationCenter","angularVelocity","result","calculateGlobalRotation","center","omega","i","length","fixed","velocity","sub","prevPosition","scaleBy","damping","acceleration","add","inertialAccel","calculateInertialAcceleration","positionDelta","scale","constraint","constraints","lambda","iter","solveConstraintXPBD","solveConstraint","solveCollisions","particle","node","worldMatrix","worldPos","m03","m13","m23","positionHistory","push","shift","fixedParticles","velocities","magnitudeSq","estimateRotationCenterFromHistory","sumOmega","count","r","v","rLengthSq","cross","currentVelocity","history","speed","magnitude","estimatedRadius","max","up","perpDir","inplaceNormalize","p1","p2","floor","p3","calculateCircleCenter","mid12","mid23","dir12","dir23","normal","perp12","perp23","diff","det","x","y","abs","t","particleVelocity","omegaCrossR","centrifugalAccel","coriolisAccel","totalAccel","pA","particleA","pB","particleB","wA","mass","wB","wSum","delta","currentLength","C","restLength","alphaTilde","compliance","deltaLambda","n","correction","stiffness","collider","updateColliderFromNode","enabled","type","resolveSphereCollision","resolveCapsuleCollision","resolvePlaneCollision","applyToNodes","weight","nextParticle","currentBonePos","nextNode","nextBonePos","originalDir","currentBoneRotation","Quaternion","decompose","newDir","deltaRotation","IKUtils","fromToRotation","worldRotation","multiply","slerp","parent","parentWorldRotation","parentInvRotation","conjugate","localRotation","rotation","reset","c","addCollider","removeCollider","index","indexOf","splice","clearColliders","colliders"],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { SkeletonModifier } from './skeleton_modifier.js';
2
+
3
+ /**
4
+ * Post-processor wrapper for spring physics systems.
5
+ *
6
+ * Integrates spring-based physics simulation into the skeleton post-processing pipeline.
7
+ * The spring system is updated each frame and results are blended with the base animation.
8
+ *
9
+ * @public
10
+ */ class SpringModifier extends SkeletonModifier {
11
+ _springSystem;
12
+ /**
13
+ * Create a spring post-processor.
14
+ *
15
+ * @param springSystem - The spring system to integrate
16
+ * @param weight - Blend weight [0-1] (default: 1.0)
17
+ */ constructor(springSystem, weight = 1.0){
18
+ super(weight);
19
+ this._springSystem = springSystem;
20
+ }
21
+ /**
22
+ * Get the spring system.
23
+ */ get springSystem() {
24
+ return this._springSystem;
25
+ }
26
+ /**
27
+ * Apply spring physics to skeleton joints.
28
+ */ apply(_skeleton, deltaTime) {
29
+ if (!this._enabled || this._weight <= 0) {
30
+ return;
31
+ }
32
+ // Update spring physics simulation
33
+ this._springSystem.update(deltaTime);
34
+ // Apply results to scene nodes with blending
35
+ this._springSystem.applyToNodes(this._weight);
36
+ }
37
+ /**
38
+ * Reset the spring system to initial state.
39
+ */ reset() {
40
+ this._springSystem.reset();
41
+ }
42
+ }
43
+
44
+ export { SpringModifier };
45
+ //# sourceMappingURL=spring_modifier.js.map