@zephyr3d/scene 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (387) hide show
  1. package/dist/animation/animationset.js +198 -1
  2. package/dist/animation/animationset.js.map +1 -1
  3. package/dist/animation/ik/ccd_solver.js +3 -4
  4. package/dist/animation/ik/ccd_solver.js.map +1 -1
  5. package/dist/animation/ik/fabrik_solver.js +3 -4
  6. package/dist/animation/ik/fabrik_solver.js.map +1 -1
  7. package/dist/animation/ik/ik_pole_constraint.js +7 -2
  8. package/dist/animation/ik/ik_pole_constraint.js.map +1 -1
  9. package/dist/animation/ik/ik_utils.js +0 -79
  10. package/dist/animation/ik/ik_utils.js.map +1 -1
  11. package/dist/animation/ik/two_bone_ik_solver.js +3 -4
  12. package/dist/animation/ik/two_bone_ik_solver.js.map +1 -1
  13. package/dist/animation/spring/spring_bone.js +240 -0
  14. package/dist/animation/spring/spring_bone.js.map +1 -0
  15. package/dist/animation/spring/spring_bone_collider.js +198 -0
  16. package/dist/animation/spring/spring_bone_collider.js.map +1 -0
  17. package/dist/animation/spring/spring_bone_constraint.js +170 -0
  18. package/dist/animation/spring/spring_bone_constraint.js.map +1 -0
  19. package/dist/animation/spring/spring_bone_system.js +328 -0
  20. package/dist/animation/spring/spring_bone_system.js.map +1 -0
  21. package/dist/asset/model.js +2 -2
  22. package/dist/index.d.ts +15 -0
  23. package/dist/material/mixins/pbr/common.js +20 -17
  24. package/dist/material/mixins/pbr/common.js.map +1 -1
  25. package/dist/render/gpu_picking.js +100 -0
  26. package/dist/render/gpu_picking.js.map +1 -0
  27. package/dist/render/rendergraph/device_pool_allocator.js +41 -0
  28. package/dist/render/rendergraph/device_pool_allocator.js.map +1 -0
  29. package/dist/render/rendergraph/executor.js +146 -0
  30. package/dist/render/rendergraph/executor.js.map +1 -0
  31. package/dist/render/rendergraph/forward_plus_builder.js +414 -0
  32. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -0
  33. package/dist/render/rendergraph/rendergraph.js +306 -0
  34. package/dist/render/rendergraph/rendergraph.js.map +1 -0
  35. package/dist/render/rendergraph/types.js +57 -0
  36. package/dist/render/rendergraph/types.js.map +1 -0
  37. package/dist/render/sky_motion_vector.js +85 -0
  38. package/dist/render/sky_motion_vector.js.map +1 -0
  39. package/dist/utility/serialization/scene/animation.js +3 -3
  40. package/dist/utility/serialization/scene/node.js +1 -1
  41. package/package.json +2 -2
  42. package/dist/animation/ik/ik_chain_builder.js +0 -68
  43. package/dist/animation/ik/ik_chain_builder.js.map +0 -1
  44. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/runtimemgr.js +0 -38
  45. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/runtimemgr.js.map +0 -1
  46. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/runtimescript.js +0 -10
  47. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/runtimescript.js.map +0 -1
  48. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/scriptingsystem.js +0 -127
  49. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/scriptingsystem.js.map +0 -1
  50. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/scriptregistry.js +0 -263
  51. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/scriptregistry.js.map +0 -1
  52. package/dist/src/animation/animation.js +0 -127
  53. package/dist/src/animation/animation.js.map +0 -1
  54. package/dist/src/animation/animationset.js +0 -255
  55. package/dist/src/animation/animationset.js.map +0 -1
  56. package/dist/src/animation/animationtrack.js +0 -34
  57. package/dist/src/animation/animationtrack.js.map +0 -1
  58. package/dist/src/animation/eulerrotationtrack.js +0 -52
  59. package/dist/src/animation/eulerrotationtrack.js.map +0 -1
  60. package/dist/src/animation/morphtarget.js +0 -93
  61. package/dist/src/animation/morphtarget.js.map +0 -1
  62. package/dist/src/animation/morphtrack.js +0 -70
  63. package/dist/src/animation/morphtrack.js.map +0 -1
  64. package/dist/src/animation/proptrack.js +0 -161
  65. package/dist/src/animation/proptrack.js.map +0 -1
  66. package/dist/src/animation/rotationtrack.js +0 -51
  67. package/dist/src/animation/rotationtrack.js.map +0 -1
  68. package/dist/src/animation/scaletrack.js +0 -50
  69. package/dist/src/animation/scaletrack.js.map +0 -1
  70. package/dist/src/animation/skeleton.js +0 -204
  71. package/dist/src/animation/skeleton.js.map +0 -1
  72. package/dist/src/animation/translationtrack.js +0 -50
  73. package/dist/src/animation/translationtrack.js.map +0 -1
  74. package/dist/src/app/app.js +0 -129
  75. package/dist/src/app/app.js.map +0 -1
  76. package/dist/src/app/inputmgr.js +0 -267
  77. package/dist/src/app/inputmgr.js.map +0 -1
  78. package/dist/src/asset/assetmanager.js +0 -404
  79. package/dist/src/asset/assetmanager.js.map +0 -1
  80. package/dist/src/asset/builtin.js +0 -337
  81. package/dist/src/asset/builtin.js.map +0 -1
  82. package/dist/src/asset/loaders/dds/dds.js +0 -470
  83. package/dist/src/asset/loaders/dds/dds.js.map +0 -1
  84. package/dist/src/asset/loaders/dds/dds_loader.js +0 -28
  85. package/dist/src/asset/loaders/dds/dds_loader.js.map +0 -1
  86. package/dist/src/asset/loaders/gltf/gltf_loader.js +0 -1265
  87. package/dist/src/asset/loaders/gltf/gltf_loader.js.map +0 -1
  88. package/dist/src/asset/loaders/gltf/helpers.js +0 -327
  89. package/dist/src/asset/loaders/gltf/helpers.js.map +0 -1
  90. package/dist/src/asset/loaders/hdr/hdr.js +0 -180
  91. package/dist/src/asset/loaders/hdr/hdr.js.map +0 -1
  92. package/dist/src/asset/loaders/image/tga_Loader.js +0 -116
  93. package/dist/src/asset/loaders/image/tga_Loader.js.map +0 -1
  94. package/dist/src/asset/loaders/image/webimage_loader.js +0 -63
  95. package/dist/src/asset/loaders/image/webimage_loader.js.map +0 -1
  96. package/dist/src/asset/loaders/loader.js +0 -45
  97. package/dist/src/asset/loaders/loader.js.map +0 -1
  98. package/dist/src/asset/model.js +0 -414
  99. package/dist/src/asset/model.js.map +0 -1
  100. package/dist/src/blitter/bilateralblur.js +0 -221
  101. package/dist/src/blitter/bilateralblur.js.map +0 -1
  102. package/dist/src/blitter/blitter.js +0 -390
  103. package/dist/src/blitter/blitter.js.map +0 -1
  104. package/dist/src/blitter/box.js +0 -118
  105. package/dist/src/blitter/box.js.map +0 -1
  106. package/dist/src/blitter/copy.js +0 -22
  107. package/dist/src/blitter/copy.js.map +0 -1
  108. package/dist/src/blitter/gaussianblur.js +0 -228
  109. package/dist/src/blitter/gaussianblur.js.map +0 -1
  110. package/dist/src/camera/base.js +0 -92
  111. package/dist/src/camera/base.js.map +0 -1
  112. package/dist/src/camera/camera.js +0 -1005
  113. package/dist/src/camera/camera.js.map +0 -1
  114. package/dist/src/camera/fps.js +0 -238
  115. package/dist/src/camera/fps.js.map +0 -1
  116. package/dist/src/camera/orbit.js +0 -245
  117. package/dist/src/camera/orbit.js.map +0 -1
  118. package/dist/src/camera/orthocamera.js +0 -167
  119. package/dist/src/camera/orthocamera.js.map +0 -1
  120. package/dist/src/camera/perspectivecamera.js +0 -141
  121. package/dist/src/camera/perspectivecamera.js.map +0 -1
  122. package/dist/src/index.js +0 -120
  123. package/dist/src/index.js.map +0 -1
  124. package/dist/src/material/blinn.js +0 -81
  125. package/dist/src/material/blinn.js.map +0 -1
  126. package/dist/src/material/grassmaterial.js +0 -113
  127. package/dist/src/material/grassmaterial.js.map +0 -1
  128. package/dist/src/material/lambert.js +0 -92
  129. package/dist/src/material/lambert.js.map +0 -1
  130. package/dist/src/material/material.js +0 -301
  131. package/dist/src/material/material.js.map +0 -1
  132. package/dist/src/material/meshmaterial.js +0 -704
  133. package/dist/src/material/meshmaterial.js.map +0 -1
  134. package/dist/src/material/mixins/albedocolor.js +0 -76
  135. package/dist/src/material/mixins/albedocolor.js.map +0 -1
  136. package/dist/src/material/mixins/foliage.js +0 -47
  137. package/dist/src/material/mixins/foliage.js.map +0 -1
  138. package/dist/src/material/mixins/lightmodel/blinnphong.js +0 -112
  139. package/dist/src/material/mixins/lightmodel/blinnphong.js.map +0 -1
  140. package/dist/src/material/mixins/lightmodel/lambert.js +0 -58
  141. package/dist/src/material/mixins/lightmodel/lambert.js.map +0 -1
  142. package/dist/src/material/mixins/lightmodel/pbrmetallicroughness.js +0 -178
  143. package/dist/src/material/mixins/lightmodel/pbrmetallicroughness.js.map +0 -1
  144. package/dist/src/material/mixins/lightmodel/pbrspecularglossness.js +0 -139
  145. package/dist/src/material/mixins/lightmodel/pbrspecularglossness.js.map +0 -1
  146. package/dist/src/material/mixins/lit.js +0 -476
  147. package/dist/src/material/mixins/lit.js.map +0 -1
  148. package/dist/src/material/mixins/pbr/common.js +0 -918
  149. package/dist/src/material/mixins/pbr/common.js.map +0 -1
  150. package/dist/src/material/mixins/texture.js +0 -172
  151. package/dist/src/material/mixins/texture.js.map +0 -1
  152. package/dist/src/material/mixins/vertexcolor.js +0 -56
  153. package/dist/src/material/mixins/vertexcolor.js.map +0 -1
  154. package/dist/src/material/particle.js +0 -178
  155. package/dist/src/material/particle.js.map +0 -1
  156. package/dist/src/material/pbrmr.js +0 -97
  157. package/dist/src/material/pbrmr.js.map +0 -1
  158. package/dist/src/material/pbrsg.js +0 -97
  159. package/dist/src/material/pbrsg.js.map +0 -1
  160. package/dist/src/material/shader/helper.js +0 -1209
  161. package/dist/src/material/shader/helper.js.map +0 -1
  162. package/dist/src/material/terrain-cm.js +0 -606
  163. package/dist/src/material/terrain-cm.js.map +0 -1
  164. package/dist/src/material/terrainmaterial.js +0 -375
  165. package/dist/src/material/terrainmaterial.js.map +0 -1
  166. package/dist/src/material/unlit.js +0 -41
  167. package/dist/src/material/unlit.js.map +0 -1
  168. package/dist/src/material/water.js +0 -417
  169. package/dist/src/material/water.js.map +0 -1
  170. package/dist/src/posteffect/bloom.js +0 -361
  171. package/dist/src/posteffect/bloom.js.map +0 -1
  172. package/dist/src/posteffect/compositor.js +0 -226
  173. package/dist/src/posteffect/compositor.js.map +0 -1
  174. package/dist/src/posteffect/fxaa.js +0 -273
  175. package/dist/src/posteffect/fxaa.js.map +0 -1
  176. package/dist/src/posteffect/grayscale.js +0 -69
  177. package/dist/src/posteffect/grayscale.js.map +0 -1
  178. package/dist/src/posteffect/motionblur.js +0 -96
  179. package/dist/src/posteffect/motionblur.js.map +0 -1
  180. package/dist/src/posteffect/posteffect.js +0 -126
  181. package/dist/src/posteffect/posteffect.js.map +0 -1
  182. package/dist/src/posteffect/sao.js +0 -324
  183. package/dist/src/posteffect/sao.js.map +0 -1
  184. package/dist/src/posteffect/ssr.js +0 -489
  185. package/dist/src/posteffect/ssr.js.map +0 -1
  186. package/dist/src/posteffect/taa.js +0 -172
  187. package/dist/src/posteffect/taa.js.map +0 -1
  188. package/dist/src/posteffect/tonemap.js +0 -94
  189. package/dist/src/posteffect/tonemap.js.map +0 -1
  190. package/dist/src/render/abuffer_oit.js +0 -361
  191. package/dist/src/render/abuffer_oit.js.map +0 -1
  192. package/dist/src/render/clipmap.js +0 -851
  193. package/dist/src/render/clipmap.js.map +0 -1
  194. package/dist/src/render/cluster_light.js +0 -333
  195. package/dist/src/render/cluster_light.js.map +0 -1
  196. package/dist/src/render/cull_visitor.js +0 -187
  197. package/dist/src/render/cull_visitor.js.map +0 -1
  198. package/dist/src/render/depthpass.js +0 -68
  199. package/dist/src/render/depthpass.js.map +0 -1
  200. package/dist/src/render/drawable_mixin.js +0 -227
  201. package/dist/src/render/drawable_mixin.js.map +0 -1
  202. package/dist/src/render/envlight.js +0 -463
  203. package/dist/src/render/envlight.js.map +0 -1
  204. package/dist/src/render/fbm_wavegenerator.js +0 -251
  205. package/dist/src/render/fbm_wavegenerator.js.map +0 -1
  206. package/dist/src/render/fft_wavegenerator.js +0 -1006
  207. package/dist/src/render/fft_wavegenerator.js.map +0 -1
  208. package/dist/src/render/fullscreenquad.js +0 -38
  209. package/dist/src/render/fullscreenquad.js.map +0 -1
  210. package/dist/src/render/gerstner_wavegenerator.js +0 -314
  211. package/dist/src/render/gerstner_wavegenerator.js.map +0 -1
  212. package/dist/src/render/globalbindgroup_allocator.js +0 -60
  213. package/dist/src/render/globalbindgroup_allocator.js.map +0 -1
  214. package/dist/src/render/hzb.js +0 -273
  215. package/dist/src/render/hzb.js.map +0 -1
  216. package/dist/src/render/lightpass.js +0 -172
  217. package/dist/src/render/lightpass.js.map +0 -1
  218. package/dist/src/render/objectcolorpass.js +0 -51
  219. package/dist/src/render/objectcolorpass.js.map +0 -1
  220. package/dist/src/render/primitive.js +0 -364
  221. package/dist/src/render/primitive.js.map +0 -1
  222. package/dist/src/render/render_queue.js +0 -467
  223. package/dist/src/render/render_queue.js.map +0 -1
  224. package/dist/src/render/renderbundle_wrapper.js +0 -152
  225. package/dist/src/render/renderbundle_wrapper.js.map +0 -1
  226. package/dist/src/render/renderer.js +0 -455
  227. package/dist/src/render/renderer.js.map +0 -1
  228. package/dist/src/render/renderpass.js +0 -200
  229. package/dist/src/render/renderpass.js.map +0 -1
  230. package/dist/src/render/shadowmap_pass.js +0 -56
  231. package/dist/src/render/shadowmap_pass.js.map +0 -1
  232. package/dist/src/render/sky.js +0 -1103
  233. package/dist/src/render/sky.js.map +0 -1
  234. package/dist/src/render/weightedblended_oit.js +0 -168
  235. package/dist/src/render/weightedblended_oit.js.map +0 -1
  236. package/dist/src/scene/batchgroup.js +0 -162
  237. package/dist/src/scene/batchgroup.js.map +0 -1
  238. package/dist/src/scene/environment.js +0 -209
  239. package/dist/src/scene/environment.js.map +0 -1
  240. package/dist/src/scene/graph_node.js +0 -72
  241. package/dist/src/scene/graph_node.js.map +0 -1
  242. package/dist/src/scene/light.js +0 -416
  243. package/dist/src/scene/light.js.map +0 -1
  244. package/dist/src/scene/mesh.js +0 -341
  245. package/dist/src/scene/mesh.js.map +0 -1
  246. package/dist/src/scene/octree.js +0 -649
  247. package/dist/src/scene/octree.js.map +0 -1
  248. package/dist/src/scene/particlesys.js +0 -738
  249. package/dist/src/scene/particlesys.js.map +0 -1
  250. package/dist/src/scene/raycast_visitor.js +0 -103
  251. package/dist/src/scene/raycast_visitor.js.map +0 -1
  252. package/dist/src/scene/scene.js +0 -284
  253. package/dist/src/scene/scene.js.map +0 -1
  254. package/dist/src/scene/scene_node.js +0 -732
  255. package/dist/src/scene/scene_node.js.map +0 -1
  256. package/dist/src/scene/terrain/grass.js +0 -278
  257. package/dist/src/scene/terrain/grass.js.map +0 -1
  258. package/dist/src/scene/terrain/heightfield.js +0 -475
  259. package/dist/src/scene/terrain/heightfield.js.map +0 -1
  260. package/dist/src/scene/terrain/patch.js +0 -530
  261. package/dist/src/scene/terrain/patch.js.map +0 -1
  262. package/dist/src/scene/terrain/quadtree.js +0 -461
  263. package/dist/src/scene/terrain/quadtree.js.map +0 -1
  264. package/dist/src/scene/terrain/terrain.js +0 -246
  265. package/dist/src/scene/terrain/terrain.js.map +0 -1
  266. package/dist/src/scene/terrain-cm/grass.js +0 -594
  267. package/dist/src/scene/terrain-cm/grass.js.map +0 -1
  268. package/dist/src/scene/terrain-cm/grassmaterial.js +0 -159
  269. package/dist/src/scene/terrain-cm/grassmaterial.js.map +0 -1
  270. package/dist/src/scene/terrain-cm/terrain-cm.js +0 -538
  271. package/dist/src/scene/terrain-cm/terrain-cm.js.map +0 -1
  272. package/dist/src/scene/water.js +0 -374
  273. package/dist/src/scene/water.js.map +0 -1
  274. package/dist/src/shaders/atmosphere.js +0 -957
  275. package/dist/src/shaders/atmosphere.js.map +0 -1
  276. package/dist/src/shaders/fog.js +0 -112
  277. package/dist/src/shaders/fog.js.map +0 -1
  278. package/dist/src/shaders/misc.js +0 -266
  279. package/dist/src/shaders/misc.js.map +0 -1
  280. package/dist/src/shaders/noise.js +0 -222
  281. package/dist/src/shaders/noise.js.map +0 -1
  282. package/dist/src/shaders/pbr.js +0 -51
  283. package/dist/src/shaders/pbr.js.map +0 -1
  284. package/dist/src/shaders/shadow.js +0 -636
  285. package/dist/src/shaders/shadow.js.map +0 -1
  286. package/dist/src/shaders/ssr.js +0 -490
  287. package/dist/src/shaders/ssr.js.map +0 -1
  288. package/dist/src/shaders/temporal.js +0 -215
  289. package/dist/src/shaders/temporal.js.map +0 -1
  290. package/dist/src/shaders/water.js +0 -756
  291. package/dist/src/shaders/water.js.map +0 -1
  292. package/dist/src/shadow/esm.js +0 -237
  293. package/dist/src/shadow/esm.js.map +0 -1
  294. package/dist/src/shadow/pcf_opt.js +0 -181
  295. package/dist/src/shadow/pcf_opt.js.map +0 -1
  296. package/dist/src/shadow/pcf_pd.js +0 -189
  297. package/dist/src/shadow/pcf_pd.js.map +0 -1
  298. package/dist/src/shadow/shader.js +0 -37
  299. package/dist/src/shadow/shader.js.map +0 -1
  300. package/dist/src/shadow/shadow_impl.js +0 -15
  301. package/dist/src/shadow/shadow_impl.js.map +0 -1
  302. package/dist/src/shadow/shadowmapper.js +0 -790
  303. package/dist/src/shadow/shadowmapper.js.map +0 -1
  304. package/dist/src/shadow/ssm.js +0 -159
  305. package/dist/src/shadow/ssm.js.map +0 -1
  306. package/dist/src/shadow/vsm.js +0 -297
  307. package/dist/src/shadow/vsm.js.map +0 -1
  308. package/dist/src/shapes/box.js +0 -386
  309. package/dist/src/shapes/box.js.map +0 -1
  310. package/dist/src/shapes/cylinder.js +0 -125
  311. package/dist/src/shapes/cylinder.js.map +0 -1
  312. package/dist/src/shapes/plane.js +0 -88
  313. package/dist/src/shapes/plane.js.map +0 -1
  314. package/dist/src/shapes/shape.js +0 -87
  315. package/dist/src/shapes/shape.js.map +0 -1
  316. package/dist/src/shapes/sphere.js +0 -114
  317. package/dist/src/shapes/sphere.js.map +0 -1
  318. package/dist/src/shapes/tetrahedron.js +0 -188
  319. package/dist/src/shapes/tetrahedron.js.map +0 -1
  320. package/dist/src/shapes/torus.js +0 -111
  321. package/dist/src/shapes/torus.js.map +0 -1
  322. package/dist/src/utility/aabbtree.js +0 -400
  323. package/dist/src/utility/aabbtree.js.map +0 -1
  324. package/dist/src/utility/bounding_volume.js +0 -29
  325. package/dist/src/utility/bounding_volume.js.map +0 -1
  326. package/dist/src/utility/debug.js +0 -28
  327. package/dist/src/utility/debug.js.map +0 -1
  328. package/dist/src/utility/draco/decoder.js +0 -116
  329. package/dist/src/utility/draco/decoder.js.map +0 -1
  330. package/dist/src/utility/misc.js +0 -105
  331. package/dist/src/utility/misc.js.map +0 -1
  332. package/dist/src/utility/panorama.js +0 -163
  333. package/dist/src/utility/panorama.js.map +0 -1
  334. package/dist/src/utility/pmrem.js +0 -354
  335. package/dist/src/utility/pmrem.js.map +0 -1
  336. package/dist/src/utility/rendermipmap.js +0 -115
  337. package/dist/src/utility/rendermipmap.js.map +0 -1
  338. package/dist/src/utility/serialization/json.js +0 -402
  339. package/dist/src/utility/serialization/json.js.map +0 -1
  340. package/dist/src/utility/serialization/manager.js +0 -623
  341. package/dist/src/utility/serialization/manager.js.map +0 -1
  342. package/dist/src/utility/serialization/scene/animation.js +0 -248
  343. package/dist/src/utility/serialization/scene/animation.js.map +0 -1
  344. package/dist/src/utility/serialization/scene/batch.js +0 -59
  345. package/dist/src/utility/serialization/scene/batch.js.map +0 -1
  346. package/dist/src/utility/serialization/scene/camera.js +0 -790
  347. package/dist/src/utility/serialization/scene/camera.js.map +0 -1
  348. package/dist/src/utility/serialization/scene/common.js +0 -222
  349. package/dist/src/utility/serialization/scene/common.js.map +0 -1
  350. package/dist/src/utility/serialization/scene/light.js +0 -575
  351. package/dist/src/utility/serialization/scene/light.js.map +0 -1
  352. package/dist/src/utility/serialization/scene/material.js +0 -1111
  353. package/dist/src/utility/serialization/scene/material.js.map +0 -1
  354. package/dist/src/utility/serialization/scene/mesh.js +0 -148
  355. package/dist/src/utility/serialization/scene/mesh.js.map +0 -1
  356. package/dist/src/utility/serialization/scene/misc.js +0 -39
  357. package/dist/src/utility/serialization/scene/misc.js.map +0 -1
  358. package/dist/src/utility/serialization/scene/node.js +0 -451
  359. package/dist/src/utility/serialization/scene/node.js.map +0 -1
  360. package/dist/src/utility/serialization/scene/particle.js +0 -425
  361. package/dist/src/utility/serialization/scene/particle.js.map +0 -1
  362. package/dist/src/utility/serialization/scene/primitive.js +0 -692
  363. package/dist/src/utility/serialization/scene/primitive.js.map +0 -1
  364. package/dist/src/utility/serialization/scene/scene.js +0 -704
  365. package/dist/src/utility/serialization/scene/scene.js.map +0 -1
  366. package/dist/src/utility/serialization/scene/terrain.js +0 -488
  367. package/dist/src/utility/serialization/scene/terrain.js.map +0 -1
  368. package/dist/src/utility/serialization/scene/water.js +0 -465
  369. package/dist/src/utility/serialization/scene/water.js.map +0 -1
  370. package/dist/src/utility/shprojector.js +0 -297
  371. package/dist/src/utility/shprojector.js.map +0 -1
  372. package/dist/src/utility/textures/ggxlut.js +0 -213
  373. package/dist/src/utility/textures/ggxlut.js.map +0 -1
  374. package/dist/src/utility/textures/gradientnoise.js +0 -62
  375. package/dist/src/utility/textures/gradientnoise.js.map +0 -1
  376. package/dist/src/utility/textures/randomnoise.js +0 -41
  377. package/dist/src/utility/textures/randomnoise.js.map +0 -1
  378. package/dist/src/values.js +0 -162
  379. package/dist/src/values.js.map +0 -1
  380. package/dist/utility/blueprint/material/common.js +0 -7
  381. package/dist/utility/blueprint/material/common.js.map +0 -1
  382. package/dist/utility/serialization/blueprint/constants.js +0 -255
  383. package/dist/utility/serialization/blueprint/constants.js.map +0 -1
  384. package/dist/utility/serialization/blueprint/material/constants.js +0 -203
  385. package/dist/utility/serialization/blueprint/material/constants.js.map +0 -1
  386. package/dist/utility/serialization/blueprint/material/texture.js +0 -165
  387. package/dist/utility/serialization/blueprint/material/texture.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"fabrik_solver.js","sources":["../../../src/animation/ik/fabrik_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 * FABRIK (Forward And Backward Reaching Inverse Kinematics) solver.\r\n *\r\n * @remarks\r\n * FABRIK is an iterative IK algorithm that alternates between:\r\n * 1. Forward pass: Move from end effector to root, pulling joints toward target\r\n * 2. Backward pass: Move from root to end effector, restoring root position\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 FABRIKSolver 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 FABRIK solver.\r\n *\r\n * @param chain - The IK chain to solve\r\n * @param maxIterations - Maximum number of iterations (default: 15)\r\n * @param tolerance - Convergence tolerance in world units (default: 0.001)\r\n */\r\n constructor(chain: IKChain, maxIterations = 15, 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 FABRIK 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 const rootPos = joints[0].originalPosition.clone();\r\n\r\n // Check if target is reachable\r\n const distToTarget = Vector3.distance(rootPos, target);\r\n if (distToTarget > this._chain.totalLength) {\r\n // Target unreachable - stretch chain toward target\r\n this._stretchToward(target);\r\n return false;\r\n }\r\n\r\n let converged = false;\r\n for (let iteration = 0; iteration < this._maxIterations; iteration++) {\r\n // Check convergence\r\n const distToEnd = Vector3.distance(joints[joints.length - 1].position, target);\r\n if (distToEnd < this._tolerance) {\r\n converged = true;\r\n break;\r\n }\r\n\r\n // Forward pass: end effector to root\r\n this._forwardPass(target);\r\n\r\n // Backward pass: root to end effector (constraints are applied within the pass)\r\n this._backwardPass(rootPos);\r\n }\r\n\r\n return converged;\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 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\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 /**\r\n * Forward pass: move from end effector toward root.\r\n * Each joint is pulled toward its child, maintaining bone length.\r\n * Constraints are applied immediately after each joint adjustment.\r\n *\r\n * @param target - Target position for end effector\r\n */\r\n private _forwardPass(target: Vector3): void {\r\n const joints = this._chain.joints;\r\n\r\n // Set end effector to target\r\n joints[joints.length - 1].position.set(target);\r\n\r\n // Move backward through chain\r\n for (let i = joints.length - 2; i >= 0; i--) {\r\n const joint = joints[i];\r\n const childJoint = joints[i + 1];\r\n\r\n // Calculate direction from child to current joint\r\n const direction = Vector3.sub(joint.position, childJoint.position, new Vector3());\r\n const distance = direction.magnitude;\r\n\r\n if (distance > 0.000001) {\r\n direction.scaleBy(1 / distance);\r\n // Place joint at correct distance from child\r\n Vector3.scale(direction, joint.boneLength, direction);\r\n Vector3.add(childJoint.position, direction, joint.position);\r\n }\r\n\r\n // Apply constraints immediately after adjusting this joint\r\n // This ensures constraints are integrated into the FABRIK algorithm\r\n if (i > 0) {\r\n // Apply constraints for joint i (not for root joint)\r\n this._applyConstraintsForJoint(i);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Backward pass: move from root toward end effector.\r\n * Each joint is pulled toward its parent, maintaining bone length.\r\n * Constraints are applied immediately after each joint adjustment.\r\n *\r\n * @param rootPos - Original root position to restore\r\n */\r\n private _backwardPass(rootPos: Vector3): void {\r\n const joints = this._chain.joints;\r\n\r\n // Restore root position\r\n joints[0].position.set(rootPos);\r\n\r\n // Move forward through chain\r\n for (let i = 0; i < joints.length - 1; i++) {\r\n const joint = joints[i];\r\n const childJoint = joints[i + 1];\r\n\r\n // Calculate direction from current joint to child\r\n const direction = Vector3.sub(childJoint.position, joint.position, new Vector3());\r\n const distance = direction.magnitude;\r\n\r\n if (distance > 0.000001) {\r\n direction.scaleBy(1 / distance);\r\n // Place child at correct distance from current joint\r\n Vector3.scale(direction, joint.boneLength, direction);\r\n Vector3.add(joint.position, direction, childJoint.position);\r\n }\r\n\r\n // Apply constraints immediately after adjusting this joint\r\n // This ensures constraints are integrated into the FABRIK algorithm\r\n this._applyConstraintsForJoint(i + 1);\r\n }\r\n }\r\n\r\n /**\r\n * Apply constraints for a specific joint.\r\n * This is called during the FABRIK passes to integrate constraints into the algorithm.\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\r\n // Apply non-pole-vector constraints\r\n // IKPoleVectorConstraint is deprecated and ignored in favor of built-in pole vectors\r\n for (const constraint of constraints) {\r\n if (constraint.jointIndex === jointIndex) {\r\n // Skip IKPoleVectorConstraint - use built-in pole vectors instead\r\n if (constraint.constructor.name === 'IKPoleVectorConstraint') {\r\n continue;\r\n }\r\n constraint.apply(this._chain.joints);\r\n }\r\n }\r\n\r\n // Apply built-in pole vector if configured for this joint\r\n const poleConfig = this._poleVectors.get(jointIndex);\r\n if (poleConfig && poleConfig.weight > 0.001) {\r\n this._applyPoleVectorTwist(jointIndex, poleConfig.position, poleConfig.weight);\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 adjusts the joint position to align with the pole vector.\r\n * It uses the same algorithm as IKPoleVectorConstraint but is integrated\r\n * into the solver for better performance and control.\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 * Stretch the chain toward an unreachable target.\r\n * All joints are aligned in a straight line toward the target.\r\n *\r\n * @param target - Unreachable target position\r\n */\r\n private _stretchToward(target: Vector3): void {\r\n const joints = this._chain.joints;\r\n const rootPos = joints[0].originalPosition;\r\n\r\n // Calculate direction from root to target\r\n const direction = Vector3.sub(target, rootPos, new Vector3()).inplaceNormalize();\r\n\r\n // Place each joint along the direction at its bone length\r\n let currentPos = rootPos.clone();\r\n for (let i = 0; i < joints.length; i++) {\r\n joints[i].position.set(currentPos);\r\n if (i < joints.length - 1) {\r\n const offset = Vector3.scale(direction, joints[i].boneLength, new Vector3());\r\n currentPos.addBy(offset);\r\n }\r\n }\r\n }\r\n}\r\n"],"names":["FABRIKSolver","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","rootPos","originalPosition","distToTarget","Vector3","distance","totalLength","_stretchToward","converged","iteration","_maxIterations","distToEnd","_tolerance","_forwardPass","_backwardPass","applyToNodes","joint","nextJoint","originalDir","sub","newDir","originalDirNorm","normalize","newDirNorm","deltaRotation","Quaternion","IKUtils","fromToRotation","worldRotation","multiply","originalRotation","swing","twist","decomposeSwingTwist","twistAngle","getTwistAngle","constraint","clampAndSmoothTwist","previousTwist","clampedTwist","createTwist","slerp","previousIKRotation","node","parent","parentWorldRotation","worldMatrix","decompose","parentInvRotation","conjugate","localRotation","rotation","childJoint","direction","magnitude","scaleBy","scale","boneLength","add","_applyConstraintsForJoint","constraints","name","apply","poleConfig","_applyPoleVectorTwist","parentJoint","currentJoint","parentPos","currentPos","childPos","parentToChild","lineLength","lineDir","parentToCurrent","projectionLength","dot","projectionPoint","perpendicular","perpLength","parentToPole","poleProjectionLength","poleProjectionPoint","poleDirection","poleDirLength","desiredPerpendicular","newPosition","blended","x","y","z","inplaceNormalize","offset","addBy"],"mappings":"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"}
