@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,372 @@
1
+ import { Vector3, Quaternion } from '@zephyr3d/base';
2
+ import { IKSolver } from './ik_solver.js';
3
+ import { IKUtils } from './ik_utils.js';
4
+
5
+ /**
6
+ * CCD (Cyclic Coordinate Descent) IK solver.
7
+ *
8
+ * @remarks
9
+ * CCD is an iterative IK algorithm that works by:
10
+ * 1. Starting from the joint closest to the end effector
11
+ * 2. Rotating each joint to point the end effector toward the target
12
+ * 3. Moving backward through the chain to the root
13
+ * 4. Repeating until convergence or max iterations
14
+ *
15
+ * CCD is generally faster than FABRIK and works well for chains of any length.
16
+ * It's particularly good for tentacles, tails, and other flexible chains.
17
+ *
18
+ * Supports multiple pole vectors to control the bending direction of different joints.
19
+ *
20
+ * @public
21
+ */ class CCDSolver extends IKSolver {
22
+ /** Map of joint index to pole vector configuration */ _poleVectors;
23
+ /** Twist constraints for each joint (indexed by joint index) */ _twistConstraints;
24
+ /**
25
+ * Create a CCD solver.
26
+ *
27
+ * @param chain - The IK chain to solve
28
+ * @param maxIterations - Maximum number of iterations (default: 10)
29
+ * @param tolerance - Convergence tolerance in world units (default: 0.001)
30
+ */ constructor(chain, maxIterations = 10, tolerance = 0.001){
31
+ super(chain, maxIterations, tolerance);
32
+ this._poleVectors = new Map();
33
+ this._twistConstraints = new Map();
34
+ // Set default twist constraints for all joints
35
+ for(let i = 0; i < chain.joints.length - 1; i++){
36
+ // Middle joints have more restrictive twist limits
37
+ const isMiddleJoint = i > 0 && i < chain.joints.length - 2;
38
+ this._twistConstraints.set(i, {
39
+ minTwist: isMiddleJoint ? -Math.PI * 0.2 : -Math.PI * 0.3,
40
+ maxTwist: isMiddleJoint ? Math.PI * 0.2 : Math.PI * 0.3,
41
+ smoothFactor: 0.3
42
+ });
43
+ }
44
+ }
45
+ /**
46
+ * Set twist constraint for a specific joint.
47
+ *
48
+ * @param jointIndex - Index of the joint
49
+ * @param minTwist - Minimum twist angle in radians
50
+ * @param maxTwist - Maximum twist angle in radians
51
+ * @param smoothFactor - Smoothing factor [0-1] (default: 0.3)
52
+ */ setTwistConstraint(jointIndex, minTwist, maxTwist, smoothFactor = 0.3) {
53
+ if (jointIndex < 0 || jointIndex >= this._chain.joints.length - 1) {
54
+ throw new Error(`Invalid joint index: ${jointIndex}`);
55
+ }
56
+ this._twistConstraints.set(jointIndex, {
57
+ minTwist,
58
+ maxTwist,
59
+ smoothFactor: Math.max(0, Math.min(1, smoothFactor))
60
+ });
61
+ }
62
+ /**
63
+ * Get twist constraint for a specific joint.
64
+ *
65
+ * @param jointIndex - Index of the joint
66
+ * @returns Twist constraint or undefined if not set
67
+ */ getTwistConstraint(jointIndex) {
68
+ return this._twistConstraints.get(jointIndex);
69
+ }
70
+ /**
71
+ * Remove twist constraint for a specific joint.
72
+ *
73
+ * @param jointIndex - Index of the joint
74
+ * @returns True if a constraint was removed
75
+ */ removeTwistConstraint(jointIndex) {
76
+ return this._twistConstraints.delete(jointIndex);
77
+ }
78
+ /**
79
+ * Clear all twist constraints.
80
+ */ clearTwistConstraints() {
81
+ this._twistConstraints.clear();
82
+ }
83
+ /**
84
+ * Set pole vector for a specific joint.
85
+ *
86
+ * @param jointIndex - Index of the joint to apply pole vector to
87
+ * @param poleVector - Pole vector position in world space
88
+ * @param weight - Weight of the pole vector constraint (0-1, default: 1)
89
+ */ setPoleVector(jointIndex, poleVector, weight = 1) {
90
+ if (jointIndex < 0 || jointIndex >= this._chain.joints.length) {
91
+ throw new Error(`Invalid joint index: ${jointIndex}`);
92
+ }
93
+ this._poleVectors.set(jointIndex, {
94
+ position: poleVector.clone(),
95
+ weight: Math.max(0, Math.min(1, weight))
96
+ });
97
+ }
98
+ /**
99
+ * Remove pole vector for a specific joint.
100
+ *
101
+ * @param jointIndex - Index of the joint to remove pole vector from
102
+ * @returns True if a pole vector was removed, false if none existed
103
+ */ removePoleVector(jointIndex) {
104
+ return this._poleVectors.delete(jointIndex);
105
+ }
106
+ /**
107
+ * Clear all pole vectors.
108
+ */ clearPoleVectors() {
109
+ this._poleVectors.clear();
110
+ }
111
+ /**
112
+ * Get pole vector configuration for a specific joint.
113
+ *
114
+ * @param jointIndex - Index of the joint
115
+ * @returns Pole vector configuration or undefined if not set
116
+ */ getPoleVector(jointIndex) {
117
+ const config = this._poleVectors.get(jointIndex);
118
+ if (config) {
119
+ return {
120
+ position: config.position.clone(),
121
+ weight: config.weight
122
+ };
123
+ }
124
+ return undefined;
125
+ }
126
+ /**
127
+ * Check if a joint has a pole vector.
128
+ *
129
+ * @param jointIndex - Index of the joint
130
+ * @returns True if the joint has a pole vector
131
+ */ hasPoleVector(jointIndex) {
132
+ return this._poleVectors.has(jointIndex);
133
+ }
134
+ /**
135
+ * Solve the IK chain to reach the target position using CCD algorithm.
136
+ *
137
+ * @param target - Target position for the end effector
138
+ * @returns True if converged within tolerance, false otherwise
139
+ */ solve(target) {
140
+ const joints = this._chain.joints;
141
+ // Update joint positions from scene nodes before solving
142
+ this._chain.updateFromNodes();
143
+ // Store original positions
144
+ this._chain.storeOriginalPositions();
145
+ let converged = false;
146
+ for(let iteration = 0; iteration < this._maxIterations; iteration++){
147
+ // Check convergence
148
+ const endEffector = joints[joints.length - 1];
149
+ const distToTarget = Vector3.distance(endEffector.position, target);
150
+ if (distToTarget < this._tolerance) {
151
+ converged = true;
152
+ break;
153
+ }
154
+ // Iterate backward through joints (from second-to-last to root)
155
+ // We skip the end effector itself since it doesn't have a child to rotate toward
156
+ for(let i = joints.length - 2; i >= 0; i--){
157
+ const joint = joints[i];
158
+ // Vector from current joint to end effector
159
+ const toEnd = Vector3.sub(endEffector.position, joint.position, new Vector3());
160
+ const toEndDist = toEnd.magnitude;
161
+ // Vector from current joint to target
162
+ const toTarget = Vector3.sub(target, joint.position, new Vector3());
163
+ const toTargetDist = toTarget.magnitude;
164
+ // Skip if either vector is too small
165
+ if (toEndDist < 0.000001 || toTargetDist < 0.000001) {
166
+ continue;
167
+ }
168
+ // Normalize vectors
169
+ const toEndDir = Vector3.scale(toEnd, 1 / toEndDist, new Vector3());
170
+ const toTargetDir = Vector3.scale(toTarget, 1 / toTargetDist, new Vector3());
171
+ // Calculate rotation needed to align end effector toward target
172
+ let rotation = new Quaternion();
173
+ IKUtils.fromToRotation(toEndDir, toTargetDir, rotation);
174
+ // Apply rotation to all joints from current to end effector
175
+ this._rotateJointsFromIndex(i, rotation, joint.position);
176
+ // Apply constraints after rotating this joint
177
+ this._applyConstraintsForJoint(i);
178
+ }
179
+ // Apply all pole vector constraints after each full iteration
180
+ // This is more stable than applying them during the CCD loop
181
+ this._applyAllPoleVectors();
182
+ }
183
+ return converged;
184
+ }
185
+ /**
186
+ * Rotate all joints from the given index to the end effector around a pivot point.
187
+ *
188
+ * @param startIndex - Index of the joint to start rotating from
189
+ * @param rotation - Rotation to apply
190
+ * @param pivot - Pivot point for rotation (position of the joint being adjusted)
191
+ */ _rotateJointsFromIndex(startIndex, rotation, pivot) {
192
+ const joints = this._chain.joints;
193
+ // Rotate all joints from startIndex+1 to end effector
194
+ for(let i = startIndex + 1; i < joints.length; i++){
195
+ const joint = joints[i];
196
+ // Translate to pivot
197
+ const offset = Vector3.sub(joint.position, pivot, new Vector3());
198
+ // Rotate around pivot
199
+ const rotated = rotation.transform(offset, new Vector3());
200
+ // Translate back
201
+ joint.position.set(Vector3.add(pivot, rotated, new Vector3()));
202
+ }
203
+ }
204
+ /**
205
+ * Apply all pole vector constraints.
206
+ *
207
+ * @remarks
208
+ * This method applies all configured pole vectors to their respective joints.
209
+ * Pole vectors are applied in reverse order (from end to root) to minimize
210
+ * interference between multiple pole vectors. This ensures that pole vectors
211
+ * closer to the end effector are not affected by pole vectors closer to the root.
212
+ */ _applyAllPoleVectors() {
213
+ if (this._poleVectors.size === 0) {
214
+ return;
215
+ }
216
+ // Apply pole vectors in reverse order (from end to root)
217
+ // This prevents earlier pole vectors from affecting later ones
218
+ const sortedIndices = Array.from(this._poleVectors.keys()).sort((a, b)=>b - a);
219
+ for (const jointIndex of sortedIndices){
220
+ const config = this._poleVectors.get(jointIndex);
221
+ if (config && config.weight > 0.001) {
222
+ this._applyPoleVectorTwist(jointIndex, config.position, config.weight);
223
+ }
224
+ }
225
+ }
226
+ /**
227
+ * Apply pole vector twist to a specific joint.
228
+ *
229
+ * @remarks
230
+ * This method is called after the base CCD rotation has been applied.
231
+ * It adds an additional twist rotation around the joint-to-end axis
232
+ * to make the next joint (child) bend toward the pole vector.
233
+ *
234
+ * @param jointIndex - Index of the pole joint
235
+ * @param poleVector - Pole vector position in world space
236
+ * @param weight - Weight of the pole vector constraint (0-1)
237
+ */ _applyPoleVectorTwist(jointIndex, poleVector, weight) {
238
+ const joints = this._chain.joints;
239
+ // We need at least 3 joints to apply pole vector (parent, pole joint, child)
240
+ if (jointIndex < 1 || jointIndex >= joints.length - 1) {
241
+ return;
242
+ }
243
+ const parentJoint = joints[jointIndex - 1];
244
+ const currentJoint = joints[jointIndex];
245
+ const childJoint = joints[jointIndex + 1];
246
+ const parentPos = parentJoint.position;
247
+ const currentPos = currentJoint.position;
248
+ const childPos = childJoint.position;
249
+ // Calculate the plane defined by parent, child, and pole vector
250
+ // Vector from parent to child (the "line" we're bending around)
251
+ const parentToChild = Vector3.sub(childPos, parentPos, new Vector3());
252
+ const lineLength = parentToChild.magnitude;
253
+ if (lineLength < 0.000001) {
254
+ return; // Parent and child are at same position
255
+ }
256
+ const lineDir = Vector3.scale(parentToChild, 1 / lineLength, new Vector3());
257
+ // Project current joint onto the parent-child line
258
+ const parentToCurrent = Vector3.sub(currentPos, parentPos, new Vector3());
259
+ const projectionLength = Vector3.dot(parentToCurrent, lineDir);
260
+ const projectionPoint = Vector3.scale(lineDir, projectionLength, new Vector3());
261
+ Vector3.add(parentPos, projectionPoint, projectionPoint);
262
+ // Vector from projection point to current joint (perpendicular to line)
263
+ const perpendicular = Vector3.sub(currentPos, projectionPoint, new Vector3());
264
+ const perpLength = perpendicular.magnitude;
265
+ if (perpLength < 0.000001) {
266
+ return; // Current joint is on the line
267
+ }
268
+ // Calculate desired direction toward pole vector
269
+ const parentToPole = Vector3.sub(poleVector, parentPos, new Vector3());
270
+ const poleProjectionLength = Vector3.dot(parentToPole, lineDir);
271
+ const poleProjectionPoint = Vector3.scale(lineDir, poleProjectionLength, new Vector3());
272
+ Vector3.add(parentPos, poleProjectionPoint, poleProjectionPoint);
273
+ // Direction from projection to pole (perpendicular to line)
274
+ const poleDirection = Vector3.sub(poleVector, poleProjectionPoint, new Vector3());
275
+ const poleDirLength = poleDirection.magnitude;
276
+ if (poleDirLength < 0.000001) {
277
+ return; // Pole is on the line
278
+ }
279
+ poleDirection.scaleBy(1 / poleDirLength);
280
+ // Calculate new position for current joint
281
+ // Keep the same distance from the line, but rotate toward pole direction
282
+ const desiredPerpendicular = Vector3.scale(poleDirection, perpLength, new Vector3());
283
+ const newPosition = Vector3.add(projectionPoint, desiredPerpendicular, new Vector3());
284
+ // Apply weight (blend between original and constrained position)
285
+ if (weight < 0.999) {
286
+ const blended = new Vector3();
287
+ blended.x = currentPos.x + (newPosition.x - currentPos.x) * weight;
288
+ blended.y = currentPos.y + (newPosition.y - currentPos.y) * weight;
289
+ blended.z = currentPos.z + (newPosition.z - currentPos.z) * weight;
290
+ currentJoint.position.set(blended);
291
+ } else {
292
+ currentJoint.position.set(newPosition);
293
+ }
294
+ }
295
+ /**
296
+ * Apply constraints for a specific joint.
297
+ *
298
+ * @param jointIndex - Index of the joint to apply constraints to
299
+ */ _applyConstraintsForJoint(jointIndex) {
300
+ const constraints = this._chain.constraints;
301
+ for (const constraint of constraints){
302
+ if (constraint.jointIndex === jointIndex) {
303
+ constraint.apply(this._chain.joints);
304
+ }
305
+ }
306
+ }
307
+ /**
308
+ * Apply the solved joint positions to scene nodes as rotations.
309
+ *
310
+ * @param weight - Blend weight (0 = original, 1 = full IK, default: 1)
311
+ */ applyToNodes(weight = 1) {
312
+ const joints = this._chain.joints;
313
+ // Apply rotation for all joints except the end effector
314
+ for(let i = 0; i < joints.length - 1; i++){
315
+ const joint = joints[i];
316
+ const nextJoint = joints[i + 1];
317
+ // Calculate direction from current joint to next joint in world space
318
+ const originalDir = Vector3.sub(nextJoint.originalPosition, joint.originalPosition, new Vector3());
319
+ const newDir = Vector3.sub(nextJoint.position, joint.position, new Vector3());
320
+ const originalDirNorm = Vector3.normalize(originalDir, new Vector3());
321
+ const newDirNorm = Vector3.normalize(newDir, new Vector3());
322
+ // Calculate basic rotation
323
+ const deltaRotation = new Quaternion();
324
+ IKUtils.fromToRotation(originalDirNorm, newDirNorm, deltaRotation);
325
+ // Calculate new world rotation
326
+ let worldRotation = Quaternion.multiply(deltaRotation, joint.originalRotation, new Quaternion());
327
+ // Apply swing-twist constraint to prevent over-rotation
328
+ const swing = new Quaternion();
329
+ const twist = new Quaternion();
330
+ IKUtils.decomposeSwingTwist(worldRotation, newDirNorm, swing, twist);
331
+ // Get twist angle
332
+ let twistAngle = IKUtils.getTwistAngle(twist, newDirNorm);
333
+ // Get twist constraint for this joint
334
+ const constraint = this._twistConstraints.get(i);
335
+ if (constraint) {
336
+ // Clamp and smooth twist
337
+ twistAngle = IKUtils.clampAndSmoothTwist(twistAngle, joint.previousTwist, constraint.minTwist, constraint.maxTwist, constraint.smoothFactor);
338
+ }
339
+ // Store for next frame
340
+ joint.previousTwist = twistAngle;
341
+ // Reconstruct rotation from clamped twist: Q = Twist * Swing
342
+ const clampedTwist = new Quaternion();
343
+ IKUtils.createTwist(twistAngle, newDirNorm, clampedTwist);
344
+ worldRotation = Quaternion.multiply(clampedTwist, swing, worldRotation);
345
+ // Blend with original rotation based on weight
346
+ if (weight < 1) {
347
+ Quaternion.slerp(joint.originalRotation, worldRotation, weight, worldRotation);
348
+ }
349
+ // Store this frame's world rotation for next frame's twist continuity
350
+ if (!joint.previousIKRotation) {
351
+ joint.previousIKRotation = worldRotation.clone();
352
+ } else {
353
+ joint.previousIKRotation.set(worldRotation);
354
+ }
355
+ // Convert world rotation to local rotation (relative to parent)
356
+ if (joint.node.parent) {
357
+ const parentWorldRotation = new Quaternion();
358
+ joint.node.parent.worldMatrix.decompose(null, parentWorldRotation, null);
359
+ // localRotation = conjugate(parentWorldRotation) * worldRotation
360
+ const parentInvRotation = Quaternion.conjugate(parentWorldRotation, new Quaternion());
361
+ const localRotation = Quaternion.multiply(parentInvRotation, worldRotation, new Quaternion());
362
+ joint.node.rotation = localRotation;
363
+ } else {
364
+ // Root node has no parent, world rotation is local rotation
365
+ joint.node.rotation = worldRotation;
366
+ }
367
+ }
368
+ }
369
+ }
370
+
371
+ export { CCDSolver };
372
+ //# sourceMappingURL=ccd_solver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ccd_solver.js","sources":["../../../src/animation/ik/ccd_solver.ts"],"sourcesContent":["import { Vector3, Quaternion } from '@zephyr3d/base';\r\nimport { IKSolver } from './ik_solver';\r\nimport type { IKChain } from './ik_chain';\r\nimport { IKUtils } from './ik_utils';\r\nimport type { TwistConstraint } from './ik_constraint';\r\n\r\n/**\r\n * Pole vector configuration for a specific joint.\r\n */\r\ninterface PoleVectorConfig {\r\n /** Pole vector position in world space */\r\n position: Vector3;\r\n /** Weight of the pole vector constraint (0-1) */\r\n weight: number;\r\n}\r\n\r\n/**\r\n * CCD (Cyclic Coordinate Descent) IK solver.\r\n *\r\n * @remarks\r\n * CCD is an iterative IK algorithm that works by:\r\n * 1. Starting from the joint closest to the end effector\r\n * 2. Rotating each joint to point the end effector toward the target\r\n * 3. Moving backward through the chain to the root\r\n * 4. Repeating until convergence or max iterations\r\n *\r\n * CCD is generally faster than FABRIK and works well for chains of any length.\r\n * It's particularly good for tentacles, tails, and other flexible chains.\r\n *\r\n * Supports multiple pole vectors to control the bending direction of different joints.\r\n *\r\n * @public\r\n */\r\nexport class CCDSolver extends IKSolver {\r\n /** Map of joint index to pole vector configuration */\r\n private _poleVectors: Map<number, PoleVectorConfig>;\r\n /** Twist constraints for each joint (indexed by joint index) */\r\n private _twistConstraints: Map<number, TwistConstraint>;\r\n\r\n /**\r\n * Create a CCD solver.\r\n *\r\n * @param chain - The IK chain to solve\r\n * @param maxIterations - Maximum number of iterations (default: 10)\r\n * @param tolerance - Convergence tolerance in world units (default: 0.001)\r\n */\r\n constructor(chain: IKChain, maxIterations = 10, tolerance = 0.001) {\r\n super(chain, maxIterations, tolerance);\r\n this._poleVectors = new Map();\r\n this._twistConstraints = new Map();\r\n\r\n // Set default twist constraints for all joints\r\n for (let i = 0; i < chain.joints.length - 1; i++) {\r\n // Middle joints have more restrictive twist limits\r\n const isMiddleJoint = i > 0 && i < chain.joints.length - 2;\r\n this._twistConstraints.set(i, {\r\n minTwist: isMiddleJoint ? -Math.PI * 0.2 : -Math.PI * 0.3,\r\n maxTwist: isMiddleJoint ? Math.PI * 0.2 : Math.PI * 0.3,\r\n smoothFactor: 0.3\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Set twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @param minTwist - Minimum twist angle in radians\r\n * @param maxTwist - Maximum twist angle in radians\r\n * @param smoothFactor - Smoothing factor [0-1] (default: 0.3)\r\n */\r\n setTwistConstraint(\r\n jointIndex: number,\r\n minTwist: number,\r\n maxTwist: number,\r\n smoothFactor: number = 0.3\r\n ): void {\r\n if (jointIndex < 0 || jointIndex >= this._chain.joints.length - 1) {\r\n throw new Error(`Invalid joint index: ${jointIndex}`);\r\n }\r\n\r\n this._twistConstraints.set(jointIndex, {\r\n minTwist,\r\n maxTwist,\r\n smoothFactor: Math.max(0, Math.min(1, smoothFactor))\r\n });\r\n }\r\n\r\n /**\r\n * Get twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns Twist constraint or undefined if not set\r\n */\r\n getTwistConstraint(jointIndex: number): TwistConstraint | undefined {\r\n return this._twistConstraints.get(jointIndex);\r\n }\r\n\r\n /**\r\n * Remove twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns True if a constraint was removed\r\n */\r\n removeTwistConstraint(jointIndex: number): boolean {\r\n return this._twistConstraints.delete(jointIndex);\r\n }\r\n\r\n /**\r\n * Clear all twist constraints.\r\n */\r\n clearTwistConstraints(): void {\r\n this._twistConstraints.clear();\r\n }\r\n\r\n /**\r\n * Set pole vector for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint to apply pole vector to\r\n * @param poleVector - Pole vector position in world space\r\n * @param weight - Weight of the pole vector constraint (0-1, default: 1)\r\n */\r\n setPoleVector(jointIndex: number, poleVector: Vector3, weight = 1): void {\r\n if (jointIndex < 0 || jointIndex >= this._chain.joints.length) {\r\n throw new Error(`Invalid joint index: ${jointIndex}`);\r\n }\r\n\r\n this._poleVectors.set(jointIndex, {\r\n position: poleVector.clone(),\r\n weight: Math.max(0, Math.min(1, weight))\r\n });\r\n }\r\n\r\n /**\r\n * Remove pole vector for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint to remove pole vector from\r\n * @returns True if a pole vector was removed, false if none existed\r\n */\r\n removePoleVector(jointIndex: number): boolean {\r\n return this._poleVectors.delete(jointIndex);\r\n }\r\n\r\n /**\r\n * Clear all pole vectors.\r\n */\r\n clearPoleVectors(): void {\r\n this._poleVectors.clear();\r\n }\r\n\r\n /**\r\n * Get pole vector configuration for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns Pole vector configuration or undefined if not set\r\n */\r\n getPoleVector(jointIndex: number): { position: Vector3; weight: number } | undefined {\r\n const config = this._poleVectors.get(jointIndex);\r\n if (config) {\r\n return {\r\n position: config.position.clone(),\r\n weight: config.weight\r\n };\r\n }\r\n return undefined;\r\n }\r\n\r\n /**\r\n * Check if a joint has a pole vector.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns True if the joint has a pole vector\r\n */\r\n hasPoleVector(jointIndex: number): boolean {\r\n return this._poleVectors.has(jointIndex);\r\n }\r\n\r\n /**\r\n * Solve the IK chain to reach the target position using CCD algorithm.\r\n *\r\n * @param target - Target position for the end effector\r\n * @returns True if converged within tolerance, false otherwise\r\n */\r\n solve(target: Vector3): boolean {\r\n const joints = this._chain.joints;\r\n\r\n // Update joint positions from scene nodes before solving\r\n this._chain.updateFromNodes();\r\n\r\n // Store original positions\r\n this._chain.storeOriginalPositions();\r\n\r\n let converged = false;\r\n\r\n for (let iteration = 0; iteration < this._maxIterations; iteration++) {\r\n // Check convergence\r\n const endEffector = joints[joints.length - 1];\r\n const distToTarget = Vector3.distance(endEffector.position, target);\r\n\r\n if (distToTarget < this._tolerance) {\r\n converged = true;\r\n break;\r\n }\r\n\r\n // Iterate backward through joints (from second-to-last to root)\r\n // We skip the end effector itself since it doesn't have a child to rotate toward\r\n for (let i = joints.length - 2; i >= 0; i--) {\r\n const joint = joints[i];\r\n\r\n // Vector from current joint to end effector\r\n const toEnd = Vector3.sub(endEffector.position, joint.position, new Vector3());\r\n const toEndDist = toEnd.magnitude;\r\n\r\n // Vector from current joint to target\r\n const toTarget = Vector3.sub(target, joint.position, new Vector3());\r\n const toTargetDist = toTarget.magnitude;\r\n\r\n // Skip if either vector is too small\r\n if (toEndDist < 0.000001 || toTargetDist < 0.000001) {\r\n continue;\r\n }\r\n\r\n // Normalize vectors\r\n const toEndDir = Vector3.scale(toEnd, 1 / toEndDist, new Vector3());\r\n const toTargetDir = Vector3.scale(toTarget, 1 / toTargetDist, new Vector3());\r\n\r\n // Calculate rotation needed to align end effector toward target\r\n let rotation = new Quaternion();\r\n IKUtils.fromToRotation(toEndDir, toTargetDir, rotation);\r\n\r\n // Apply rotation to all joints from current to end effector\r\n this._rotateJointsFromIndex(i, rotation, joint.position);\r\n\r\n // Apply constraints after rotating this joint\r\n this._applyConstraintsForJoint(i);\r\n }\r\n\r\n // Apply all pole vector constraints after each full iteration\r\n // This is more stable than applying them during the CCD loop\r\n this._applyAllPoleVectors();\r\n }\r\n\r\n return converged;\r\n }\r\n\r\n /**\r\n * Rotate all joints from the given index to the end effector around a pivot point.\r\n *\r\n * @param startIndex - Index of the joint to start rotating from\r\n * @param rotation - Rotation to apply\r\n * @param pivot - Pivot point for rotation (position of the joint being adjusted)\r\n */\r\n private _rotateJointsFromIndex(startIndex: number, rotation: Quaternion, pivot: Vector3): void {\r\n const joints = this._chain.joints;\r\n\r\n // Rotate all joints from startIndex+1 to end effector\r\n for (let i = startIndex + 1; i < joints.length; i++) {\r\n const joint = joints[i];\r\n\r\n // Translate to pivot\r\n const offset = Vector3.sub(joint.position, pivot, new Vector3());\r\n\r\n // Rotate around pivot\r\n const rotated = rotation.transform(offset, new Vector3());\r\n\r\n // Translate back\r\n joint.position.set(Vector3.add(pivot, rotated, new Vector3()));\r\n }\r\n }\r\n\r\n /**\r\n * Apply all pole vector constraints.\r\n *\r\n * @remarks\r\n * This method applies all configured pole vectors to their respective joints.\r\n * Pole vectors are applied in reverse order (from end to root) to minimize\r\n * interference between multiple pole vectors. This ensures that pole vectors\r\n * closer to the end effector are not affected by pole vectors closer to the root.\r\n */\r\n private _applyAllPoleVectors(): void {\r\n if (this._poleVectors.size === 0) {\r\n return;\r\n }\r\n\r\n // Apply pole vectors in reverse order (from end to root)\r\n // This prevents earlier pole vectors from affecting later ones\r\n const sortedIndices = Array.from(this._poleVectors.keys()).sort((a, b) => b - a);\r\n\r\n for (const jointIndex of sortedIndices) {\r\n const config = this._poleVectors.get(jointIndex);\r\n if (config && config.weight > 0.001) {\r\n this._applyPoleVectorTwist(jointIndex, config.position, config.weight);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Apply pole vector twist to a specific joint.\r\n *\r\n * @remarks\r\n * This method is called after the base CCD rotation has been applied.\r\n * It adds an additional twist rotation around the joint-to-end axis\r\n * to make the next joint (child) bend toward the pole vector.\r\n *\r\n * @param jointIndex - Index of the pole joint\r\n * @param poleVector - Pole vector position in world space\r\n * @param weight - Weight of the pole vector constraint (0-1)\r\n */\r\n private _applyPoleVectorTwist(jointIndex: number, poleVector: Vector3, weight: number): void {\r\n const joints = this._chain.joints;\r\n\r\n // We need at least 3 joints to apply pole vector (parent, pole joint, child)\r\n if (jointIndex < 1 || jointIndex >= joints.length - 1) {\r\n return;\r\n }\r\n\r\n const parentJoint = joints[jointIndex - 1];\r\n const currentJoint = joints[jointIndex];\r\n const childJoint = joints[jointIndex + 1];\r\n\r\n const parentPos = parentJoint.position;\r\n const currentPos = currentJoint.position;\r\n const childPos = childJoint.position;\r\n\r\n // Calculate the plane defined by parent, child, and pole vector\r\n // Vector from parent to child (the \"line\" we're bending around)\r\n const parentToChild = Vector3.sub(childPos, parentPos, new Vector3());\r\n const lineLength = parentToChild.magnitude;\r\n\r\n if (lineLength < 0.000001) {\r\n return; // Parent and child are at same position\r\n }\r\n\r\n const lineDir = Vector3.scale(parentToChild, 1 / lineLength, new Vector3());\r\n\r\n // Project current joint onto the parent-child line\r\n const parentToCurrent = Vector3.sub(currentPos, parentPos, new Vector3());\r\n const projectionLength = Vector3.dot(parentToCurrent, lineDir);\r\n const projectionPoint = Vector3.scale(lineDir, projectionLength, new Vector3());\r\n Vector3.add(parentPos, projectionPoint, projectionPoint);\r\n\r\n // Vector from projection point to current joint (perpendicular to line)\r\n const perpendicular = Vector3.sub(currentPos, projectionPoint, new Vector3());\r\n const perpLength = perpendicular.magnitude;\r\n\r\n if (perpLength < 0.000001) {\r\n return; // Current joint is on the line\r\n }\r\n\r\n // Calculate desired direction toward pole vector\r\n const parentToPole = Vector3.sub(poleVector, parentPos, new Vector3());\r\n const poleProjectionLength = Vector3.dot(parentToPole, lineDir);\r\n const poleProjectionPoint = Vector3.scale(lineDir, poleProjectionLength, new Vector3());\r\n Vector3.add(parentPos, poleProjectionPoint, poleProjectionPoint);\r\n\r\n // Direction from projection to pole (perpendicular to line)\r\n const poleDirection = Vector3.sub(poleVector, poleProjectionPoint, new Vector3());\r\n const poleDirLength = poleDirection.magnitude;\r\n\r\n if (poleDirLength < 0.000001) {\r\n return; // Pole is on the line\r\n }\r\n\r\n poleDirection.scaleBy(1 / poleDirLength);\r\n\r\n // Calculate new position for current joint\r\n // Keep the same distance from the line, but rotate toward pole direction\r\n const desiredPerpendicular = Vector3.scale(poleDirection, perpLength, new Vector3());\r\n const newPosition = Vector3.add(projectionPoint, desiredPerpendicular, new Vector3());\r\n\r\n // Apply weight (blend between original and constrained position)\r\n if (weight < 0.999) {\r\n const blended = new Vector3();\r\n blended.x = currentPos.x + (newPosition.x - currentPos.x) * weight;\r\n blended.y = currentPos.y + (newPosition.y - currentPos.y) * weight;\r\n blended.z = currentPos.z + (newPosition.z - currentPos.z) * weight;\r\n currentJoint.position.set(blended);\r\n } else {\r\n currentJoint.position.set(newPosition);\r\n }\r\n }\r\n\r\n /**\r\n * Apply constraints for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint to apply constraints to\r\n */\r\n private _applyConstraintsForJoint(jointIndex: number): void {\r\n const constraints = this._chain.constraints;\r\n for (const constraint of constraints) {\r\n if (constraint.jointIndex === jointIndex) {\r\n constraint.apply(this._chain.joints);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Apply the solved joint positions to scene nodes as rotations.\r\n *\r\n * @param weight - Blend weight (0 = original, 1 = full IK, default: 1)\r\n */\r\n applyToNodes(weight = 1): void {\r\n const joints = this._chain.joints;\r\n\r\n // Apply rotation for all joints except the end effector\r\n for (let i = 0; i < joints.length - 1; i++) {\r\n const joint = joints[i];\r\n const nextJoint = joints[i + 1];\r\n\r\n // Calculate direction from current joint to next joint in world space\r\n const originalDir = Vector3.sub(nextJoint.originalPosition, joint.originalPosition, new Vector3());\r\n const newDir = Vector3.sub(nextJoint.position, joint.position, new Vector3());\r\n\r\n const originalDirNorm = Vector3.normalize(originalDir, new Vector3());\r\n const newDirNorm = Vector3.normalize(newDir, new Vector3());\r\n\r\n // Calculate basic rotation\r\n const deltaRotation = new Quaternion();\r\n IKUtils.fromToRotation(originalDirNorm, newDirNorm, deltaRotation);\r\n\r\n // Calculate new world rotation\r\n let worldRotation = Quaternion.multiply(deltaRotation, joint.originalRotation, new Quaternion());\r\n\r\n // Apply swing-twist constraint to prevent over-rotation\r\n const swing = new Quaternion();\r\n const twist = new Quaternion();\r\n IKUtils.decomposeSwingTwist(worldRotation, newDirNorm, swing, twist);\r\n\r\n // Get twist angle\r\n let twistAngle = IKUtils.getTwistAngle(twist, newDirNorm);\r\n\r\n // Get twist constraint for this joint\r\n const constraint = this._twistConstraints.get(i);\r\n if (constraint) {\r\n // Clamp and smooth twist\r\n twistAngle = IKUtils.clampAndSmoothTwist(\r\n twistAngle,\r\n joint.previousTwist,\r\n constraint.minTwist,\r\n constraint.maxTwist,\r\n constraint.smoothFactor\r\n );\r\n }\r\n\r\n // Store for next frame\r\n joint.previousTwist = twistAngle;\r\n\r\n // Reconstruct rotation from clamped twist: Q = Twist * Swing\r\n const clampedTwist = new Quaternion();\r\n IKUtils.createTwist(twistAngle, newDirNorm, clampedTwist);\r\n worldRotation = Quaternion.multiply(clampedTwist, swing, worldRotation);\r\n\r\n // Blend with original rotation based on weight\r\n if (weight < 1) {\r\n Quaternion.slerp(joint.originalRotation, worldRotation, weight, worldRotation);\r\n }\r\n\r\n // Store this frame's world rotation for next frame's twist continuity\r\n if (!joint.previousIKRotation) {\r\n joint.previousIKRotation = worldRotation.clone();\r\n } else {\r\n joint.previousIKRotation.set(worldRotation);\r\n }\r\n\r\n // Convert world rotation to local rotation (relative to parent)\r\n if (joint.node.parent) {\r\n const parentWorldRotation = new Quaternion();\r\n joint.node.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 joint.node.rotation = localRotation;\r\n } else {\r\n // Root node has no parent, world rotation is local rotation\r\n joint.node.rotation = worldRotation;\r\n }\r\n }\r\n }\r\n}\r\n"],"names":["CCDSolver","IKSolver","chain","maxIterations","tolerance","_poleVectors","Map","_twistConstraints","i","joints","length","isMiddleJoint","set","minTwist","Math","PI","maxTwist","smoothFactor","setTwistConstraint","jointIndex","_chain","Error","max","min","getTwistConstraint","get","removeTwistConstraint","delete","clearTwistConstraints","clear","setPoleVector","poleVector","weight","position","clone","removePoleVector","clearPoleVectors","getPoleVector","config","undefined","hasPoleVector","has","solve","target","updateFromNodes","storeOriginalPositions","converged","iteration","_maxIterations","endEffector","distToTarget","Vector3","distance","_tolerance","joint","toEnd","sub","toEndDist","magnitude","toTarget","toTargetDist","toEndDir","scale","toTargetDir","rotation","Quaternion","IKUtils","fromToRotation","_rotateJointsFromIndex","_applyConstraintsForJoint","_applyAllPoleVectors","startIndex","pivot","offset","rotated","transform","add","size","sortedIndices","Array","from","keys","sort","a","b","_applyPoleVectorTwist","parentJoint","currentJoint","childJoint","parentPos","currentPos","childPos","parentToChild","lineLength","lineDir","parentToCurrent","projectionLength","dot","projectionPoint","perpendicular","perpLength","parentToPole","poleProjectionLength","poleProjectionPoint","poleDirection","poleDirLength","scaleBy","desiredPerpendicular","newPosition","blended","x","y","z","constraints","constraint","apply","applyToNodes","nextJoint","originalDir","originalPosition","newDir","originalDirNorm","normalize","newDirNorm","deltaRotation","worldRotation","multiply","originalRotation","swing","twist","decomposeSwingTwist","twistAngle","getTwistAngle","clampAndSmoothTwist","previousTwist","clampedTwist","createTwist","slerp","previousIKRotation","node","parent","parentWorldRotation","worldMatrix","decompose","parentInvRotation","conjugate","localRotation"],"mappings":"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"}