1
+ {"version":3,"file":"fabrik_solver.js","sources":["../../../src/animation/ik/fabrik_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 * FABRIK (Forward And Backward Reaching Inverse Kinematics) solver.\r\n *\r\n * @remarks\r\n * FABRIK is an iterative IK algorithm that alternates between:\r\n * 1. Forward pass: Move from end effector to root, pulling joints toward target\r\n * 2. Backward pass: Move from root to end effector, restoring root position\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 FABRIKSolver 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 FABRIK solver.\r\n *\r\n * @param chain - The IK chain to solve\r\n * @param maxIterations - Maximum number of iterations (default: 15)\r\n * @param tolerance - Convergence tolerance in world units (default: 0.001)\r\n */\r\n constructor(chain: IKChain, maxIterations = 15, 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 FABRIK 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 const rootPos = joints[0].originalPosition.clone();\r\n\r\n // Check if target is reachable\r\n const distToTarget = Vector3.distance(rootPos, target);\r\n if (distToTarget > this._chain.totalLength) {\r\n // Target unreachable - stretch chain toward target\r\n this._stretchToward(target);\r\n return false;\r\n }\r\n\r\n let converged = false;\r\n for (let iteration = 0; iteration < this._maxIterations; iteration++) {\r\n // Check convergence\r\n const distToEnd = Vector3.distance(joints[joints.length - 1].position, target);\r\n if (distToEnd < this._tolerance) {\r\n converged = true;\r\n break;\r\n }\r\n\r\n // Forward pass: end effector to root\r\n this._forwardPass(target);\r\n\r\n // Backward pass: root to end effector (constraints are applied within the pass)\r\n this._backwardPass(rootPos);\r\n }\r\n\r\n return converged;\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 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 worldRotation.decomposeSwingTwist(newDirNorm, swing, twist);\r\n\r\n // Get twist angle\r\n let twistAngle = twist.getTwistAngle(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 = Quaternion.fromAxisAngle(newDirNorm, twistAngle);\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\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 /**\r\n * Forward pass: move from end effector toward root.\r\n * Each joint is pulled toward its child, maintaining bone length.\r\n * Constraints are applied immediately after each joint adjustment.\r\n *\r\n * @param target - Target position for end effector\r\n */\r\n private _forwardPass(target: Vector3): void {\r\n const joints = this._chain.joints;\r\n\r\n // Set end effector to target\r\n joints[joints.length - 1].position.set(target);\r\n\r\n // Move backward through chain\r\n for (let i = joints.length - 2; i >= 0; i--) {\r\n const joint = joints[i];\r\n const childJoint = joints[i + 1];\r\n\r\n // Calculate direction from child to current joint\r\n const direction = Vector3.sub(joint.position, childJoint.position, new Vector3());\r\n const distance = direction.magnitude;\r\n\r\n if (distance > 0.000001) {\r\n direction.scaleBy(1 / distance);\r\n // Place joint at correct distance from child\r\n Vector3.scale(direction, joint.boneLength, direction);\r\n Vector3.add(childJoint.position, direction, joint.position);\r\n }\r\n\r\n // Apply constraints immediately after adjusting this joint\r\n // This ensures constraints are integrated into the FABRIK algorithm\r\n if (i > 0) {\r\n // Apply constraints for joint i (not for root joint)\r\n this._applyConstraintsForJoint(i);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Backward pass: move from root toward end effector.\r\n * Each joint is pulled toward its parent, maintaining bone length.\r\n * Constraints are applied immediately after each joint adjustment.\r\n *\r\n * @param rootPos - Original root position to restore\r\n */\r\n private _backwardPass(rootPos: Vector3): void {\r\n const joints = this._chain.joints;\r\n\r\n // Restore root position\r\n joints[0].position.set(rootPos);\r\n\r\n // Move forward through chain\r\n for (let i = 0; i < joints.length - 1; i++) {\r\n const joint = joints[i];\r\n const childJoint = joints[i + 1];\r\n\r\n // Calculate direction from current joint to child\r\n const direction = Vector3.sub(childJoint.position, joint.position, new Vector3());\r\n const distance = direction.magnitude;\r\n\r\n if (distance > 0.000001) {\r\n direction.scaleBy(1 / distance);\r\n // Place child at correct distance from current joint\r\n Vector3.scale(direction, joint.boneLength, direction);\r\n Vector3.add(joint.position, direction, childJoint.position);\r\n }\r\n\r\n // Apply constraints immediately after adjusting this joint\r\n // This ensures constraints are integrated into the FABRIK algorithm\r\n this._applyConstraintsForJoint(i + 1);\r\n }\r\n }\r\n\r\n /**\r\n * Apply constraints for a specific joint.\r\n * This is called during the FABRIK passes to integrate constraints into the algorithm.\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\r\n // Apply non-pole-vector constraints\r\n // IKPoleVectorConstraint is deprecated and ignored in favor of built-in pole vectors\r\n for (const constraint of constraints) {\r\n if (constraint.jointIndex === jointIndex) {\r\n // Skip IKPoleVectorConstraint - use built-in pole vectors instead\r\n if (constraint.constructor.name === 'IKPoleVectorConstraint') {\r\n continue;\r\n }\r\n constraint.apply(this._chain.joints);\r\n }\r\n }\r\n\r\n // Apply built-in pole vector if configured for this joint\r\n const poleConfig = this._poleVectors.get(jointIndex);\r\n if (poleConfig && poleConfig.weight > 0.001) {\r\n this._applyPoleVectorTwist(jointIndex, poleConfig.position, poleConfig.weight);\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 adjusts the joint position to align with the pole vector.\r\n * It uses the same algorithm as IKPoleVectorConstraint but is integrated\r\n * into the solver for better performance and control.\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 * Stretch the chain toward an unreachable target.\r\n * All joints are aligned in a straight line toward the target.\r\n *\r\n * @param target - Unreachable target position\r\n */\r\n private _stretchToward(target: Vector3): void {\r\n const joints = this._chain.joints;\r\n const rootPos = joints[0].originalPosition;\r\n\r\n // Calculate direction from root to target\r\n const direction = Vector3.sub(target, rootPos, new Vector3()).inplaceNormalize();\r\n\r\n // Place each joint along the direction at its bone length\r\n let currentPos = rootPos.clone();\r\n for (let i = 0; i < joints.length; i++) {\r\n joints[i].position.set(currentPos);\r\n if (i < joints.length - 1) {\r\n const offset = Vector3.scale(direction, joints[i].boneLength, new Vector3());\r\n currentPos.addBy(offset);\r\n }\r\n }\r\n }\r\n}\r\n"],"names":["FABRIKSolver","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","rootPos","originalPosition","distToTarget","Vector3","distance","totalLength","_stretchToward","converged","iteration","_maxIterations","distToEnd","_tolerance","_forwardPass","_backwardPass","applyToNodes","joint","nextJoint","originalDir","sub","newDir","originalDirNorm","normalize","newDirNorm","deltaRotation","Quaternion","IKUtils","fromToRotation","worldRotation","multiply","originalRotation","swing","twist","decomposeSwingTwist","twistAngle","getTwistAngle","constraint","clampAndSmoothTwist","previousTwist","clampedTwist","fromAxisAngle","slerp","previousIKRotation","node","parent","parentWorldRotation","worldMatrix","decompose","parentInvRotation","conjugate","localRotation","rotation","childJoint","direction","magnitude","scaleBy","scale","boneLength","add","_applyConstraintsForJoint","constraints","name","apply","poleConfig","_applyPoleVectorTwist","parentJoint","currentJoint","parentPos","currentPos","childPos","parentToChild","lineLength","lineDir","parentToCurrent","projectionLength","dot","projectionPoint","perpendicular","perpLength","parentToPole","poleProjectionLength","poleProjectionPoint","poleDirection","poleDirLength","desiredPerpendicular","newPosition","blended","x","y","z","inplaceNormalize","offset","addBy"],"mappings":"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"}
@@ -4,8 +4,13 @@ import { IKConstraint } from './ik_constraint.js';
4
4
  /**
5
5
  * Pole vector constraint for IK chains.
6
6
  *
7
- * Controls the twist/rotation of a joint chain by ensuring the middle joint
8
- * bends toward a specified pole vector position.
7
+ * @deprecated Use the built-in pole vector methods on IK solvers instead:
8
+ * - {@link FABRIKSolver.setPoleVector}
9
+ * - {@link CCDSolver.setPoleVector}
10
+ * - {@link TwoBoneIKSolver.poleVector}
11
+ *
12
+ * This class is deprecated and will be removed in a future version.
13
+ * The built-in pole vector methods provide better performance and more control.
9
14
  *
10
15
  * @remarks
11
16
  * This is commonly used for arms and legs to control which direction
@@ -1 +1 @@
1
- {"version":3,"file":"ik_pole_constraint.js","sources":["../../../src/animation/ik/ik_pole_constraint.ts"],"sourcesContent":["import { Vector3 } from '@zephyr3d/base';\r\nimport { IKConstraint } from './ik_constraint';\r\nimport type { IKJoint } from './ik_joint';\r\n\r\n/**\r\n * Pole vector constraint for IK chains.\r\n *\r\n * Controls the twist/rotation of a joint chain by ensuring the middle joint\r\n * bends toward a specified pole vector position.\r\n *\r\n * @remarks\r\n * This is commonly used for arms and legs to control which direction\r\n * the elbow or knee points. For example, ensuring an elbow points\r\n * backward or a knee points forward.\r\n *\r\n * The pole vector defines a plane, and the middle joint is constrained\r\n * to lie on this plane.\r\n *\r\n * @public\r\n */\r\nexport class IKPoleVectorConstraint extends IKConstraint {\r\n /** The pole vector position in world space */\r\n private _poleVector: Vector3;\r\n /** Weight of the constraint (0 = no effect, 1 = full effect) */\r\n private _weight: number;\r\n\r\n /**\r\n * Create a pole vector constraint.\r\n *\r\n * @param jointIndex - Index of the middle joint to constrain (typically elbow or knee)\r\n * @param poleVector - Position in world space that the joint should point toward\r\n * @param weight - Constraint weight (0-1, default: 1)\r\n */\r\n constructor(jointIndex: number, poleVector: Vector3, weight = 1) {\r\n super(jointIndex);\r\n this._poleVector = poleVector.clone();\r\n this._weight = Math.max(0, Math.min(1, weight));\r\n }\r\n\r\n /**\r\n * Get the pole vector position.\r\n */\r\n get poleVector(): Vector3 {\r\n return this._poleVector;\r\n }\r\n\r\n /**\r\n * Set the pole vector position.\r\n */\r\n set poleVector(value: Vector3) {\r\n this._poleVector.set(value);\r\n }\r\n\r\n /**\r\n * Get the constraint weight.\r\n */\r\n get weight(): number {\r\n return this._weight;\r\n }\r\n\r\n /**\r\n * Set the constraint weight (0-1).\r\n */\r\n set weight(value: number) {\r\n this._weight = Math.max(0, Math.min(1, value));\r\n }\r\n\r\n /**\r\n * Apply the pole vector constraint.\r\n *\r\n * This adjusts the middle joint position to align with the pole vector\r\n * while maintaining bone lengths.\r\n */\r\n apply(joints: IKJoint[]): void {\r\n const index = this._jointIndex;\r\n\r\n // Need at least 3 joints (parent, this, child)\r\n if (index < 1 || index >= joints.length - 1) {\r\n return;\r\n }\r\n\r\n if (this._weight < 0.001) {\r\n return; // No effect\r\n }\r\n\r\n const parentJoint = joints[index - 1];\r\n const currentJoint = joints[index];\r\n const childJoint = joints[index + 1];\r\n\r\n // Calculate the plane defined by parent, child, and pole vector\r\n const parentPos = parentJoint.position;\r\n const childPos = childJoint.position;\r\n const currentPos = currentJoint.position;\r\n\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 projectionPoint.addBy(parentPos);\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(this._poleVector, parentPos, new Vector3());\r\n const poleProjectionLength = Vector3.dot(parentToPole, lineDir);\r\n const poleProjectionPoint = Vector3.scale(lineDir, poleProjectionLength, new Vector3());\r\n poleProjectionPoint.addBy(parentPos);\r\n\r\n // Direction from projection to pole (perpendicular to line)\r\n const poleDirection = Vector3.sub(this._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 (this._weight < 0.999) {\r\n // Manual lerp: result = a + (b - a) * t\r\n const blended = new Vector3();\r\n blended.x = currentPos.x + (newPosition.x - currentPos.x) * this._weight;\r\n blended.y = currentPos.y + (newPosition.y - currentPos.y) * this._weight;\r\n blended.z = currentPos.z + (newPosition.z - currentPos.z) * this._weight;\r\n currentJoint.position.set(blended);\r\n } else {\r\n currentJoint.position.set(newPosition);\r\n }\r\n }\r\n}\r\n"],"names":["IKPoleVectorConstraint","IKConstraint","jointIndex","poleVector","weight","_poleVector","clone","_weight","Math","max","min","value","set","apply","joints","index","_jointIndex","length","parentJoint","currentJoint","childJoint","parentPos","position","childPos","currentPos","parentToChild","Vector3","sub","lineLength","magnitude","lineDir","scale","parentToCurrent","projectionLength","dot","projectionPoint","addBy","perpendicular","perpLength","parentToPole","poleProjectionLength","poleProjectionPoint","poleDirection","poleDirLength","scaleBy","desiredPerpendicular","newPosition","add","blended","x","y","z"],"mappings":"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"}
1
+ {"version":3,"file":"ik_pole_constraint.js","sources":["../../../src/animation/ik/ik_pole_constraint.ts"],"sourcesContent":["import { Vector3 } from '@zephyr3d/base';\r\nimport { IKConstraint } from './ik_constraint';\r\nimport type { IKJoint } from './ik_joint';\r\n\r\n/**\r\n * Pole vector constraint for IK chains.\r\n *\r\n * @deprecated Use the built-in pole vector methods on IK solvers instead:\r\n * - {@link FABRIKSolver.setPoleVector}\r\n * - {@link CCDSolver.setPoleVector}\r\n * - {@link TwoBoneIKSolver.poleVector}\r\n *\r\n * This class is deprecated and will be removed in a future version.\r\n * The built-in pole vector methods provide better performance and more control.\r\n *\r\n * @remarks\r\n * This is commonly used for arms and legs to control which direction\r\n * the elbow or knee points. For example, ensuring an elbow points\r\n * backward or a knee points forward.\r\n *\r\n * The pole vector defines a plane, and the middle joint is constrained\r\n * to lie on this plane.\r\n *\r\n * @public\r\n */\r\nexport class IKPoleVectorConstraint extends IKConstraint {\r\n /** The pole vector position in world space */\r\n private _poleVector: Vector3;\r\n /** Weight of the constraint (0 = no effect, 1 = full effect) */\r\n private _weight: number;\r\n\r\n /**\r\n * Create a pole vector constraint.\r\n *\r\n * @param jointIndex - Index of the middle joint to constrain (typically elbow or knee)\r\n * @param poleVector - Position in world space that the joint should point toward\r\n * @param weight - Constraint weight (0-1, default: 1)\r\n */\r\n constructor(jointIndex: number, poleVector: Vector3, weight = 1) {\r\n super(jointIndex);\r\n this._poleVector = poleVector.clone();\r\n this._weight = Math.max(0, Math.min(1, weight));\r\n }\r\n\r\n /**\r\n * Get the pole vector position.\r\n */\r\n get poleVector(): Vector3 {\r\n return this._poleVector;\r\n }\r\n\r\n /**\r\n * Set the pole vector position.\r\n */\r\n set poleVector(value: Vector3) {\r\n this._poleVector.set(value);\r\n }\r\n\r\n /**\r\n * Get the constraint weight.\r\n */\r\n get weight(): number {\r\n return this._weight;\r\n }\r\n\r\n /**\r\n * Set the constraint weight (0-1).\r\n */\r\n set weight(value: number) {\r\n this._weight = Math.max(0, Math.min(1, value));\r\n }\r\n\r\n /**\r\n * Apply the pole vector constraint.\r\n *\r\n * This adjusts the middle joint position to align with the pole vector\r\n * while maintaining bone lengths.\r\n */\r\n apply(joints: IKJoint[]): void {\r\n const index = this._jointIndex;\r\n\r\n // Need at least 3 joints (parent, this, child)\r\n if (index < 1 || index >= joints.length - 1) {\r\n return;\r\n }\r\n\r\n if (this._weight < 0.001) {\r\n return; // No effect\r\n }\r\n\r\n const parentJoint = joints[index - 1];\r\n const currentJoint = joints[index];\r\n const childJoint = joints[index + 1];\r\n\r\n // Calculate the plane defined by parent, child, and pole vector\r\n const parentPos = parentJoint.position;\r\n const childPos = childJoint.position;\r\n const currentPos = currentJoint.position;\r\n\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 projectionPoint.addBy(parentPos);\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(this._poleVector, parentPos, new Vector3());\r\n const poleProjectionLength = Vector3.dot(parentToPole, lineDir);\r\n const poleProjectionPoint = Vector3.scale(lineDir, poleProjectionLength, new Vector3());\r\n poleProjectionPoint.addBy(parentPos);\r\n\r\n // Direction from projection to pole (perpendicular to line)\r\n const poleDirection = Vector3.sub(this._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 (this._weight < 0.999) {\r\n // Manual lerp: result = a + (b - a) * t\r\n const blended = new Vector3();\r\n blended.x = currentPos.x + (newPosition.x - currentPos.x) * this._weight;\r\n blended.y = currentPos.y + (newPosition.y - currentPos.y) * this._weight;\r\n blended.z = currentPos.z + (newPosition.z - currentPos.z) * this._weight;\r\n currentJoint.position.set(blended);\r\n } else {\r\n currentJoint.position.set(newPosition);\r\n }\r\n }\r\n}\r\n"],"names":["IKPoleVectorConstraint","IKConstraint","jointIndex","poleVector","weight","_poleVector","clone","_weight","Math","max","min","value","set","apply","joints","index","_jointIndex","length","parentJoint","currentJoint","childJoint","parentPos","position","childPos","currentPos","parentToChild","Vector3","sub","lineLength","magnitude","lineDir","scale","parentToCurrent","projectionLength","dot","projectionPoint","addBy","perpendicular","perpLength","parentToPole","poleProjectionLength","poleProjectionPoint","poleDirection","poleDirLength","scaleBy","desiredPerpendicular","newPosition","add","blended","x","y","z"],"mappings":"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"}
@@ -46,85 +46,6 @@ import { Vector3, Quaternion } from '@zephyr3d/base';
46
46
  return Vector3.distance(start, end);
47
47
  }
48
48
  /**
49
- * Decompose a quaternion into swing and twist components around a given axis.
50
- *
51
- * @remarks
52
- * Given a rotation Q and an axis A, decompose Q into:
53
- * - Twist: rotation around A
54
- * - Swing: rotation perpendicular to A
55
- * Such that Q = Twist * Swing
56
- *
57
- * Algorithm:
58
- * 1. Project Q's imaginary part onto axis to get twist component
59
- * 2. Normalize to get pure twist rotation
60
- * 3. Calculate swing = twist^-1 * Q
61
- *
62
- * @param q - The quaternion to decompose
63
- * @param axis - The twist axis (must be normalized)
64
- * @param outSwing - Output swing rotation
65
- * @param outTwist - Output twist rotation
66
- */ static decomposeSwingTwist(q, axis, outSwing, outTwist) {
67
- // Project quaternion's imaginary part (xyz) onto twist axis
68
- // twist quaternion = (w, (xyz · axis) * axis)
69
- const dot = q.x * axis.x + q.y * axis.y + q.z * axis.z;
70
- outTwist.x = axis.x * dot;
71
- outTwist.y = axis.y * dot;
72
- outTwist.z = axis.z * dot;
73
- outTwist.w = q.w;
74
- // Normalize twist quaternion
75
- const twistLen = Math.sqrt(outTwist.x * outTwist.x + outTwist.y * outTwist.y + outTwist.z * outTwist.z + outTwist.w * outTwist.w);
76
- if (twistLen < 0.000001) {
77
- // No rotation or rotation perpendicular to axis
78
- outTwist.identity();
79
- outSwing.set(q);
80
- return;
81
- }
82
- outTwist.x /= twistLen;
83
- outTwist.y /= twistLen;
84
- outTwist.z /= twistLen;
85
- outTwist.w /= twistLen;
86
- // Calculate swing: Q = Twist * Swing => Swing = Twist^-1 * Q
87
- const twistInv = Quaternion.conjugate(outTwist, new Quaternion());
88
- Quaternion.multiply(twistInv, q, outSwing);
89
- }
90
- /**
91
- * Get the twist angle (in radians) from a twist quaternion around an axis.
92
- *
93
- * @param twist - The twist quaternion
94
- * @param axis - The twist axis (must be normalized)
95
- * @returns Twist angle in radians, range [-PI, PI]
96
- */ static getTwistAngle(twist, axis) {
97
- // For a twist quaternion around axis: twist = (cos(θ/2), sin(θ/2) * axis)
98
- // We can extract the angle from the quaternion components
99
- // Ensure twist is normalized
100
- const len = Math.sqrt(twist.x * twist.x + twist.y * twist.y + twist.z * twist.z + twist.w * twist.w);
101
- if (len < 0.000001) {
102
- return 0;
103
- }
104
- const w = twist.w / len;
105
- const halfAngle = Math.acos(Math.max(-1, Math.min(1, w)));
106
- // Determine sign based on axis direction
107
- const dot = twist.x * axis.x + twist.y * axis.y + twist.z * axis.z;
108
- const sign = dot >= 0 ? 1 : -1;
109
- return sign * 2 * halfAngle;
110
- }
111
- /**
112
- * Create a twist quaternion from an angle and axis.
113
- *
114
- * @param angle - Twist angle in radians
115
- * @param axis - The twist axis (must be normalized)
116
- * @param result - Output quaternion
117
- * @returns The twist quaternion
118
- */ static createTwist(angle, axis, result) {
119
- const halfAngle = angle * 0.5;
120
- const s = Math.sin(halfAngle);
121
- result.x = axis.x * s;
122
- result.y = axis.y * s;
123
- result.z = axis.z * s;
124
- result.w = Math.cos(halfAngle);
125
- return result;
126
- }
127
- /**
128
49
  * Clamp twist angle and optionally smooth with previous twist.
129
50
  *
130
51
  * @param currentTwist - Current twist angle in radians
@@ -1 +1 @@
1
- {"version":3,"file":"ik_utils.js","sources":["../../../src/animation/ik/ik_utils.ts"],"sourcesContent":["import { Vector3, Quaternion } from '@zephyr3d/base';\r\n\r\n/**\r\n * Utility functions for IK calculations.\r\n *\r\n * @internal\r\n */\r\nexport class IKUtils {\r\n /**\r\n * Calculate the rotation needed to align 'from' direction to 'to' direction.\r\n *\r\n * @param from - Starting direction vector\r\n * @param to - Target direction vector\r\n * @param result - Output quaternion\r\n * @returns The rotation quaternion\r\n */\r\n static fromToRotation(from: Vector3, to: Vector3, result: Quaternion): Quaternion {\r\n const fromNorm = Vector3.normalize(from, new Vector3());\r\n const toNorm = Vector3.normalize(to, new Vector3());\r\n\r\n const dot = Vector3.dot(fromNorm, toNorm);\r\n\r\n // Vectors are parallel\r\n if (dot >= 0.999999) {\r\n return result.identity();\r\n }\r\n\r\n // Vectors are opposite\r\n if (dot <= -0.999999) {\r\n // Find an orthogonal axis\r\n let axis = Vector3.cross(Vector3.axisPX(), fromNorm, new Vector3());\r\n const lenSq = axis.x * axis.x + axis.y * axis.y + axis.z * axis.z;\r\n if (lenSq < 0.000001) {\r\n axis = Vector3.cross(Vector3.axisPY(), fromNorm, new Vector3());\r\n }\r\n axis.inplaceNormalize();\r\n return result.fromAxisAngle(axis, Math.PI);\r\n }\r\n\r\n // General case\r\n const axis = Vector3.cross(fromNorm, toNorm).inplaceNormalize();\r\n const angle = Math.acos(dot);\r\n return result.fromAxisAngle(axis, angle);\r\n }\r\n\r\n /**\r\n * Calculate bone length between two positions.\r\n *\r\n * @param start - Start position\r\n * @param end - End position\r\n * @returns Distance between positions\r\n */\r\n static calculateBoneLength(start: Vector3, end: Vector3): number {\r\n return Vector3.distance(start, end);\r\n }\r\n\r\n /**\r\n * Decompose a quaternion into swing and twist components around a given axis.\r\n *\r\n * @remarks\r\n * Given a rotation Q and an axis A, decompose Q into:\r\n * - Twist: rotation around A\r\n * - Swing: rotation perpendicular to A\r\n * Such that Q = Twist * Swing\r\n *\r\n * Algorithm:\r\n * 1. Project Q's imaginary part onto axis to get twist component\r\n * 2. Normalize to get pure twist rotation\r\n * 3. Calculate swing = twist^-1 * Q\r\n *\r\n * @param q - The quaternion to decompose\r\n * @param axis - The twist axis (must be normalized)\r\n * @param outSwing - Output swing rotation\r\n * @param outTwist - Output twist rotation\r\n */\r\n static decomposeSwingTwist(q: Quaternion, axis: Vector3, outSwing: Quaternion, outTwist: Quaternion): void {\r\n // Project quaternion's imaginary part (xyz) onto twist axis\r\n // twist quaternion = (w, (xyz · axis) * axis)\r\n const dot = q.x * axis.x + q.y * axis.y + q.z * axis.z;\r\n\r\n outTwist.x = axis.x * dot;\r\n outTwist.y = axis.y * dot;\r\n outTwist.z = axis.z * dot;\r\n outTwist.w = q.w;\r\n\r\n // Normalize twist quaternion\r\n const twistLen = Math.sqrt(\r\n outTwist.x * outTwist.x + outTwist.y * outTwist.y + outTwist.z * outTwist.z + outTwist.w * outTwist.w\r\n );\r\n\r\n if (twistLen < 0.000001) {\r\n // No rotation or rotation perpendicular to axis\r\n outTwist.identity();\r\n outSwing.set(q);\r\n return;\r\n }\r\n\r\n outTwist.x /= twistLen;\r\n outTwist.y /= twistLen;\r\n outTwist.z /= twistLen;\r\n outTwist.w /= twistLen;\r\n\r\n // Calculate swing: Q = Twist * Swing => Swing = Twist^-1 * Q\r\n const twistInv = Quaternion.conjugate(outTwist, new Quaternion());\r\n Quaternion.multiply(twistInv, q, outSwing);\r\n }\r\n\r\n /**\r\n * Get the twist angle (in radians) from a twist quaternion around an axis.\r\n *\r\n * @param twist - The twist quaternion\r\n * @param axis - The twist axis (must be normalized)\r\n * @returns Twist angle in radians, range [-PI, PI]\r\n */\r\n static getTwistAngle(twist: Quaternion, axis: Vector3): number {\r\n // For a twist quaternion around axis: twist = (cos(θ/2), sin(θ/2) * axis)\r\n // We can extract the angle from the quaternion components\r\n\r\n // Ensure twist is normalized\r\n const len = Math.sqrt(twist.x * twist.x + twist.y * twist.y + twist.z * twist.z + twist.w * twist.w);\r\n if (len < 0.000001) {\r\n return 0;\r\n }\r\n\r\n const w = twist.w / len;\r\n const halfAngle = Math.acos(Math.max(-1, Math.min(1, w)));\r\n\r\n // Determine sign based on axis direction\r\n const dot = twist.x * axis.x + twist.y * axis.y + twist.z * axis.z;\r\n const sign = dot >= 0 ? 1 : -1;\r\n\r\n return sign * 2 * halfAngle;\r\n }\r\n\r\n /**\r\n * Create a twist quaternion from an angle and axis.\r\n *\r\n * @param angle - Twist angle in radians\r\n * @param axis - The twist axis (must be normalized)\r\n * @param result - Output quaternion\r\n * @returns The twist quaternion\r\n */\r\n static createTwist(angle: number, axis: Vector3, result: Quaternion): Quaternion {\r\n const halfAngle = angle * 0.5;\r\n const s = Math.sin(halfAngle);\r\n result.x = axis.x * s;\r\n result.y = axis.y * s;\r\n result.z = axis.z * s;\r\n result.w = Math.cos(halfAngle);\r\n return result;\r\n }\r\n\r\n /**\r\n * Clamp twist angle and optionally smooth with previous twist.\r\n *\r\n * @param currentTwist - Current twist angle in radians\r\n * @param previousTwist - Previous frame's twist angle in radians (optional)\r\n * @param minTwist - Minimum allowed twist angle in radians\r\n * @param maxTwist - Maximum allowed twist angle in radians\r\n * @param smoothFactor - Smoothing factor [0-1], 0 = no smoothing, 1 = full smoothing\r\n * @returns Clamped and smoothed twist angle\r\n */\r\n static clampAndSmoothTwist(\r\n currentTwist: number,\r\n previousTwist: number | undefined,\r\n minTwist: number,\r\n maxTwist: number,\r\n smoothFactor: number = 0.5\r\n ): number {\r\n // Clamp to range\r\n let clampedTwist = Math.max(minTwist, Math.min(maxTwist, currentTwist));\r\n\r\n // Smooth with previous frame if available\r\n if (previousTwist !== undefined && smoothFactor > 0.001) {\r\n // Normalize angle difference to [-PI, PI]\r\n let diff = clampedTwist - previousTwist;\r\n while (diff > Math.PI) {\r\n diff -= 2 * Math.PI;\r\n }\r\n while (diff < -Math.PI) {\r\n diff += 2 * Math.PI;\r\n }\r\n\r\n // Lerp\r\n clampedTwist = previousTwist + diff * (1 - smoothFactor);\r\n }\r\n\r\n return clampedTwist;\r\n }\r\n\r\n /**\r\n * Calculate a look-at rotation with twist constraint using a pole vector.\r\n *\r\n * @remarks\r\n * This creates a rotation that:\r\n * 1. Aligns 'forward' direction to 'targetDir'\r\n * 2. Keeps the perpendicular plane aligned with 'poleDir'\r\n *\r\n * This prevents unwanted twist around the bone axis by using an external\r\n * reference direction (pole vector) rather than relying on previous rotations.\r\n *\r\n * @param forward - Current forward direction (will be aligned to targetDir)\r\n * @param targetDir - Desired forward direction\r\n * @param poleDir - Direction that should be in the \"up\" hemisphere (from joint position)\r\n * @param result - Output quaternion\r\n * @returns The rotation quaternion\r\n */\r\n static lookAtRotationWithPole(\r\n forward: Vector3,\r\n targetDir: Vector3,\r\n poleDir: Vector3,\r\n result: Quaternion\r\n ): Quaternion {\r\n const forwardNorm = Vector3.normalize(forward, new Vector3());\r\n const targetDirNorm = Vector3.normalize(targetDir, new Vector3());\r\n const poleDirNorm = Vector3.normalize(poleDir, new Vector3());\r\n\r\n // First, align forward to targetDir (swing rotation)\r\n const swingRotation = new Quaternion();\r\n this.fromToRotation(forwardNorm, targetDirNorm, swingRotation);\r\n\r\n // Calculate the \"right\" vector perpendicular to targetDir and poleDir\r\n // This defines the plane that the bone should bend in\r\n const right = Vector3.cross(targetDirNorm, poleDirNorm, new Vector3());\r\n const rightLenSq = right.x * right.x + right.y * right.y + right.z * right.z;\r\n\r\n // If pole is parallel to target direction, no twist correction possible\r\n if (rightLenSq < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n right.scaleBy(1 / Math.sqrt(rightLenSq));\r\n\r\n // Calculate the \"up\" vector perpendicular to targetDir in the pole plane\r\n const up = Vector3.cross(right, targetDirNorm, new Vector3()).inplaceNormalize();\r\n\r\n // Now we need to find the twist rotation around targetDir\r\n // We want the local \"up\" axis to align with the calculated \"up\" vector\r\n\r\n // Get a perpendicular vector to forward in the original space\r\n let originalUp = Vector3.cross(forwardNorm, Vector3.axisPY(), new Vector3());\r\n const originalUpLenSq =\r\n originalUp.x * originalUp.x + originalUp.y * originalUp.y + originalUp.z * originalUp.z;\r\n if (originalUpLenSq < 0.000001) {\r\n originalUp = Vector3.cross(forwardNorm, Vector3.axisPX(), new Vector3());\r\n }\r\n originalUp.inplaceNormalize();\r\n\r\n // Rotate originalUp by swing rotation to see where it ends up\r\n const rotatedUp = swingRotation.transform(originalUp, new Vector3());\r\n\r\n // Project rotatedUp onto the plane perpendicular to targetDir\r\n const rotatedUpDot = Vector3.dot(rotatedUp, targetDirNorm);\r\n const rotatedUpProj = Vector3.scale(targetDirNorm, rotatedUpDot, new Vector3());\r\n const rotatedUpPerp = Vector3.sub(rotatedUp, rotatedUpProj, new Vector3());\r\n const rotatedUpPerpLen = rotatedUpPerp.magnitude;\r\n\r\n if (rotatedUpPerpLen < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n rotatedUpPerp.scaleBy(1 / rotatedUpPerpLen);\r\n\r\n // Calculate twist rotation to align rotatedUpPerp with up\r\n const twistRotation = new Quaternion();\r\n this.fromToRotation(rotatedUpPerp, up, twistRotation);\r\n\r\n // Combine swing and twist\r\n return Quaternion.multiply(twistRotation, swingRotation, result);\r\n }\r\n\r\n /**\r\n * Calculate a look-at rotation with twist constraint.\r\n *\r\n * @remarks\r\n * This creates a rotation that:\r\n * 1. Aligns 'forward' direction to 'targetDir'\r\n * 2. Keeps 'up' direction as close as possible to 'targetUp'\r\n *\r\n * This prevents unwanted twist around the bone axis.\r\n *\r\n * @param forward - Current forward direction (will be aligned to targetDir)\r\n * @param targetDir - Desired forward direction\r\n * @param up - Current up direction (perpendicular to forward)\r\n * @param targetUp - Desired up direction (will be projected perpendicular to targetDir)\r\n * @param result - Output quaternion\r\n * @returns The rotation quaternion\r\n */\r\n static lookAtRotation(\r\n forward: Vector3,\r\n targetDir: Vector3,\r\n up: Vector3,\r\n targetUp: Vector3,\r\n result: Quaternion\r\n ): Quaternion {\r\n const forwardNorm = Vector3.normalize(forward, new Vector3());\r\n const targetDirNorm = Vector3.normalize(targetDir, new Vector3());\r\n\r\n // First, align forward to targetDir (swing rotation)\r\n const swingRotation = new Quaternion();\r\n this.fromToRotation(forwardNorm, targetDirNorm, swingRotation);\r\n\r\n // Rotate the up vector by swing rotation\r\n const rotatedUp = swingRotation.transform(up, new Vector3());\r\n\r\n // Project targetUp onto plane perpendicular to targetDir\r\n const dot = Vector3.dot(targetUp, targetDirNorm);\r\n const projection = Vector3.scale(targetDirNorm, dot, new Vector3());\r\n const targetUpPerp = Vector3.sub(targetUp, projection, new Vector3());\r\n const targetUpPerpLen = targetUpPerp.magnitude;\r\n\r\n // If targetUp is parallel to targetDir, no twist correction needed\r\n if (targetUpPerpLen < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n targetUpPerp.scaleBy(1 / targetUpPerpLen);\r\n\r\n // Project rotatedUp onto the same plane\r\n const rotatedUpDot = Vector3.dot(rotatedUp, targetDirNorm);\r\n const rotatedUpProj = Vector3.scale(targetDirNorm, rotatedUpDot, new Vector3());\r\n const rotatedUpPerp = Vector3.sub(rotatedUp, rotatedUpProj, new Vector3());\r\n const rotatedUpPerpLen = rotatedUpPerp.magnitude;\r\n\r\n if (rotatedUpPerpLen < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n rotatedUpPerp.scaleBy(1 / rotatedUpPerpLen);\r\n\r\n // Calculate twist rotation around targetDir\r\n const twistRotation = new Quaternion();\r\n this.fromToRotation(rotatedUpPerp, targetUpPerp, twistRotation);\r\n\r\n // Combine swing and twist\r\n return Quaternion.multiply(twistRotation, swingRotation, result);\r\n }\r\n}\r\n"],"names":["IKUtils","fromToRotation","from","to","result","fromNorm","Vector3","normalize","toNorm","dot","identity","axis","cross","axisPX","lenSq","x","y","z","axisPY","inplaceNormalize","fromAxisAngle","Math","PI","angle","acos","calculateBoneLength","start","end","distance","decomposeSwingTwist","q","outSwing","outTwist","w","twistLen","sqrt","set","twistInv","Quaternion","conjugate","multiply","getTwistAngle","twist","len","halfAngle","max","min","sign","createTwist","s","sin","cos","clampAndSmoothTwist","currentTwist","previousTwist","minTwist","maxTwist","smoothFactor","clampedTwist","undefined","diff","lookAtRotationWithPole","forward","targetDir","poleDir","forwardNorm","targetDirNorm","poleDirNorm","swingRotation","right","rightLenSq","scaleBy","up","originalUp","originalUpLenSq","rotatedUp","transform","rotatedUpDot","rotatedUpProj","scale","rotatedUpPerp","sub","rotatedUpPerpLen","magnitude","twistRotation","lookAtRotation","targetUp","projection","targetUpPerp","targetUpPerpLen"],"mappings":"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"}
1
+ {"version":3,"file":"ik_utils.js","sources":["../../../src/animation/ik/ik_utils.ts"],"sourcesContent":["import { Vector3, Quaternion } from '@zephyr3d/base';\r\n\r\n/**\r\n * Utility functions for IK calculations.\r\n *\r\n * @internal\r\n */\r\nexport class IKUtils {\r\n /**\r\n * Calculate the rotation needed to align 'from' direction to 'to' direction.\r\n *\r\n * @param from - Starting direction vector\r\n * @param to - Target direction vector\r\n * @param result - Output quaternion\r\n * @returns The rotation quaternion\r\n */\r\n static fromToRotation(from: Vector3, to: Vector3, result: Quaternion): Quaternion {\r\n const fromNorm = Vector3.normalize(from, new Vector3());\r\n const toNorm = Vector3.normalize(to, new Vector3());\r\n\r\n const dot = Vector3.dot(fromNorm, toNorm);\r\n\r\n // Vectors are parallel\r\n if (dot >= 0.999999) {\r\n return result.identity();\r\n }\r\n\r\n // Vectors are opposite\r\n if (dot <= -0.999999) {\r\n // Find an orthogonal axis\r\n let axis = Vector3.cross(Vector3.axisPX(), fromNorm, new Vector3());\r\n const lenSq = axis.x * axis.x + axis.y * axis.y + axis.z * axis.z;\r\n if (lenSq < 0.000001) {\r\n axis = Vector3.cross(Vector3.axisPY(), fromNorm, new Vector3());\r\n }\r\n axis.inplaceNormalize();\r\n return result.fromAxisAngle(axis, Math.PI);\r\n }\r\n\r\n // General case\r\n const axis = Vector3.cross(fromNorm, toNorm).inplaceNormalize();\r\n const angle = Math.acos(dot);\r\n return result.fromAxisAngle(axis, angle);\r\n }\r\n\r\n /**\r\n * Calculate bone length between two positions.\r\n *\r\n * @param start - Start position\r\n * @param end - End position\r\n * @returns Distance between positions\r\n */\r\n static calculateBoneLength(start: Vector3, end: Vector3): number {\r\n return Vector3.distance(start, end);\r\n }\r\n\r\n /**\r\n * Clamp twist angle and optionally smooth with previous twist.\r\n *\r\n * @param currentTwist - Current twist angle in radians\r\n * @param previousTwist - Previous frame's twist angle in radians (optional)\r\n * @param minTwist - Minimum allowed twist angle in radians\r\n * @param maxTwist - Maximum allowed twist angle in radians\r\n * @param smoothFactor - Smoothing factor [0-1], 0 = no smoothing, 1 = full smoothing\r\n * @returns Clamped and smoothed twist angle\r\n */\r\n static clampAndSmoothTwist(\r\n currentTwist: number,\r\n previousTwist: number | undefined,\r\n minTwist: number,\r\n maxTwist: number,\r\n smoothFactor: number = 0.5\r\n ): number {\r\n // Clamp to range\r\n let clampedTwist = Math.max(minTwist, Math.min(maxTwist, currentTwist));\r\n\r\n // Smooth with previous frame if available\r\n if (previousTwist !== undefined && smoothFactor > 0.001) {\r\n // Normalize angle difference to [-PI, PI]\r\n let diff = clampedTwist - previousTwist;\r\n while (diff > Math.PI) {\r\n diff -= 2 * Math.PI;\r\n }\r\n while (diff < -Math.PI) {\r\n diff += 2 * Math.PI;\r\n }\r\n\r\n // Lerp\r\n clampedTwist = previousTwist + diff * (1 - smoothFactor);\r\n }\r\n\r\n return clampedTwist;\r\n }\r\n\r\n /**\r\n * Calculate a look-at rotation with twist constraint using a pole vector.\r\n *\r\n * @remarks\r\n * This creates a rotation that:\r\n * 1. Aligns 'forward' direction to 'targetDir'\r\n * 2. Keeps the perpendicular plane aligned with 'poleDir'\r\n *\r\n * This prevents unwanted twist around the bone axis by using an external\r\n * reference direction (pole vector) rather than relying on previous rotations.\r\n *\r\n * @param forward - Current forward direction (will be aligned to targetDir)\r\n * @param targetDir - Desired forward direction\r\n * @param poleDir - Direction that should be in the \"up\" hemisphere (from joint position)\r\n * @param result - Output quaternion\r\n * @returns The rotation quaternion\r\n */\r\n static lookAtRotationWithPole(\r\n forward: Vector3,\r\n targetDir: Vector3,\r\n poleDir: Vector3,\r\n result: Quaternion\r\n ): Quaternion {\r\n const forwardNorm = Vector3.normalize(forward, new Vector3());\r\n const targetDirNorm = Vector3.normalize(targetDir, new Vector3());\r\n const poleDirNorm = Vector3.normalize(poleDir, new Vector3());\r\n\r\n // First, align forward to targetDir (swing rotation)\r\n const swingRotation = new Quaternion();\r\n this.fromToRotation(forwardNorm, targetDirNorm, swingRotation);\r\n\r\n // Calculate the \"right\" vector perpendicular to targetDir and poleDir\r\n // This defines the plane that the bone should bend in\r\n const right = Vector3.cross(targetDirNorm, poleDirNorm, new Vector3());\r\n const rightLenSq = right.x * right.x + right.y * right.y + right.z * right.z;\r\n\r\n // If pole is parallel to target direction, no twist correction possible\r\n if (rightLenSq < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n right.scaleBy(1 / Math.sqrt(rightLenSq));\r\n\r\n // Calculate the \"up\" vector perpendicular to targetDir in the pole plane\r\n const up = Vector3.cross(right, targetDirNorm, new Vector3()).inplaceNormalize();\r\n\r\n // Now we need to find the twist rotation around targetDir\r\n // We want the local \"up\" axis to align with the calculated \"up\" vector\r\n\r\n // Get a perpendicular vector to forward in the original space\r\n let originalUp = Vector3.cross(forwardNorm, Vector3.axisPY(), new Vector3());\r\n const originalUpLenSq =\r\n originalUp.x * originalUp.x + originalUp.y * originalUp.y + originalUp.z * originalUp.z;\r\n if (originalUpLenSq < 0.000001) {\r\n originalUp = Vector3.cross(forwardNorm, Vector3.axisPX(), new Vector3());\r\n }\r\n originalUp.inplaceNormalize();\r\n\r\n // Rotate originalUp by swing rotation to see where it ends up\r\n const rotatedUp = swingRotation.transform(originalUp, new Vector3());\r\n\r\n // Project rotatedUp onto the plane perpendicular to targetDir\r\n const rotatedUpDot = Vector3.dot(rotatedUp, targetDirNorm);\r\n const rotatedUpProj = Vector3.scale(targetDirNorm, rotatedUpDot, new Vector3());\r\n const rotatedUpPerp = Vector3.sub(rotatedUp, rotatedUpProj, new Vector3());\r\n const rotatedUpPerpLen = rotatedUpPerp.magnitude;\r\n\r\n if (rotatedUpPerpLen < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n rotatedUpPerp.scaleBy(1 / rotatedUpPerpLen);\r\n\r\n // Calculate twist rotation to align rotatedUpPerp with up\r\n const twistRotation = new Quaternion();\r\n this.fromToRotation(rotatedUpPerp, up, twistRotation);\r\n\r\n // Combine swing and twist\r\n return Quaternion.multiply(twistRotation, swingRotation, result);\r\n }\r\n\r\n /**\r\n * Calculate a look-at rotation with twist constraint.\r\n *\r\n * @remarks\r\n * This creates a rotation that:\r\n * 1. Aligns 'forward' direction to 'targetDir'\r\n * 2. Keeps 'up' direction as close as possible to 'targetUp'\r\n *\r\n * This prevents unwanted twist around the bone axis.\r\n *\r\n * @param forward - Current forward direction (will be aligned to targetDir)\r\n * @param targetDir - Desired forward direction\r\n * @param up - Current up direction (perpendicular to forward)\r\n * @param targetUp - Desired up direction (will be projected perpendicular to targetDir)\r\n * @param result - Output quaternion\r\n * @returns The rotation quaternion\r\n */\r\n static lookAtRotation(\r\n forward: Vector3,\r\n targetDir: Vector3,\r\n up: Vector3,\r\n targetUp: Vector3,\r\n result: Quaternion\r\n ): Quaternion {\r\n const forwardNorm = Vector3.normalize(forward, new Vector3());\r\n const targetDirNorm = Vector3.normalize(targetDir, new Vector3());\r\n\r\n // First, align forward to targetDir (swing rotation)\r\n const swingRotation = new Quaternion();\r\n this.fromToRotation(forwardNorm, targetDirNorm, swingRotation);\r\n\r\n // Rotate the up vector by swing rotation\r\n const rotatedUp = swingRotation.transform(up, new Vector3());\r\n\r\n // Project targetUp onto plane perpendicular to targetDir\r\n const dot = Vector3.dot(targetUp, targetDirNorm);\r\n const projection = Vector3.scale(targetDirNorm, dot, new Vector3());\r\n const targetUpPerp = Vector3.sub(targetUp, projection, new Vector3());\r\n const targetUpPerpLen = targetUpPerp.magnitude;\r\n\r\n // If targetUp is parallel to targetDir, no twist correction needed\r\n if (targetUpPerpLen < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n targetUpPerp.scaleBy(1 / targetUpPerpLen);\r\n\r\n // Project rotatedUp onto the same plane\r\n const rotatedUpDot = Vector3.dot(rotatedUp, targetDirNorm);\r\n const rotatedUpProj = Vector3.scale(targetDirNorm, rotatedUpDot, new Vector3());\r\n const rotatedUpPerp = Vector3.sub(rotatedUp, rotatedUpProj, new Vector3());\r\n const rotatedUpPerpLen = rotatedUpPerp.magnitude;\r\n\r\n if (rotatedUpPerpLen < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n rotatedUpPerp.scaleBy(1 / rotatedUpPerpLen);\r\n\r\n // Calculate twist rotation around targetDir\r\n const twistRotation = new Quaternion();\r\n this.fromToRotation(rotatedUpPerp, targetUpPerp, twistRotation);\r\n\r\n // Combine swing and twist\r\n return Quaternion.multiply(twistRotation, swingRotation, result);\r\n }\r\n}\r\n"],"names":["IKUtils","fromToRotation","from","to","result","fromNorm","Vector3","normalize","toNorm","dot","identity","axis","cross","axisPX","lenSq","x","y","z","axisPY","inplaceNormalize","fromAxisAngle","Math","PI","angle","acos","calculateBoneLength","start","end","distance","clampAndSmoothTwist","currentTwist","previousTwist","minTwist","maxTwist","smoothFactor","clampedTwist","max","min","undefined","diff","lookAtRotationWithPole","forward","targetDir","poleDir","forwardNorm","targetDirNorm","poleDirNorm","swingRotation","Quaternion","right","rightLenSq","set","scaleBy","sqrt","up","originalUp","originalUpLenSq","rotatedUp","transform","rotatedUpDot","rotatedUpProj","scale","rotatedUpPerp","sub","rotatedUpPerpLen","magnitude","twistRotation","multiply","lookAtRotation","targetUp","projection","targetUpPerp","targetUpPerpLen"],"mappings":"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"}
@@ -270,9 +270,9 @@ import { IKUtils } from './ik_utils.js';
270
270
  // Decompose rotation around bone axis
271
271
  const swing = new Quaternion();
272
272
  const twist = new Quaternion();
273
- IKUtils.decomposeSwingTwist(worldRotation, newDirNorm, swing, twist);
273
+ worldRotation.decomposeSwingTwist(newDirNorm, swing, twist);
274
274
  // Get twist angle
275
- let twistAngle = IKUtils.getTwistAngle(twist, newDirNorm);
275
+ let twistAngle = twist.getTwistAngle(newDirNorm);
276
276
  // Get twist constraint for this joint
277
277
  const constraint = this._twistConstraints.get(i);
278
278
  if (constraint) {
@@ -282,8 +282,7 @@ import { IKUtils } from './ik_utils.js';
282
282
  // Store for next frame
283
283
  joint.previousTwist = twistAngle;
284
284
  // Reconstruct rotation from clamped twist: Q = Twist * Swing
285
- const clampedTwist = new Quaternion();
286
- IKUtils.createTwist(twistAngle, newDirNorm, clampedTwist);
285
+ const clampedTwist = Quaternion.fromAxisAngle(newDirNorm, twistAngle);
287
286
  worldRotation = Quaternion.multiply(clampedTwist, swing, worldRotation);
288
287
  // Blend with original rotation based on weight
289
288
  if (weight < 1) {
@@ -1 +1 @@
1
- {"version":3,"file":"two_bone_ik_solver.js","sources":["../../../src/animation/ik/two_bone_ik_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 * Two Bone IK solver for chains with exactly 3 joints (2 bones).\r\n *\r\n * @remarks\r\n * This solver uses an analytical solution specifically optimized for\r\n * two-bone chains like arms (shoulder-elbow-wrist) or legs (hip-knee-ankle).\r\n * It's faster and more stable than iterative methods like FABRIK for this case.\r\n *\r\n * The solver supports an optional pole vector to control the bending direction\r\n * of the middle joint (elbow/knee).\r\n *\r\n * @public\r\n */\r\nexport class TwoBoneIKSolver extends IKSolver {\r\n /** Optional pole vector position in world space */\r\n private _poleVector: Vector3 | null;\r\n /** Weight of the pole vector constraint (0-1) */\r\n private _poleWeight: number;\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 Two Bone IK solver.\r\n *\r\n * @param chain - The IK chain to solve (must have exactly 3 joints)\r\n * @param poleVector - Optional pole vector position in world space\r\n * @param poleWeight - Weight of the pole vector constraint (0-1, default: 1)\r\n */\r\n constructor(chain: IKChain, poleVector: Vector3 | null = null, poleWeight = 1) {\r\n super(chain, 1, 0.001); // Two bone IK doesn't need iterations\r\n\r\n if (chain.joints.length !== 3) {\r\n throw new Error('Two Bone IK requires exactly 3 joints (2 bones)');\r\n }\r\n\r\n this._poleVector = poleVector ? poleVector.clone() : null;\r\n this._poleWeight = Math.max(0, Math.min(1, poleWeight));\r\n this._twistConstraints = new Map();\r\n\r\n // Set default twist constraints\r\n // Root joint (shoulder/hip) - moderate twist\r\n this._twistConstraints.set(0, {\r\n minTwist: -Math.PI * 0.25, // -45 degrees\r\n maxTwist: Math.PI * 0.25, // +45 degrees\r\n smoothFactor: 0.3\r\n });\r\n\r\n // Middle joint (elbow/knee) - very limited twist\r\n this._twistConstraints.set(1, {\r\n minTwist: -Math.PI * 0.15, // -27 degrees\r\n maxTwist: Math.PI * 0.15, // +27 degrees\r\n smoothFactor: 0.3\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 (0 = root, 1 = middle)\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 * Get the pole vector position.\r\n */\r\n get poleVector(): Vector3 | null {\r\n return this._poleVector;\r\n }\r\n\r\n /**\r\n * Set the pole vector position.\r\n */\r\n set poleVector(value: Vector3 | null) {\r\n if (value) {\r\n if (!this._poleVector) {\r\n this._poleVector = value.clone();\r\n } else {\r\n this._poleVector.set(value);\r\n }\r\n } else {\r\n this._poleVector = null;\r\n }\r\n }\r\n\r\n /**\r\n * Get the pole vector weight.\r\n */\r\n get poleWeight(): number {\r\n return this._poleWeight;\r\n }\r\n\r\n /**\r\n * Set the pole vector weight (0-1).\r\n */\r\n set poleWeight(value: number) {\r\n this._poleWeight = Math.max(0, Math.min(1, value));\r\n }\r\n\r\n /**\r\n * Solve the IK chain to reach the target position using Two Bone IK algorithm.\r\n *\r\n * @param target - Target position for the end effector\r\n * @returns True if the target is reachable, false if stretched to maximum\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 const root = joints[0];\r\n const middle = joints[1];\r\n const end = joints[2];\r\n\r\n const rootPos = root.position;\r\n const upperLength = root.boneLength; // Length from root to middle\r\n const lowerLength = middle.boneLength; // Length from middle to end\r\n const totalLength = upperLength + lowerLength;\r\n\r\n // Calculate direction and distance from root to target\r\n const rootToTarget = Vector3.sub(target, rootPos, new Vector3());\r\n const targetDistance = rootToTarget.magnitude;\r\n\r\n // Check if target is reachable\r\n if (targetDistance < 0.000001) {\r\n // Target is at root position, keep original pose\r\n return true;\r\n }\r\n\r\n let reachable = true;\r\n\r\n // If target is unreachable, clamp to maximum distance\r\n let effectiveTarget = target;\r\n if (targetDistance >= totalLength - 0.0001) {\r\n // Stretch to maximum length\r\n const direction = Vector3.scale(rootToTarget, 1 / targetDistance, new Vector3());\r\n effectiveTarget = Vector3.add(\r\n rootPos,\r\n Vector3.scale(direction, totalLength - 0.0001, new Vector3()),\r\n new Vector3()\r\n );\r\n reachable = false;\r\n }\r\n\r\n // Calculate the distance from root to effective target\r\n const rootToEffectiveTarget = Vector3.sub(effectiveTarget, rootPos, new Vector3());\r\n const distance = rootToEffectiveTarget.magnitude;\r\n\r\n // Use law of cosines to find the angle at the root joint\r\n // cos(rootAngle) = (a² + c² - b²) / (2ac)\r\n const cosRootAngle =\r\n (upperLength * upperLength + distance * distance - lowerLength * lowerLength) /\r\n (2 * upperLength * distance);\r\n const clampedCosRootAngle = Math.max(-1, Math.min(1, cosRootAngle));\r\n const rootAngle = Math.acos(clampedCosRootAngle);\r\n\r\n // Determine the plane of bending\r\n let bendNormal: Vector3;\r\n\r\n if (this._poleVector && this._poleWeight > 0.001) {\r\n // Use pole vector to determine bend direction\r\n const rootToTargetDir = Vector3.normalize(rootToEffectiveTarget, new Vector3());\r\n const rootToPole = Vector3.sub(this._poleVector, rootPos, new Vector3());\r\n\r\n // Project pole vector onto plane perpendicular to root-target direction\r\n const projectionLength = Vector3.dot(rootToPole, rootToTargetDir);\r\n const projection = Vector3.scale(rootToTargetDir, projectionLength, new Vector3());\r\n const perpendicular = Vector3.sub(rootToPole, projection, new Vector3());\r\n\r\n const perpLength = perpendicular.magnitude;\r\n if (perpLength > 0.000001) {\r\n // Bend normal is perpendicular to both root-target and pole direction\r\n bendNormal = Vector3.cross(rootToTargetDir, perpendicular, new Vector3()).inplaceNormalize();\r\n } else {\r\n // Pole is on the line, use default bend direction\r\n bendNormal = this._getDefaultBendNormal(rootToEffectiveTarget);\r\n }\r\n\r\n // Apply pole weight\r\n if (this._poleWeight < 0.999) {\r\n const defaultNormal = this._getDefaultBendNormal(rootToEffectiveTarget);\r\n // Slerp between default and pole-based normal\r\n const angle = Math.acos(Math.max(-1, Math.min(1, Vector3.dot(defaultNormal, bendNormal))));\r\n if (angle > 0.001) {\r\n const axis = Vector3.cross(defaultNormal, bendNormal, new Vector3()).inplaceNormalize();\r\n const rotation = new Quaternion().fromAxisAngle(axis, angle * this._poleWeight);\r\n bendNormal = rotation.transform(defaultNormal, new Vector3());\r\n }\r\n }\r\n } else {\r\n // No pole vector, use default bend direction\r\n bendNormal = this._getDefaultBendNormal(rootToEffectiveTarget);\r\n }\r\n\r\n // Calculate middle joint position\r\n const rootToTargetDir = Vector3.normalize(rootToEffectiveTarget, new Vector3());\r\n\r\n // Rotate root-to-target direction by rootAngle around bendNormal\r\n const rotationToMiddle = new Quaternion().fromAxisAngle(bendNormal, rootAngle);\r\n const rootToMiddleDir = rotationToMiddle.transform(rootToTargetDir, new Vector3());\r\n\r\n // Place middle joint\r\n middle.position.set(\r\n Vector3.add(rootPos, Vector3.scale(rootToMiddleDir, upperLength, new Vector3()), new Vector3())\r\n );\r\n\r\n // Place end joint at target\r\n end.position.set(effectiveTarget);\r\n\r\n // Apply constraints after solving\r\n // Note: Constraints may modify joint positions, which could affect bone lengths\r\n // For Two Bone IK, we apply constraints and then restore bone lengths\r\n this._applyConstraints();\r\n\r\n return reachable;\r\n }\r\n\r\n /**\r\n * Apply all constraints to the joint chain.\r\n * After applying constraints, we need to restore bone lengths.\r\n */\r\n private _applyConstraints(): void {\r\n const constraints = this._chain.constraints;\r\n if (constraints.length === 0) {\r\n return;\r\n }\r\n\r\n const joints = this._chain.joints;\r\n\r\n // Apply each constraint\r\n for (const constraint of constraints) {\r\n constraint.apply(joints);\r\n }\r\n\r\n // After constraints are applied, we need to restore bone lengths\r\n // because constraints may have moved joints in ways that change bone lengths\r\n // For Two Bone IK, we fix this by adjusting positions while maintaining the constraint\r\n this._restoreBoneLengths();\r\n }\r\n\r\n /**\r\n * Restore bone lengths after constraints have been applied.\r\n * This ensures that the chain maintains correct bone lengths.\r\n */\r\n private _restoreBoneLengths(): void {\r\n const joints = this._chain.joints;\r\n const root = joints[0];\r\n const middle = joints[1];\r\n const end = joints[2];\r\n\r\n const upperLength = root.boneLength;\r\n const lowerLength = middle.boneLength;\r\n\r\n // Fix middle joint position to maintain upper bone length\r\n const rootToMiddle = Vector3.sub(middle.position, root.position, new Vector3());\r\n const rootToMiddleDist = rootToMiddle.magnitude;\r\n\r\n if (rootToMiddleDist > 0.000001 && Math.abs(rootToMiddleDist - upperLength) > 0.0001) {\r\n const rootToMiddleDir = Vector3.scale(rootToMiddle, 1 / rootToMiddleDist, new Vector3());\r\n middle.position.set(\r\n Vector3.add(root.position, Vector3.scale(rootToMiddleDir, upperLength, new Vector3()), new Vector3())\r\n );\r\n }\r\n\r\n // Fix end joint position to maintain lower bone length\r\n const middleToEnd = Vector3.sub(end.position, middle.position, new Vector3());\r\n const middleToEndDist = middleToEnd.magnitude;\r\n\r\n if (middleToEndDist > 0.000001 && Math.abs(middleToEndDist - lowerLength) > 0.0001) {\r\n const middleToEndDir = Vector3.scale(middleToEnd, 1 / middleToEndDist, new Vector3());\r\n end.position.set(\r\n Vector3.add(middle.position, Vector3.scale(middleToEndDir, lowerLength, new Vector3()), new Vector3())\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 root and middle joints (end joint doesn't need rotation)\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 // Decompose rotation around bone axis\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 /**\r\n * Get a default bend normal when no pole vector is specified.\r\n * This tries to find a reasonable perpendicular direction.\r\n *\r\n * @param rootToTarget - Direction from root to target\r\n * @returns A normalized perpendicular vector\r\n */\r\n private _getDefaultBendNormal(rootToTarget: Vector3): Vector3 {\r\n const rootToTargetDir = Vector3.normalize(rootToTarget, new Vector3());\r\n\r\n // Try to use world up (Y axis) as reference\r\n let bendNormal = Vector3.cross(rootToTargetDir, Vector3.axisPY(), new Vector3());\r\n const lenSq = bendNormal.x * bendNormal.x + bendNormal.y * bendNormal.y + bendNormal.z * bendNormal.z;\r\n\r\n // If root-to-target is parallel to Y axis, use X axis instead\r\n if (lenSq < 0.000001) {\r\n bendNormal = Vector3.cross(rootToTargetDir, Vector3.axisPX(), new Vector3());\r\n }\r\n\r\n return bendNormal.inplaceNormalize();\r\n }\r\n}\r\n"],"names":["TwoBoneIKSolver","IKSolver","chain","poleVector","poleWeight","joints","length","Error","_poleVector","clone","_poleWeight","Math","max","min","_twistConstraints","Map","set","minTwist","PI","maxTwist","smoothFactor","setTwistConstraint","jointIndex","_chain","getTwistConstraint","get","removeTwistConstraint","delete","clearTwistConstraints","clear","value","solve","target","updateFromNodes","storeOriginalPositions","root","middle","end","rootPos","position","upperLength","boneLength","lowerLength","totalLength","rootToTarget","Vector3","sub","targetDistance","magnitude","reachable","effectiveTarget","direction","scale","add","rootToEffectiveTarget","distance","cosRootAngle","clampedCosRootAngle","rootAngle","acos","bendNormal","rootToTargetDir","normalize","rootToPole","projectionLength","dot","projection","perpendicular","perpLength","cross","inplaceNormalize","_getDefaultBendNormal","defaultNormal","angle","axis","rotation","Quaternion","fromAxisAngle","transform","rotationToMiddle","rootToMiddleDir","_applyConstraints","constraints","constraint","apply","_restoreBoneLengths","rootToMiddle","rootToMiddleDist","abs","middleToEnd","middleToEndDist","middleToEndDir","applyToNodes","weight","i","joint","nextJoint","originalDir","originalPosition","newDir","originalDirNorm","newDirNorm","deltaRotation","IKUtils","fromToRotation","worldRotation","multiply","originalRotation","swing","twist","decomposeSwingTwist","twistAngle","getTwistAngle","clampAndSmoothTwist","previousTwist","clampedTwist","createTwist","slerp","previousIKRotation","node","parent","parentWorldRotation","worldMatrix","decompose","parentInvRotation","conjugate","localRotation","axisPY","lenSq","x","y","z","axisPX"],"mappings":"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"}
1
+ {"version":3,"file":"two_bone_ik_solver.js","sources":["../../../src/animation/ik/two_bone_ik_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 * Two Bone IK solver for chains with exactly 3 joints (2 bones).\r\n *\r\n * @remarks\r\n * This solver uses an analytical solution specifically optimized for\r\n * two-bone chains like arms (shoulder-elbow-wrist) or legs (hip-knee-ankle).\r\n * It's faster and more stable than iterative methods like FABRIK for this case.\r\n *\r\n * The solver supports an optional pole vector to control the bending direction\r\n * of the middle joint (elbow/knee).\r\n *\r\n * @public\r\n */\r\nexport class TwoBoneIKSolver extends IKSolver {\r\n /** Optional pole vector position in world space */\r\n private _poleVector: Vector3 | null;\r\n /** Weight of the pole vector constraint (0-1) */\r\n private _poleWeight: number;\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 Two Bone IK solver.\r\n *\r\n * @param chain - The IK chain to solve (must have exactly 3 joints)\r\n * @param poleVector - Optional pole vector position in world space\r\n * @param poleWeight - Weight of the pole vector constraint (0-1, default: 1)\r\n */\r\n constructor(chain: IKChain, poleVector: Vector3 | null = null, poleWeight = 1) {\r\n super(chain, 1, 0.001); // Two bone IK doesn't need iterations\r\n\r\n if (chain.joints.length !== 3) {\r\n throw new Error('Two Bone IK requires exactly 3 joints (2 bones)');\r\n }\r\n\r\n this._poleVector = poleVector ? poleVector.clone() : null;\r\n this._poleWeight = Math.max(0, Math.min(1, poleWeight));\r\n this._twistConstraints = new Map();\r\n\r\n // Set default twist constraints\r\n // Root joint (shoulder/hip) - moderate twist\r\n this._twistConstraints.set(0, {\r\n minTwist: -Math.PI * 0.25, // -45 degrees\r\n maxTwist: Math.PI * 0.25, // +45 degrees\r\n smoothFactor: 0.3\r\n });\r\n\r\n // Middle joint (elbow/knee) - very limited twist\r\n this._twistConstraints.set(1, {\r\n minTwist: -Math.PI * 0.15, // -27 degrees\r\n maxTwist: Math.PI * 0.15, // +27 degrees\r\n smoothFactor: 0.3\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 (0 = root, 1 = middle)\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 * Get the pole vector position.\r\n */\r\n get poleVector(): Vector3 | null {\r\n return this._poleVector;\r\n }\r\n\r\n /**\r\n * Set the pole vector position.\r\n */\r\n set poleVector(value: Vector3 | null) {\r\n if (value) {\r\n if (!this._poleVector) {\r\n this._poleVector = value.clone();\r\n } else {\r\n this._poleVector.set(value);\r\n }\r\n } else {\r\n this._poleVector = null;\r\n }\r\n }\r\n\r\n /**\r\n * Get the pole vector weight.\r\n */\r\n get poleWeight(): number {\r\n return this._poleWeight;\r\n }\r\n\r\n /**\r\n * Set the pole vector weight (0-1).\r\n */\r\n set poleWeight(value: number) {\r\n this._poleWeight = Math.max(0, Math.min(1, value));\r\n }\r\n\r\n /**\r\n * Solve the IK chain to reach the target position using Two Bone IK algorithm.\r\n *\r\n * @param target - Target position for the end effector\r\n * @returns True if the target is reachable, false if stretched to maximum\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 const root = joints[0];\r\n const middle = joints[1];\r\n const end = joints[2];\r\n\r\n const rootPos = root.position;\r\n const upperLength = root.boneLength; // Length from root to middle\r\n const lowerLength = middle.boneLength; // Length from middle to end\r\n const totalLength = upperLength + lowerLength;\r\n\r\n // Calculate direction and distance from root to target\r\n const rootToTarget = Vector3.sub(target, rootPos, new Vector3());\r\n const targetDistance = rootToTarget.magnitude;\r\n\r\n // Check if target is reachable\r\n if (targetDistance < 0.000001) {\r\n // Target is at root position, keep original pose\r\n return true;\r\n }\r\n\r\n let reachable = true;\r\n\r\n // If target is unreachable, clamp to maximum distance\r\n let effectiveTarget = target;\r\n if (targetDistance >= totalLength - 0.0001) {\r\n // Stretch to maximum length\r\n const direction = Vector3.scale(rootToTarget, 1 / targetDistance, new Vector3());\r\n effectiveTarget = Vector3.add(\r\n rootPos,\r\n Vector3.scale(direction, totalLength - 0.0001, new Vector3()),\r\n new Vector3()\r\n );\r\n reachable = false;\r\n }\r\n\r\n // Calculate the distance from root to effective target\r\n const rootToEffectiveTarget = Vector3.sub(effectiveTarget, rootPos, new Vector3());\r\n const distance = rootToEffectiveTarget.magnitude;\r\n\r\n // Use law of cosines to find the angle at the root joint\r\n // cos(rootAngle) = (a² + c² - b²) / (2ac)\r\n const cosRootAngle =\r\n (upperLength * upperLength + distance * distance - lowerLength * lowerLength) /\r\n (2 * upperLength * distance);\r\n const clampedCosRootAngle = Math.max(-1, Math.min(1, cosRootAngle));\r\n const rootAngle = Math.acos(clampedCosRootAngle);\r\n\r\n // Determine the plane of bending\r\n let bendNormal: Vector3;\r\n\r\n if (this._poleVector && this._poleWeight > 0.001) {\r\n // Use pole vector to determine bend direction\r\n const rootToTargetDir = Vector3.normalize(rootToEffectiveTarget, new Vector3());\r\n const rootToPole = Vector3.sub(this._poleVector, rootPos, new Vector3());\r\n\r\n // Project pole vector onto plane perpendicular to root-target direction\r\n const projectionLength = Vector3.dot(rootToPole, rootToTargetDir);\r\n const projection = Vector3.scale(rootToTargetDir, projectionLength, new Vector3());\r\n const perpendicular = Vector3.sub(rootToPole, projection, new Vector3());\r\n\r\n const perpLength = perpendicular.magnitude;\r\n if (perpLength > 0.000001) {\r\n // Bend normal is perpendicular to both root-target and pole direction\r\n bendNormal = Vector3.cross(rootToTargetDir, perpendicular, new Vector3()).inplaceNormalize();\r\n } else {\r\n // Pole is on the line, use default bend direction\r\n bendNormal = this._getDefaultBendNormal(rootToEffectiveTarget);\r\n }\r\n\r\n // Apply pole weight\r\n if (this._poleWeight < 0.999) {\r\n const defaultNormal = this._getDefaultBendNormal(rootToEffectiveTarget);\r\n // Slerp between default and pole-based normal\r\n const angle = Math.acos(Math.max(-1, Math.min(1, Vector3.dot(defaultNormal, bendNormal))));\r\n if (angle > 0.001) {\r\n const axis = Vector3.cross(defaultNormal, bendNormal, new Vector3()).inplaceNormalize();\r\n const rotation = new Quaternion().fromAxisAngle(axis, angle * this._poleWeight);\r\n bendNormal = rotation.transform(defaultNormal, new Vector3());\r\n }\r\n }\r\n } else {\r\n // No pole vector, use default bend direction\r\n bendNormal = this._getDefaultBendNormal(rootToEffectiveTarget);\r\n }\r\n\r\n // Calculate middle joint position\r\n const rootToTargetDir = Vector3.normalize(rootToEffectiveTarget, new Vector3());\r\n\r\n // Rotate root-to-target direction by rootAngle around bendNormal\r\n const rotationToMiddle = new Quaternion().fromAxisAngle(bendNormal, rootAngle);\r\n const rootToMiddleDir = rotationToMiddle.transform(rootToTargetDir, new Vector3());\r\n\r\n // Place middle joint\r\n middle.position.set(\r\n Vector3.add(rootPos, Vector3.scale(rootToMiddleDir, upperLength, new Vector3()), new Vector3())\r\n );\r\n\r\n // Place end joint at target\r\n end.position.set(effectiveTarget);\r\n\r\n // Apply constraints after solving\r\n // Note: Constraints may modify joint positions, which could affect bone lengths\r\n // For Two Bone IK, we apply constraints and then restore bone lengths\r\n this._applyConstraints();\r\n\r\n return reachable;\r\n }\r\n\r\n /**\r\n * Apply all constraints to the joint chain.\r\n * After applying constraints, we need to restore bone lengths.\r\n */\r\n private _applyConstraints(): void {\r\n const constraints = this._chain.constraints;\r\n if (constraints.length === 0) {\r\n return;\r\n }\r\n\r\n const joints = this._chain.joints;\r\n\r\n // Apply each constraint\r\n for (const constraint of constraints) {\r\n constraint.apply(joints);\r\n }\r\n\r\n // After constraints are applied, we need to restore bone lengths\r\n // because constraints may have moved joints in ways that change bone lengths\r\n // For Two Bone IK, we fix this by adjusting positions while maintaining the constraint\r\n this._restoreBoneLengths();\r\n }\r\n\r\n /**\r\n * Restore bone lengths after constraints have been applied.\r\n * This ensures that the chain maintains correct bone lengths.\r\n */\r\n private _restoreBoneLengths(): void {\r\n const joints = this._chain.joints;\r\n const root = joints[0];\r\n const middle = joints[1];\r\n const end = joints[2];\r\n\r\n const upperLength = root.boneLength;\r\n const lowerLength = middle.boneLength;\r\n\r\n // Fix middle joint position to maintain upper bone length\r\n const rootToMiddle = Vector3.sub(middle.position, root.position, new Vector3());\r\n const rootToMiddleDist = rootToMiddle.magnitude;\r\n\r\n if (rootToMiddleDist > 0.000001 && Math.abs(rootToMiddleDist - upperLength) > 0.0001) {\r\n const rootToMiddleDir = Vector3.scale(rootToMiddle, 1 / rootToMiddleDist, new Vector3());\r\n middle.position.set(\r\n Vector3.add(root.position, Vector3.scale(rootToMiddleDir, upperLength, new Vector3()), new Vector3())\r\n );\r\n }\r\n\r\n // Fix end joint position to maintain lower bone length\r\n const middleToEnd = Vector3.sub(end.position, middle.position, new Vector3());\r\n const middleToEndDist = middleToEnd.magnitude;\r\n\r\n if (middleToEndDist > 0.000001 && Math.abs(middleToEndDist - lowerLength) > 0.0001) {\r\n const middleToEndDir = Vector3.scale(middleToEnd, 1 / middleToEndDist, new Vector3());\r\n end.position.set(\r\n Vector3.add(middle.position, Vector3.scale(middleToEndDir, lowerLength, new Vector3()), new Vector3())\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 root and middle joints (end joint doesn't need rotation)\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 // Decompose rotation around bone axis\r\n const swing = new Quaternion();\r\n const twist = new Quaternion();\r\n worldRotation.decomposeSwingTwist(newDirNorm, swing, twist);\r\n\r\n // Get twist angle\r\n let twistAngle = twist.getTwistAngle(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 = Quaternion.fromAxisAngle(newDirNorm, twistAngle);\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 /**\r\n * Get a default bend normal when no pole vector is specified.\r\n * This tries to find a reasonable perpendicular direction.\r\n *\r\n * @param rootToTarget - Direction from root to target\r\n * @returns A normalized perpendicular vector\r\n */\r\n private _getDefaultBendNormal(rootToTarget: Vector3): Vector3 {\r\n const rootToTargetDir = Vector3.normalize(rootToTarget, new Vector3());\r\n\r\n // Try to use world up (Y axis) as reference\r\n let bendNormal = Vector3.cross(rootToTargetDir, Vector3.axisPY(), new Vector3());\r\n const lenSq = bendNormal.x * bendNormal.x + bendNormal.y * bendNormal.y + bendNormal.z * bendNormal.z;\r\n\r\n // If root-to-target is parallel to Y axis, use X axis instead\r\n if (lenSq < 0.000001) {\r\n bendNormal = Vector3.cross(rootToTargetDir, Vector3.axisPX(), new Vector3());\r\n }\r\n\r\n return bendNormal.inplaceNormalize();\r\n }\r\n}\r\n"],"names":["TwoBoneIKSolver","IKSolver","chain","poleVector","poleWeight","joints","length","Error","_poleVector","clone","_poleWeight","Math","max","min","_twistConstraints","Map","set","minTwist","PI","maxTwist","smoothFactor","setTwistConstraint","jointIndex","_chain","getTwistConstraint","get","removeTwistConstraint","delete","clearTwistConstraints","clear","value","solve","target","updateFromNodes","storeOriginalPositions","root","middle","end","rootPos","position","upperLength","boneLength","lowerLength","totalLength","rootToTarget","Vector3","sub","targetDistance","magnitude","reachable","effectiveTarget","direction","scale","add","rootToEffectiveTarget","distance","cosRootAngle","clampedCosRootAngle","rootAngle","acos","bendNormal","rootToTargetDir","normalize","rootToPole","projectionLength","dot","projection","perpendicular","perpLength","cross","inplaceNormalize","_getDefaultBendNormal","defaultNormal","angle","axis","rotation","Quaternion","fromAxisAngle","transform","rotationToMiddle","rootToMiddleDir","_applyConstraints","constraints","constraint","apply","_restoreBoneLengths","rootToMiddle","rootToMiddleDist","abs","middleToEnd","middleToEndDist","middleToEndDir","applyToNodes","weight","i","joint","nextJoint","originalDir","originalPosition","newDir","originalDirNorm","newDirNorm","deltaRotation","IKUtils","fromToRotation","worldRotation","multiply","originalRotation","swing","twist","decomposeSwingTwist","twistAngle","getTwistAngle","clampAndSmoothTwist","previousTwist","clampedTwist","slerp","previousIKRotation","node","parent","parentWorldRotation","worldMatrix","decompose","parentInvRotation","conjugate","localRotation","axisPY","lenSq","x","y","z","axisPX"],"mappings":"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"}