@zephyr3d/scene 0.7.1 → 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 (441) hide show
  1. package/dist/animation/animation.js +0 -18
  2. package/dist/animation/animation.js.map +1 -1
  3. package/dist/animation/animationset.js +200 -3
  4. package/dist/animation/animationset.js.map +1 -1
  5. package/dist/animation/ik/ccd_solver.js +371 -0
  6. package/dist/animation/ik/ccd_solver.js.map +1 -0
  7. package/dist/animation/ik/fabrik_solver.js +398 -0
  8. package/dist/animation/ik/fabrik_solver.js.map +1 -0
  9. package/dist/animation/ik/ik_angle_constraint.js +181 -0
  10. package/dist/animation/ik/ik_angle_constraint.js.map +1 -0
  11. package/dist/animation/ik/ik_chain.js +163 -0
  12. package/dist/animation/ik/ik_chain.js.map +1 -0
  13. package/dist/animation/ik/ik_constraint.js +25 -0
  14. package/dist/animation/ik/ik_constraint.js.map +1 -0
  15. package/dist/animation/ik/ik_pole_constraint.js +128 -0
  16. package/dist/animation/ik/ik_pole_constraint.js.map +1 -0
  17. package/dist/animation/ik/ik_solver.js +48 -0
  18. package/dist/animation/ik/ik_solver.js.map +1 -0
  19. package/dist/animation/ik/ik_track.js +96 -0
  20. package/dist/animation/ik/ik_track.js.map +1 -0
  21. package/dist/animation/ik/ik_utils.js +191 -0
  22. package/dist/animation/ik/ik_utils.js.map +1 -0
  23. package/dist/animation/ik/two_bone_ik_solver.js +331 -0
  24. package/dist/animation/ik/two_bone_ik_solver.js.map +1 -0
  25. package/dist/animation/ik_modifier.js +61 -0
  26. package/dist/animation/ik_modifier.js.map +1 -0
  27. package/dist/animation/ik_postprocessor.js +71 -0
  28. package/dist/animation/ik_postprocessor.js.map +1 -0
  29. package/dist/animation/manual_transform_processor.js +156 -0
  30. package/dist/animation/manual_transform_processor.js.map +1 -0
  31. package/dist/animation/skeleton.js +55 -51
  32. package/dist/animation/skeleton.js.map +1 -1
  33. package/dist/animation/skeleton_modifier.js +38 -0
  34. package/dist/animation/skeleton_modifier.js.map +1 -0
  35. package/dist/animation/skeleton_postprocessor.js +50 -0
  36. package/dist/animation/skeleton_postprocessor.js.map +1 -0
  37. package/dist/animation/spring/multi_chain_spring_system.js +503 -0
  38. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -0
  39. package/dist/animation/spring/spring_bone.js +240 -0
  40. package/dist/animation/spring/spring_bone.js.map +1 -0
  41. package/dist/animation/spring/spring_bone_collider.js +198 -0
  42. package/dist/animation/spring/spring_bone_collider.js.map +1 -0
  43. package/dist/animation/spring/spring_bone_constraint.js +170 -0
  44. package/dist/animation/spring/spring_bone_constraint.js.map +1 -0
  45. package/dist/animation/spring/spring_bone_system.js +328 -0
  46. package/dist/animation/spring/spring_bone_system.js.map +1 -0
  47. package/dist/animation/spring/spring_chain.js +103 -0
  48. package/dist/animation/spring/spring_chain.js.map +1 -0
  49. package/dist/animation/spring/spring_collider.js +247 -0
  50. package/dist/animation/spring/spring_collider.js.map +1 -0
  51. package/dist/animation/spring/spring_constraint.js +21 -0
  52. package/dist/animation/spring/spring_constraint.js.map +1 -0
  53. package/dist/animation/spring/spring_particle.js +20 -0
  54. package/dist/animation/spring/spring_particle.js.map +1 -0
  55. package/dist/animation/spring/spring_system.js +526 -0
  56. package/dist/animation/spring/spring_system.js.map +1 -0
  57. package/dist/animation/spring_modifier.js +45 -0
  58. package/dist/animation/spring_modifier.js.map +1 -0
  59. package/dist/animation/spring_postprocessor.js +54 -0
  60. package/dist/animation/spring_postprocessor.js.map +1 -0
  61. package/dist/app/screen.js +1 -1
  62. package/dist/app/screen.js.map +1 -1
  63. package/dist/asset/model.js +10 -6
  64. package/dist/asset/model.js.map +1 -1
  65. package/dist/camera/perspectivecamera.js +3 -3
  66. package/dist/camera/perspectivecamera.js.map +1 -1
  67. package/dist/index.d.ts +1400 -4
  68. package/dist/index.js +16 -0
  69. package/dist/index.js.map +1 -1
  70. package/dist/material/mixins/lightmodel/blinnphong.js +66 -4
  71. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  72. package/dist/material/mixins/pbr/common.js +20 -17
  73. package/dist/material/mixins/pbr/common.js.map +1 -1
  74. package/dist/material/shader/helper.js +5 -3
  75. package/dist/material/shader/helper.js.map +1 -1
  76. package/dist/render/gpu_picking.js +100 -0
  77. package/dist/render/gpu_picking.js.map +1 -0
  78. package/dist/render/rendergraph/device_pool_allocator.js +41 -0
  79. package/dist/render/rendergraph/device_pool_allocator.js.map +1 -0
  80. package/dist/render/rendergraph/executor.js +146 -0
  81. package/dist/render/rendergraph/executor.js.map +1 -0
  82. package/dist/render/rendergraph/forward_plus_builder.js +414 -0
  83. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -0
  84. package/dist/render/rendergraph/rendergraph.js +306 -0
  85. package/dist/render/rendergraph/rendergraph.js.map +1 -0
  86. package/dist/render/rendergraph/types.js +57 -0
  87. package/dist/render/rendergraph/types.js.map +1 -0
  88. package/dist/render/sky_motion_vector.js +85 -0
  89. package/dist/render/sky_motion_vector.js.map +1 -0
  90. package/dist/scene/mesh.js +15 -23
  91. package/dist/scene/mesh.js.map +1 -1
  92. package/dist/utility/serialization/scene/animation.js +24 -23
  93. package/dist/utility/serialization/scene/animation.js.map +1 -1
  94. package/dist/utility/serialization/scene/material.js +62 -0
  95. package/dist/utility/serialization/scene/material.js.map +1 -1
  96. package/dist/utility/serialization/scene/node.js +1 -1
  97. package/package.json +3 -3
  98. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/runtimemgr.js +0 -38
  99. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/runtimemgr.js.map +0 -1
  100. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/runtimescript.js +0 -10
  101. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/runtimescript.js.map +0 -1
  102. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/scriptingsystem.js +0 -127
  103. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/scriptingsystem.js.map +0 -1
  104. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/scriptregistry.js +0 -263
  105. package/dist/node_modules/@zephyr3d/runtime/dist/runtime/scriptregistry.js.map +0 -1
  106. package/dist/src/animation/animation.js +0 -127
  107. package/dist/src/animation/animation.js.map +0 -1
  108. package/dist/src/animation/animationset.js +0 -255
  109. package/dist/src/animation/animationset.js.map +0 -1
  110. package/dist/src/animation/animationtrack.js +0 -34
  111. package/dist/src/animation/animationtrack.js.map +0 -1
  112. package/dist/src/animation/eulerrotationtrack.js +0 -52
  113. package/dist/src/animation/eulerrotationtrack.js.map +0 -1
  114. package/dist/src/animation/morphtarget.js +0 -93
  115. package/dist/src/animation/morphtarget.js.map +0 -1
  116. package/dist/src/animation/morphtrack.js +0 -70
  117. package/dist/src/animation/morphtrack.js.map +0 -1
  118. package/dist/src/animation/proptrack.js +0 -161
  119. package/dist/src/animation/proptrack.js.map +0 -1
  120. package/dist/src/animation/rotationtrack.js +0 -51
  121. package/dist/src/animation/rotationtrack.js.map +0 -1
  122. package/dist/src/animation/scaletrack.js +0 -50
  123. package/dist/src/animation/scaletrack.js.map +0 -1
  124. package/dist/src/animation/skeleton.js +0 -204
  125. package/dist/src/animation/skeleton.js.map +0 -1
  126. package/dist/src/animation/translationtrack.js +0 -50
  127. package/dist/src/animation/translationtrack.js.map +0 -1
  128. package/dist/src/app/app.js +0 -129
  129. package/dist/src/app/app.js.map +0 -1
  130. package/dist/src/app/inputmgr.js +0 -267
  131. package/dist/src/app/inputmgr.js.map +0 -1
  132. package/dist/src/asset/assetmanager.js +0 -404
  133. package/dist/src/asset/assetmanager.js.map +0 -1
  134. package/dist/src/asset/builtin.js +0 -337
  135. package/dist/src/asset/builtin.js.map +0 -1
  136. package/dist/src/asset/loaders/dds/dds.js +0 -470
  137. package/dist/src/asset/loaders/dds/dds.js.map +0 -1
  138. package/dist/src/asset/loaders/dds/dds_loader.js +0 -28
  139. package/dist/src/asset/loaders/dds/dds_loader.js.map +0 -1
  140. package/dist/src/asset/loaders/gltf/gltf_loader.js +0 -1265
  141. package/dist/src/asset/loaders/gltf/gltf_loader.js.map +0 -1
  142. package/dist/src/asset/loaders/gltf/helpers.js +0 -327
  143. package/dist/src/asset/loaders/gltf/helpers.js.map +0 -1
  144. package/dist/src/asset/loaders/hdr/hdr.js +0 -180
  145. package/dist/src/asset/loaders/hdr/hdr.js.map +0 -1
  146. package/dist/src/asset/loaders/image/tga_Loader.js +0 -116
  147. package/dist/src/asset/loaders/image/tga_Loader.js.map +0 -1
  148. package/dist/src/asset/loaders/image/webimage_loader.js +0 -63
  149. package/dist/src/asset/loaders/image/webimage_loader.js.map +0 -1
  150. package/dist/src/asset/loaders/loader.js +0 -45
  151. package/dist/src/asset/loaders/loader.js.map +0 -1
  152. package/dist/src/asset/model.js +0 -414
  153. package/dist/src/asset/model.js.map +0 -1
  154. package/dist/src/blitter/bilateralblur.js +0 -221
  155. package/dist/src/blitter/bilateralblur.js.map +0 -1
  156. package/dist/src/blitter/blitter.js +0 -390
  157. package/dist/src/blitter/blitter.js.map +0 -1
  158. package/dist/src/blitter/box.js +0 -118
  159. package/dist/src/blitter/box.js.map +0 -1
  160. package/dist/src/blitter/copy.js +0 -22
  161. package/dist/src/blitter/copy.js.map +0 -1
  162. package/dist/src/blitter/gaussianblur.js +0 -228
  163. package/dist/src/blitter/gaussianblur.js.map +0 -1
  164. package/dist/src/camera/base.js +0 -92
  165. package/dist/src/camera/base.js.map +0 -1
  166. package/dist/src/camera/camera.js +0 -1005
  167. package/dist/src/camera/camera.js.map +0 -1
  168. package/dist/src/camera/fps.js +0 -238
  169. package/dist/src/camera/fps.js.map +0 -1
  170. package/dist/src/camera/orbit.js +0 -245
  171. package/dist/src/camera/orbit.js.map +0 -1
  172. package/dist/src/camera/orthocamera.js +0 -167
  173. package/dist/src/camera/orthocamera.js.map +0 -1
  174. package/dist/src/camera/perspectivecamera.js +0 -141
  175. package/dist/src/camera/perspectivecamera.js.map +0 -1
  176. package/dist/src/index.js +0 -120
  177. package/dist/src/index.js.map +0 -1
  178. package/dist/src/material/blinn.js +0 -81
  179. package/dist/src/material/blinn.js.map +0 -1
  180. package/dist/src/material/grassmaterial.js +0 -113
  181. package/dist/src/material/grassmaterial.js.map +0 -1
  182. package/dist/src/material/lambert.js +0 -92
  183. package/dist/src/material/lambert.js.map +0 -1
  184. package/dist/src/material/material.js +0 -301
  185. package/dist/src/material/material.js.map +0 -1
  186. package/dist/src/material/meshmaterial.js +0 -704
  187. package/dist/src/material/meshmaterial.js.map +0 -1
  188. package/dist/src/material/mixins/albedocolor.js +0 -76
  189. package/dist/src/material/mixins/albedocolor.js.map +0 -1
  190. package/dist/src/material/mixins/foliage.js +0 -47
  191. package/dist/src/material/mixins/foliage.js.map +0 -1
  192. package/dist/src/material/mixins/lightmodel/blinnphong.js +0 -112
  193. package/dist/src/material/mixins/lightmodel/blinnphong.js.map +0 -1
  194. package/dist/src/material/mixins/lightmodel/lambert.js +0 -58
  195. package/dist/src/material/mixins/lightmodel/lambert.js.map +0 -1
  196. package/dist/src/material/mixins/lightmodel/pbrmetallicroughness.js +0 -178
  197. package/dist/src/material/mixins/lightmodel/pbrmetallicroughness.js.map +0 -1
  198. package/dist/src/material/mixins/lightmodel/pbrspecularglossness.js +0 -139
  199. package/dist/src/material/mixins/lightmodel/pbrspecularglossness.js.map +0 -1
  200. package/dist/src/material/mixins/lit.js +0 -476
  201. package/dist/src/material/mixins/lit.js.map +0 -1
  202. package/dist/src/material/mixins/pbr/common.js +0 -918
  203. package/dist/src/material/mixins/pbr/common.js.map +0 -1
  204. package/dist/src/material/mixins/texture.js +0 -172
  205. package/dist/src/material/mixins/texture.js.map +0 -1
  206. package/dist/src/material/mixins/vertexcolor.js +0 -56
  207. package/dist/src/material/mixins/vertexcolor.js.map +0 -1
  208. package/dist/src/material/particle.js +0 -178
  209. package/dist/src/material/particle.js.map +0 -1
  210. package/dist/src/material/pbrmr.js +0 -97
  211. package/dist/src/material/pbrmr.js.map +0 -1
  212. package/dist/src/material/pbrsg.js +0 -97
  213. package/dist/src/material/pbrsg.js.map +0 -1
  214. package/dist/src/material/shader/helper.js +0 -1209
  215. package/dist/src/material/shader/helper.js.map +0 -1
  216. package/dist/src/material/terrain-cm.js +0 -606
  217. package/dist/src/material/terrain-cm.js.map +0 -1
  218. package/dist/src/material/terrainmaterial.js +0 -375
  219. package/dist/src/material/terrainmaterial.js.map +0 -1
  220. package/dist/src/material/unlit.js +0 -41
  221. package/dist/src/material/unlit.js.map +0 -1
  222. package/dist/src/material/water.js +0 -417
  223. package/dist/src/material/water.js.map +0 -1
  224. package/dist/src/posteffect/bloom.js +0 -361
  225. package/dist/src/posteffect/bloom.js.map +0 -1
  226. package/dist/src/posteffect/compositor.js +0 -226
  227. package/dist/src/posteffect/compositor.js.map +0 -1
  228. package/dist/src/posteffect/fxaa.js +0 -273
  229. package/dist/src/posteffect/fxaa.js.map +0 -1
  230. package/dist/src/posteffect/grayscale.js +0 -69
  231. package/dist/src/posteffect/grayscale.js.map +0 -1
  232. package/dist/src/posteffect/motionblur.js +0 -96
  233. package/dist/src/posteffect/motionblur.js.map +0 -1
  234. package/dist/src/posteffect/posteffect.js +0 -126
  235. package/dist/src/posteffect/posteffect.js.map +0 -1
  236. package/dist/src/posteffect/sao.js +0 -324
  237. package/dist/src/posteffect/sao.js.map +0 -1
  238. package/dist/src/posteffect/ssr.js +0 -489
  239. package/dist/src/posteffect/ssr.js.map +0 -1
  240. package/dist/src/posteffect/taa.js +0 -172
  241. package/dist/src/posteffect/taa.js.map +0 -1
  242. package/dist/src/posteffect/tonemap.js +0 -94
  243. package/dist/src/posteffect/tonemap.js.map +0 -1
  244. package/dist/src/render/abuffer_oit.js +0 -361
  245. package/dist/src/render/abuffer_oit.js.map +0 -1
  246. package/dist/src/render/clipmap.js +0 -851
  247. package/dist/src/render/clipmap.js.map +0 -1
  248. package/dist/src/render/cluster_light.js +0 -333
  249. package/dist/src/render/cluster_light.js.map +0 -1
  250. package/dist/src/render/cull_visitor.js +0 -187
  251. package/dist/src/render/cull_visitor.js.map +0 -1
  252. package/dist/src/render/depthpass.js +0 -68
  253. package/dist/src/render/depthpass.js.map +0 -1
  254. package/dist/src/render/drawable_mixin.js +0 -227
  255. package/dist/src/render/drawable_mixin.js.map +0 -1
  256. package/dist/src/render/envlight.js +0 -463
  257. package/dist/src/render/envlight.js.map +0 -1
  258. package/dist/src/render/fbm_wavegenerator.js +0 -251
  259. package/dist/src/render/fbm_wavegenerator.js.map +0 -1
  260. package/dist/src/render/fft_wavegenerator.js +0 -1006
  261. package/dist/src/render/fft_wavegenerator.js.map +0 -1
  262. package/dist/src/render/fullscreenquad.js +0 -38
  263. package/dist/src/render/fullscreenquad.js.map +0 -1
  264. package/dist/src/render/gerstner_wavegenerator.js +0 -314
  265. package/dist/src/render/gerstner_wavegenerator.js.map +0 -1
  266. package/dist/src/render/globalbindgroup_allocator.js +0 -60
  267. package/dist/src/render/globalbindgroup_allocator.js.map +0 -1
  268. package/dist/src/render/hzb.js +0 -273
  269. package/dist/src/render/hzb.js.map +0 -1
  270. package/dist/src/render/lightpass.js +0 -172
  271. package/dist/src/render/lightpass.js.map +0 -1
  272. package/dist/src/render/objectcolorpass.js +0 -51
  273. package/dist/src/render/objectcolorpass.js.map +0 -1
  274. package/dist/src/render/primitive.js +0 -364
  275. package/dist/src/render/primitive.js.map +0 -1
  276. package/dist/src/render/render_queue.js +0 -467
  277. package/dist/src/render/render_queue.js.map +0 -1
  278. package/dist/src/render/renderbundle_wrapper.js +0 -152
  279. package/dist/src/render/renderbundle_wrapper.js.map +0 -1
  280. package/dist/src/render/renderer.js +0 -455
  281. package/dist/src/render/renderer.js.map +0 -1
  282. package/dist/src/render/renderpass.js +0 -200
  283. package/dist/src/render/renderpass.js.map +0 -1
  284. package/dist/src/render/shadowmap_pass.js +0 -56
  285. package/dist/src/render/shadowmap_pass.js.map +0 -1
  286. package/dist/src/render/sky.js +0 -1103
  287. package/dist/src/render/sky.js.map +0 -1
  288. package/dist/src/render/weightedblended_oit.js +0 -168
  289. package/dist/src/render/weightedblended_oit.js.map +0 -1
  290. package/dist/src/scene/batchgroup.js +0 -162
  291. package/dist/src/scene/batchgroup.js.map +0 -1
  292. package/dist/src/scene/environment.js +0 -209
  293. package/dist/src/scene/environment.js.map +0 -1
  294. package/dist/src/scene/graph_node.js +0 -72
  295. package/dist/src/scene/graph_node.js.map +0 -1
  296. package/dist/src/scene/light.js +0 -416
  297. package/dist/src/scene/light.js.map +0 -1
  298. package/dist/src/scene/mesh.js +0 -341
  299. package/dist/src/scene/mesh.js.map +0 -1
  300. package/dist/src/scene/octree.js +0 -649
  301. package/dist/src/scene/octree.js.map +0 -1
  302. package/dist/src/scene/particlesys.js +0 -738
  303. package/dist/src/scene/particlesys.js.map +0 -1
  304. package/dist/src/scene/raycast_visitor.js +0 -103
  305. package/dist/src/scene/raycast_visitor.js.map +0 -1
  306. package/dist/src/scene/scene.js +0 -284
  307. package/dist/src/scene/scene.js.map +0 -1
  308. package/dist/src/scene/scene_node.js +0 -732
  309. package/dist/src/scene/scene_node.js.map +0 -1
  310. package/dist/src/scene/terrain/grass.js +0 -278
  311. package/dist/src/scene/terrain/grass.js.map +0 -1
  312. package/dist/src/scene/terrain/heightfield.js +0 -475
  313. package/dist/src/scene/terrain/heightfield.js.map +0 -1
  314. package/dist/src/scene/terrain/patch.js +0 -530
  315. package/dist/src/scene/terrain/patch.js.map +0 -1
  316. package/dist/src/scene/terrain/quadtree.js +0 -461
  317. package/dist/src/scene/terrain/quadtree.js.map +0 -1
  318. package/dist/src/scene/terrain/terrain.js +0 -246
  319. package/dist/src/scene/terrain/terrain.js.map +0 -1
  320. package/dist/src/scene/terrain-cm/grass.js +0 -594
  321. package/dist/src/scene/terrain-cm/grass.js.map +0 -1
  322. package/dist/src/scene/terrain-cm/grassmaterial.js +0 -159
  323. package/dist/src/scene/terrain-cm/grassmaterial.js.map +0 -1
  324. package/dist/src/scene/terrain-cm/terrain-cm.js +0 -538
  325. package/dist/src/scene/terrain-cm/terrain-cm.js.map +0 -1
  326. package/dist/src/scene/water.js +0 -374
  327. package/dist/src/scene/water.js.map +0 -1
  328. package/dist/src/shaders/atmosphere.js +0 -957
  329. package/dist/src/shaders/atmosphere.js.map +0 -1
  330. package/dist/src/shaders/fog.js +0 -112
  331. package/dist/src/shaders/fog.js.map +0 -1
  332. package/dist/src/shaders/misc.js +0 -266
  333. package/dist/src/shaders/misc.js.map +0 -1
  334. package/dist/src/shaders/noise.js +0 -222
  335. package/dist/src/shaders/noise.js.map +0 -1
  336. package/dist/src/shaders/pbr.js +0 -51
  337. package/dist/src/shaders/pbr.js.map +0 -1
  338. package/dist/src/shaders/shadow.js +0 -636
  339. package/dist/src/shaders/shadow.js.map +0 -1
  340. package/dist/src/shaders/ssr.js +0 -490
  341. package/dist/src/shaders/ssr.js.map +0 -1
  342. package/dist/src/shaders/temporal.js +0 -215
  343. package/dist/src/shaders/temporal.js.map +0 -1
  344. package/dist/src/shaders/water.js +0 -756
  345. package/dist/src/shaders/water.js.map +0 -1
  346. package/dist/src/shadow/esm.js +0 -237
  347. package/dist/src/shadow/esm.js.map +0 -1
  348. package/dist/src/shadow/pcf_opt.js +0 -181
  349. package/dist/src/shadow/pcf_opt.js.map +0 -1
  350. package/dist/src/shadow/pcf_pd.js +0 -189
  351. package/dist/src/shadow/pcf_pd.js.map +0 -1
  352. package/dist/src/shadow/shader.js +0 -37
  353. package/dist/src/shadow/shader.js.map +0 -1
  354. package/dist/src/shadow/shadow_impl.js +0 -15
  355. package/dist/src/shadow/shadow_impl.js.map +0 -1
  356. package/dist/src/shadow/shadowmapper.js +0 -790
  357. package/dist/src/shadow/shadowmapper.js.map +0 -1
  358. package/dist/src/shadow/ssm.js +0 -159
  359. package/dist/src/shadow/ssm.js.map +0 -1
  360. package/dist/src/shadow/vsm.js +0 -297
  361. package/dist/src/shadow/vsm.js.map +0 -1
  362. package/dist/src/shapes/box.js +0 -386
  363. package/dist/src/shapes/box.js.map +0 -1
  364. package/dist/src/shapes/cylinder.js +0 -125
  365. package/dist/src/shapes/cylinder.js.map +0 -1
  366. package/dist/src/shapes/plane.js +0 -88
  367. package/dist/src/shapes/plane.js.map +0 -1
  368. package/dist/src/shapes/shape.js +0 -87
  369. package/dist/src/shapes/shape.js.map +0 -1
  370. package/dist/src/shapes/sphere.js +0 -114
  371. package/dist/src/shapes/sphere.js.map +0 -1
  372. package/dist/src/shapes/tetrahedron.js +0 -188
  373. package/dist/src/shapes/tetrahedron.js.map +0 -1
  374. package/dist/src/shapes/torus.js +0 -111
  375. package/dist/src/shapes/torus.js.map +0 -1
  376. package/dist/src/utility/aabbtree.js +0 -400
  377. package/dist/src/utility/aabbtree.js.map +0 -1
  378. package/dist/src/utility/bounding_volume.js +0 -29
  379. package/dist/src/utility/bounding_volume.js.map +0 -1
  380. package/dist/src/utility/debug.js +0 -28
  381. package/dist/src/utility/debug.js.map +0 -1
  382. package/dist/src/utility/draco/decoder.js +0 -116
  383. package/dist/src/utility/draco/decoder.js.map +0 -1
  384. package/dist/src/utility/misc.js +0 -105
  385. package/dist/src/utility/misc.js.map +0 -1
  386. package/dist/src/utility/panorama.js +0 -163
  387. package/dist/src/utility/panorama.js.map +0 -1
  388. package/dist/src/utility/pmrem.js +0 -354
  389. package/dist/src/utility/pmrem.js.map +0 -1
  390. package/dist/src/utility/rendermipmap.js +0 -115
  391. package/dist/src/utility/rendermipmap.js.map +0 -1
  392. package/dist/src/utility/serialization/json.js +0 -402
  393. package/dist/src/utility/serialization/json.js.map +0 -1
  394. package/dist/src/utility/serialization/manager.js +0 -623
  395. package/dist/src/utility/serialization/manager.js.map +0 -1
  396. package/dist/src/utility/serialization/scene/animation.js +0 -248
  397. package/dist/src/utility/serialization/scene/animation.js.map +0 -1
  398. package/dist/src/utility/serialization/scene/batch.js +0 -59
  399. package/dist/src/utility/serialization/scene/batch.js.map +0 -1
  400. package/dist/src/utility/serialization/scene/camera.js +0 -790
  401. package/dist/src/utility/serialization/scene/camera.js.map +0 -1
  402. package/dist/src/utility/serialization/scene/common.js +0 -222
  403. package/dist/src/utility/serialization/scene/common.js.map +0 -1
  404. package/dist/src/utility/serialization/scene/light.js +0 -575
  405. package/dist/src/utility/serialization/scene/light.js.map +0 -1
  406. package/dist/src/utility/serialization/scene/material.js +0 -1111
  407. package/dist/src/utility/serialization/scene/material.js.map +0 -1
  408. package/dist/src/utility/serialization/scene/mesh.js +0 -148
  409. package/dist/src/utility/serialization/scene/mesh.js.map +0 -1
  410. package/dist/src/utility/serialization/scene/misc.js +0 -39
  411. package/dist/src/utility/serialization/scene/misc.js.map +0 -1
  412. package/dist/src/utility/serialization/scene/node.js +0 -451
  413. package/dist/src/utility/serialization/scene/node.js.map +0 -1
  414. package/dist/src/utility/serialization/scene/particle.js +0 -425
  415. package/dist/src/utility/serialization/scene/particle.js.map +0 -1
  416. package/dist/src/utility/serialization/scene/primitive.js +0 -692
  417. package/dist/src/utility/serialization/scene/primitive.js.map +0 -1
  418. package/dist/src/utility/serialization/scene/scene.js +0 -704
  419. package/dist/src/utility/serialization/scene/scene.js.map +0 -1
  420. package/dist/src/utility/serialization/scene/terrain.js +0 -488
  421. package/dist/src/utility/serialization/scene/terrain.js.map +0 -1
  422. package/dist/src/utility/serialization/scene/water.js +0 -465
  423. package/dist/src/utility/serialization/scene/water.js.map +0 -1
  424. package/dist/src/utility/shprojector.js +0 -297
  425. package/dist/src/utility/shprojector.js.map +0 -1
  426. package/dist/src/utility/textures/ggxlut.js +0 -213
  427. package/dist/src/utility/textures/ggxlut.js.map +0 -1
  428. package/dist/src/utility/textures/gradientnoise.js +0 -62
  429. package/dist/src/utility/textures/gradientnoise.js.map +0 -1
  430. package/dist/src/utility/textures/randomnoise.js +0 -41
  431. package/dist/src/utility/textures/randomnoise.js.map +0 -1
  432. package/dist/src/values.js +0 -162
  433. package/dist/src/values.js.map +0 -1
  434. package/dist/utility/blueprint/material/common.js +0 -7
  435. package/dist/utility/blueprint/material/common.js.map +0 -1
  436. package/dist/utility/serialization/blueprint/constants.js +0 -255
  437. package/dist/utility/serialization/blueprint/constants.js.map +0 -1
  438. package/dist/utility/serialization/blueprint/material/constants.js +0 -203
  439. package/dist/utility/serialization/blueprint/material/constants.js.map +0 -1
  440. package/dist/utility/serialization/blueprint/material/texture.js +0 -165
  441. package/dist/utility/serialization/blueprint/material/texture.js.map +0 -1
@@ -0,0 +1,398 @@
1
+ import { Vector3, Quaternion } from '@zephyr3d/base';
2
+ import { IKSolver } from './ik_solver.js';
3
+ import { IKUtils } from './ik_utils.js';
4
+
5
+ /**
6
+ * FABRIK (Forward And Backward Reaching Inverse Kinematics) solver.
7
+ *
8
+ * @remarks
9
+ * FABRIK is an iterative IK algorithm that alternates between:
10
+ * 1. Forward pass: Move from end effector to root, pulling joints toward target
11
+ * 2. Backward pass: Move from root to end effector, restoring root position
12
+ *
13
+ * Supports multiple pole vectors to control the bending direction of different joints.
14
+ *
15
+ * @public
16
+ */ class FABRIKSolver extends IKSolver {
17
+ /** Map of joint index to pole vector configuration */ _poleVectors;
18
+ /** Twist constraints for each joint (indexed by joint index) */ _twistConstraints;
19
+ /**
20
+ * Create a FABRIK solver.
21
+ *
22
+ * @param chain - The IK chain to solve
23
+ * @param maxIterations - Maximum number of iterations (default: 15)
24
+ * @param tolerance - Convergence tolerance in world units (default: 0.001)
25
+ */ constructor(chain, maxIterations = 15, tolerance = 0.001){
26
+ super(chain, maxIterations, tolerance);
27
+ this._poleVectors = new Map();
28
+ this._twistConstraints = new Map();
29
+ // Set default twist constraints for all joints
30
+ for(let i = 0; i < chain.joints.length - 1; i++){
31
+ // Middle joints have more restrictive twist limits
32
+ const isMiddleJoint = i > 0 && i < chain.joints.length - 2;
33
+ this._twistConstraints.set(i, {
34
+ minTwist: isMiddleJoint ? -Math.PI * 0.2 : -Math.PI * 0.3,
35
+ maxTwist: isMiddleJoint ? Math.PI * 0.2 : Math.PI * 0.3,
36
+ smoothFactor: 0.3
37
+ });
38
+ }
39
+ }
40
+ /**
41
+ * Set twist constraint for a specific joint.
42
+ *
43
+ * @param jointIndex - Index of the joint
44
+ * @param minTwist - Minimum twist angle in radians
45
+ * @param maxTwist - Maximum twist angle in radians
46
+ * @param smoothFactor - Smoothing factor [0-1] (default: 0.3)
47
+ */ setTwistConstraint(jointIndex, minTwist, maxTwist, smoothFactor = 0.3) {
48
+ if (jointIndex < 0 || jointIndex >= this._chain.joints.length - 1) {
49
+ throw new Error(`Invalid joint index: ${jointIndex}`);
50
+ }
51
+ this._twistConstraints.set(jointIndex, {
52
+ minTwist,
53
+ maxTwist,
54
+ smoothFactor: Math.max(0, Math.min(1, smoothFactor))
55
+ });
56
+ }
57
+ /**
58
+ * Get twist constraint for a specific joint.
59
+ *
60
+ * @param jointIndex - Index of the joint
61
+ * @returns Twist constraint or undefined if not set
62
+ */ getTwistConstraint(jointIndex) {
63
+ return this._twistConstraints.get(jointIndex);
64
+ }
65
+ /**
66
+ * Remove twist constraint for a specific joint.
67
+ *
68
+ * @param jointIndex - Index of the joint
69
+ * @returns True if a constraint was removed
70
+ */ removeTwistConstraint(jointIndex) {
71
+ return this._twistConstraints.delete(jointIndex);
72
+ }
73
+ /**
74
+ * Clear all twist constraints.
75
+ */ clearTwistConstraints() {
76
+ this._twistConstraints.clear();
77
+ }
78
+ /**
79
+ * Set pole vector for a specific joint.
80
+ *
81
+ * @param jointIndex - Index of the joint to apply pole vector to
82
+ * @param poleVector - Pole vector position in world space
83
+ * @param weight - Weight of the pole vector constraint (0-1, default: 1)
84
+ */ setPoleVector(jointIndex, poleVector, weight = 1) {
85
+ if (jointIndex < 0 || jointIndex >= this._chain.joints.length) {
86
+ throw new Error(`Invalid joint index: ${jointIndex}`);
87
+ }
88
+ this._poleVectors.set(jointIndex, {
89
+ position: poleVector.clone(),
90
+ weight: Math.max(0, Math.min(1, weight))
91
+ });
92
+ }
93
+ /**
94
+ * Remove pole vector for a specific joint.
95
+ *
96
+ * @param jointIndex - Index of the joint to remove pole vector from
97
+ * @returns True if a pole vector was removed, false if none existed
98
+ */ removePoleVector(jointIndex) {
99
+ return this._poleVectors.delete(jointIndex);
100
+ }
101
+ /**
102
+ * Clear all pole vectors.
103
+ */ clearPoleVectors() {
104
+ this._poleVectors.clear();
105
+ }
106
+ /**
107
+ * Get pole vector configuration for a specific joint.
108
+ *
109
+ * @param jointIndex - Index of the joint
110
+ * @returns Pole vector configuration or undefined if not set
111
+ */ getPoleVector(jointIndex) {
112
+ const config = this._poleVectors.get(jointIndex);
113
+ if (config) {
114
+ return {
115
+ position: config.position.clone(),
116
+ weight: config.weight
117
+ };
118
+ }
119
+ return undefined;
120
+ }
121
+ /**
122
+ * Check if a joint has a pole vector.
123
+ *
124
+ * @param jointIndex - Index of the joint
125
+ * @returns True if the joint has a pole vector
126
+ */ hasPoleVector(jointIndex) {
127
+ return this._poleVectors.has(jointIndex);
128
+ }
129
+ /**
130
+ * Solve the IK chain to reach the target position using FABRIK algorithm.
131
+ *
132
+ * @param target - Target position for the end effector
133
+ * @returns True if converged within tolerance, false otherwise
134
+ */ solve(target) {
135
+ const joints = this._chain.joints;
136
+ // Update joint positions from scene nodes before solving
137
+ this._chain.updateFromNodes();
138
+ // Store original positions
139
+ this._chain.storeOriginalPositions();
140
+ const rootPos = joints[0].originalPosition.clone();
141
+ // Check if target is reachable
142
+ const distToTarget = Vector3.distance(rootPos, target);
143
+ if (distToTarget > this._chain.totalLength) {
144
+ // Target unreachable - stretch chain toward target
145
+ this._stretchToward(target);
146
+ return false;
147
+ }
148
+ let converged = false;
149
+ for(let iteration = 0; iteration < this._maxIterations; iteration++){
150
+ // Check convergence
151
+ const distToEnd = Vector3.distance(joints[joints.length - 1].position, target);
152
+ if (distToEnd < this._tolerance) {
153
+ converged = true;
154
+ break;
155
+ }
156
+ // Forward pass: end effector to root
157
+ this._forwardPass(target);
158
+ // Backward pass: root to end effector (constraints are applied within the pass)
159
+ this._backwardPass(rootPos);
160
+ }
161
+ return converged;
162
+ }
163
+ /**
164
+ * Apply the solved joint positions to scene nodes as rotations.
165
+ *
166
+ * @param weight - Blend weight (0 = original, 1 = full IK, default: 1)
167
+ */ applyToNodes(weight = 1) {
168
+ const joints = this._chain.joints;
169
+ for(let i = 0; i < joints.length - 1; i++){
170
+ const joint = joints[i];
171
+ const nextJoint = joints[i + 1];
172
+ // Calculate direction from current joint to next joint in world space
173
+ const originalDir = Vector3.sub(nextJoint.originalPosition, joint.originalPosition, new Vector3());
174
+ const newDir = Vector3.sub(nextJoint.position, joint.position, new Vector3());
175
+ const originalDirNorm = Vector3.normalize(originalDir, new Vector3());
176
+ const newDirNorm = Vector3.normalize(newDir, new Vector3());
177
+ // Calculate basic rotation
178
+ const deltaRotation = new Quaternion();
179
+ IKUtils.fromToRotation(originalDirNorm, newDirNorm, deltaRotation);
180
+ // Calculate new world rotation
181
+ let worldRotation = Quaternion.multiply(deltaRotation, joint.originalRotation, new Quaternion());
182
+ // Apply swing-twist constraint to prevent over-rotation
183
+ const swing = new Quaternion();
184
+ const twist = new Quaternion();
185
+ worldRotation.decomposeSwingTwist(newDirNorm, swing, twist);
186
+ // Get twist angle
187
+ let twistAngle = twist.getTwistAngle(newDirNorm);
188
+ // Get twist constraint for this joint
189
+ const constraint = this._twistConstraints.get(i);
190
+ if (constraint) {
191
+ // Clamp and smooth twist
192
+ twistAngle = IKUtils.clampAndSmoothTwist(twistAngle, joint.previousTwist, constraint.minTwist, constraint.maxTwist, constraint.smoothFactor);
193
+ }
194
+ // Store for next frame
195
+ joint.previousTwist = twistAngle;
196
+ // Reconstruct rotation from clamped twist: Q = Twist * Swing
197
+ const clampedTwist = Quaternion.fromAxisAngle(newDirNorm, twistAngle);
198
+ worldRotation = Quaternion.multiply(clampedTwist, swing, worldRotation);
199
+ // Blend with original rotation based on weight
200
+ if (weight < 1) {
201
+ Quaternion.slerp(joint.originalRotation, worldRotation, weight, worldRotation);
202
+ }
203
+ // Store this frame's world rotation
204
+ if (!joint.previousIKRotation) {
205
+ joint.previousIKRotation = worldRotation.clone();
206
+ } else {
207
+ joint.previousIKRotation.set(worldRotation);
208
+ }
209
+ // Convert world rotation to local rotation (relative to parent)
210
+ if (joint.node.parent) {
211
+ const parentWorldRotation = new Quaternion();
212
+ joint.node.parent.worldMatrix.decompose(null, parentWorldRotation, null);
213
+ // localRotation = conjugate(parentWorldRotation) * worldRotation
214
+ const parentInvRotation = Quaternion.conjugate(parentWorldRotation, new Quaternion());
215
+ const localRotation = Quaternion.multiply(parentInvRotation, worldRotation, new Quaternion());
216
+ joint.node.rotation = localRotation;
217
+ } else {
218
+ // Root node has no parent, world rotation is local rotation
219
+ joint.node.rotation = worldRotation;
220
+ }
221
+ }
222
+ }
223
+ /**
224
+ * Forward pass: move from end effector toward root.
225
+ * Each joint is pulled toward its child, maintaining bone length.
226
+ * Constraints are applied immediately after each joint adjustment.
227
+ *
228
+ * @param target - Target position for end effector
229
+ */ _forwardPass(target) {
230
+ const joints = this._chain.joints;
231
+ // Set end effector to target
232
+ joints[joints.length - 1].position.set(target);
233
+ // Move backward through chain
234
+ for(let i = joints.length - 2; i >= 0; i--){
235
+ const joint = joints[i];
236
+ const childJoint = joints[i + 1];
237
+ // Calculate direction from child to current joint
238
+ const direction = Vector3.sub(joint.position, childJoint.position, new Vector3());
239
+ const distance = direction.magnitude;
240
+ if (distance > 0.000001) {
241
+ direction.scaleBy(1 / distance);
242
+ // Place joint at correct distance from child
243
+ Vector3.scale(direction, joint.boneLength, direction);
244
+ Vector3.add(childJoint.position, direction, joint.position);
245
+ }
246
+ // Apply constraints immediately after adjusting this joint
247
+ // This ensures constraints are integrated into the FABRIK algorithm
248
+ if (i > 0) {
249
+ // Apply constraints for joint i (not for root joint)
250
+ this._applyConstraintsForJoint(i);
251
+ }
252
+ }
253
+ }
254
+ /**
255
+ * Backward pass: move from root toward end effector.
256
+ * Each joint is pulled toward its parent, maintaining bone length.
257
+ * Constraints are applied immediately after each joint adjustment.
258
+ *
259
+ * @param rootPos - Original root position to restore
260
+ */ _backwardPass(rootPos) {
261
+ const joints = this._chain.joints;
262
+ // Restore root position
263
+ joints[0].position.set(rootPos);
264
+ // Move forward through chain
265
+ for(let i = 0; i < joints.length - 1; i++){
266
+ const joint = joints[i];
267
+ const childJoint = joints[i + 1];
268
+ // Calculate direction from current joint to child
269
+ const direction = Vector3.sub(childJoint.position, joint.position, new Vector3());
270
+ const distance = direction.magnitude;
271
+ if (distance > 0.000001) {
272
+ direction.scaleBy(1 / distance);
273
+ // Place child at correct distance from current joint
274
+ Vector3.scale(direction, joint.boneLength, direction);
275
+ Vector3.add(joint.position, direction, childJoint.position);
276
+ }
277
+ // Apply constraints immediately after adjusting this joint
278
+ // This ensures constraints are integrated into the FABRIK algorithm
279
+ this._applyConstraintsForJoint(i + 1);
280
+ }
281
+ }
282
+ /**
283
+ * Apply constraints for a specific joint.
284
+ * This is called during the FABRIK passes to integrate constraints into the algorithm.
285
+ *
286
+ * @param jointIndex - Index of the joint to apply constraints to
287
+ */ _applyConstraintsForJoint(jointIndex) {
288
+ const constraints = this._chain.constraints;
289
+ // Apply non-pole-vector constraints
290
+ // IKPoleVectorConstraint is deprecated and ignored in favor of built-in pole vectors
291
+ for (const constraint of constraints){
292
+ if (constraint.jointIndex === jointIndex) {
293
+ // Skip IKPoleVectorConstraint - use built-in pole vectors instead
294
+ if (constraint.constructor.name === 'IKPoleVectorConstraint') {
295
+ continue;
296
+ }
297
+ constraint.apply(this._chain.joints);
298
+ }
299
+ }
300
+ // Apply built-in pole vector if configured for this joint
301
+ const poleConfig = this._poleVectors.get(jointIndex);
302
+ if (poleConfig && poleConfig.weight > 0.001) {
303
+ this._applyPoleVectorTwist(jointIndex, poleConfig.position, poleConfig.weight);
304
+ }
305
+ }
306
+ /**
307
+ * Apply pole vector twist to a specific joint.
308
+ *
309
+ * @remarks
310
+ * This method adjusts the joint position to align with the pole vector.
311
+ * It uses the same algorithm as IKPoleVectorConstraint but is integrated
312
+ * into the solver for better performance and control.
313
+ *
314
+ * @param jointIndex - Index of the pole joint
315
+ * @param poleVector - Pole vector position in world space
316
+ * @param weight - Weight of the pole vector constraint (0-1)
317
+ */ _applyPoleVectorTwist(jointIndex, poleVector, weight) {
318
+ const joints = this._chain.joints;
319
+ // We need at least 3 joints to apply pole vector (parent, pole joint, child)
320
+ if (jointIndex < 1 || jointIndex >= joints.length - 1) {
321
+ return;
322
+ }
323
+ const parentJoint = joints[jointIndex - 1];
324
+ const currentJoint = joints[jointIndex];
325
+ const childJoint = joints[jointIndex + 1];
326
+ const parentPos = parentJoint.position;
327
+ const currentPos = currentJoint.position;
328
+ const childPos = childJoint.position;
329
+ // Calculate the plane defined by parent, child, and pole vector
330
+ // Vector from parent to child (the "line" we're bending around)
331
+ const parentToChild = Vector3.sub(childPos, parentPos, new Vector3());
332
+ const lineLength = parentToChild.magnitude;
333
+ if (lineLength < 0.000001) {
334
+ return; // Parent and child are at same position
335
+ }
336
+ const lineDir = Vector3.scale(parentToChild, 1 / lineLength, new Vector3());
337
+ // Project current joint onto the parent-child line
338
+ const parentToCurrent = Vector3.sub(currentPos, parentPos, new Vector3());
339
+ const projectionLength = Vector3.dot(parentToCurrent, lineDir);
340
+ const projectionPoint = Vector3.scale(lineDir, projectionLength, new Vector3());
341
+ Vector3.add(parentPos, projectionPoint, projectionPoint);
342
+ // Vector from projection point to current joint (perpendicular to line)
343
+ const perpendicular = Vector3.sub(currentPos, projectionPoint, new Vector3());
344
+ const perpLength = perpendicular.magnitude;
345
+ if (perpLength < 0.000001) {
346
+ return; // Current joint is on the line
347
+ }
348
+ // Calculate desired direction toward pole vector
349
+ const parentToPole = Vector3.sub(poleVector, parentPos, new Vector3());
350
+ const poleProjectionLength = Vector3.dot(parentToPole, lineDir);
351
+ const poleProjectionPoint = Vector3.scale(lineDir, poleProjectionLength, new Vector3());
352
+ Vector3.add(parentPos, poleProjectionPoint, poleProjectionPoint);
353
+ // Direction from projection to pole (perpendicular to line)
354
+ const poleDirection = Vector3.sub(poleVector, poleProjectionPoint, new Vector3());
355
+ const poleDirLength = poleDirection.magnitude;
356
+ if (poleDirLength < 0.000001) {
357
+ return; // Pole is on the line
358
+ }
359
+ poleDirection.scaleBy(1 / poleDirLength);
360
+ // Calculate new position for current joint
361
+ // Keep the same distance from the line, but rotate toward pole direction
362
+ const desiredPerpendicular = Vector3.scale(poleDirection, perpLength, new Vector3());
363
+ const newPosition = Vector3.add(projectionPoint, desiredPerpendicular, new Vector3());
364
+ // Apply weight (blend between original and constrained position)
365
+ if (weight < 0.999) {
366
+ const blended = new Vector3();
367
+ blended.x = currentPos.x + (newPosition.x - currentPos.x) * weight;
368
+ blended.y = currentPos.y + (newPosition.y - currentPos.y) * weight;
369
+ blended.z = currentPos.z + (newPosition.z - currentPos.z) * weight;
370
+ currentJoint.position.set(blended);
371
+ } else {
372
+ currentJoint.position.set(newPosition);
373
+ }
374
+ }
375
+ /**
376
+ * Stretch the chain toward an unreachable target.
377
+ * All joints are aligned in a straight line toward the target.
378
+ *
379
+ * @param target - Unreachable target position
380
+ */ _stretchToward(target) {
381
+ const joints = this._chain.joints;
382
+ const rootPos = joints[0].originalPosition;
383
+ // Calculate direction from root to target
384
+ const direction = Vector3.sub(target, rootPos, new Vector3()).inplaceNormalize();
385
+ // Place each joint along the direction at its bone length
386
+ let currentPos = rootPos.clone();
387
+ for(let i = 0; i < joints.length; i++){
388
+ joints[i].position.set(currentPos);
389
+ if (i < joints.length - 1) {
390
+ const offset = Vector3.scale(direction, joints[i].boneLength, new Vector3());
391
+ currentPos.addBy(offset);
392
+ }
393
+ }
394
+ }
395
+ }
396
+
397
+ export { FABRIKSolver };
398
+ //# sourceMappingURL=fabrik_solver.js.map
@@ -0,0 +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 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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"}
@@ -0,0 +1,181 @@
1
+ import { Vector3 } from '@zephyr3d/base';
2
+ import { IKConstraint } from './ik_constraint.js';
3
+
4
+ /**
5
+ * Angle constraint for IK joints.
6
+ *
7
+ * Limits the angle between the bone from parent to this joint
8
+ * and the bone from this joint to child.
9
+ *
10
+ * @remarks
11
+ * This is useful for joints like elbows and knees that have
12
+ * limited range of motion.
13
+ *
14
+ * @public
15
+ */ class IKAngleConstraint extends IKConstraint {
16
+ /** Minimum angle in degrees */ _minAngle;
17
+ /** Maximum angle in degrees */ _maxAngle;
18
+ /**
19
+ * Create an angle constraint.
20
+ *
21
+ * @param jointIndex - Index of the joint in the chain
22
+ * @param minAngle - Minimum angle in degrees (0 = straight)
23
+ * @param maxAngle - Maximum angle in degrees (180 = fully bent)
24
+ */ constructor(jointIndex, minAngle, maxAngle){
25
+ super(jointIndex);
26
+ this._minAngle = Math.max(0, minAngle);
27
+ this._maxAngle = Math.min(180, maxAngle);
28
+ if (this._minAngle > this._maxAngle) {
29
+ throw new Error('IKAngleConstraint: minAngle must be <= maxAngle');
30
+ }
31
+ }
32
+ /**
33
+ * Get the minimum angle in degrees.
34
+ */ get minAngle() {
35
+ return this._minAngle;
36
+ }
37
+ /**
38
+ * Set the minimum angle in degrees.
39
+ */ set minAngle(value) {
40
+ this._minAngle = Math.max(0, Math.min(value, this._maxAngle));
41
+ }
42
+ /**
43
+ * Get the maximum angle in degrees.
44
+ */ get maxAngle() {
45
+ return this._maxAngle;
46
+ }
47
+ /**
48
+ * Set the maximum angle in degrees.
49
+ */ set maxAngle(value) {
50
+ this._maxAngle = Math.min(180, Math.max(value, this._minAngle));
51
+ }
52
+ /**
53
+ * Apply the angle constraint to limit joint bending.
54
+ */ apply(joints) {
55
+ const index = this._jointIndex;
56
+ // For end effector (last joint), we constrain the angle between the last two bones
57
+ // For other joints, we constrain the angle at the joint itself
58
+ if (index === joints.length - 1) {
59
+ // End effector: constrain angle between (parent-1 -> parent) and (parent -> this)
60
+ if (index < 2) {
61
+ return; // Need at least 3 joints total
62
+ }
63
+ this._applyEndEffectorConstraint(joints, index);
64
+ } else {
65
+ // Regular joint: constrain angle between (parent -> this) and (this -> child)
66
+ if (index < 1) {
67
+ return; // Root joint cannot be constrained this way
68
+ }
69
+ this._applyRegularConstraint(joints, index);
70
+ }
71
+ }
72
+ /**
73
+ * Apply constraint to end effector joint.
74
+ */ _applyEndEffectorConstraint(joints, index) {
75
+ const grandParentJoint = joints[index - 2];
76
+ const parentJoint = joints[index - 1];
77
+ const currentJoint = joints[index];
78
+ // Calculate bone vectors
79
+ const incomingBone = Vector3.sub(parentJoint.position, grandParentJoint.position, new Vector3());
80
+ const outgoingBone = Vector3.sub(currentJoint.position, parentJoint.position, new Vector3());
81
+ const incomingLen = incomingBone.magnitude;
82
+ const outgoingLen = outgoingBone.magnitude;
83
+ if (incomingLen < 0.000001 || outgoingLen < 0.000001) {
84
+ return;
85
+ }
86
+ // Normalize
87
+ const incomingNorm = Vector3.scale(incomingBone, 1 / incomingLen, new Vector3());
88
+ const outgoingNorm = Vector3.scale(outgoingBone, 1 / outgoingLen, new Vector3());
89
+ // Calculate current angle
90
+ const dot = Vector3.dot(incomingNorm, outgoingNorm);
91
+ const currentAngleDeg = Math.acos(Math.max(-1, Math.min(1, dot))) * (180 / Math.PI);
92
+ // Check if constraint is violated
93
+ let targetAngleDeg = currentAngleDeg;
94
+ if (currentAngleDeg < this._minAngle) {
95
+ targetAngleDeg = this._minAngle;
96
+ } else if (currentAngleDeg > this._maxAngle) {
97
+ targetAngleDeg = this._maxAngle;
98
+ } else {
99
+ return;
100
+ }
101
+ // Apply the same constraint logic as regular joints
102
+ this._adjustJointAngle(incomingNorm, outgoingNorm, currentAngleDeg, targetAngleDeg, parentJoint, currentJoint);
103
+ }
104
+ /**
105
+ * Apply constraint to regular joint.
106
+ */ _applyRegularConstraint(joints, index) {
107
+ const parentJoint = joints[index - 1];
108
+ const currentJoint = joints[index];
109
+ const childJoint = joints[index + 1];
110
+ // Calculate bone vectors: incoming bone (parent->current) and outgoing bone (current->child)
111
+ const incomingBone = Vector3.sub(currentJoint.position, parentJoint.position, new Vector3());
112
+ const outgoingBone = Vector3.sub(childJoint.position, currentJoint.position, new Vector3());
113
+ const incomingLen = incomingBone.magnitude;
114
+ const outgoingLen = outgoingBone.magnitude;
115
+ if (incomingLen < 0.000001 || outgoingLen < 0.000001) {
116
+ return;
117
+ }
118
+ // Normalize
119
+ const incomingNorm = Vector3.scale(incomingBone, 1 / incomingLen, new Vector3());
120
+ const outgoingNorm = Vector3.scale(outgoingBone, 1 / outgoingLen, new Vector3());
121
+ // Calculate current angle between incoming and outgoing bones (interior angle)
122
+ const dot = Vector3.dot(incomingNorm, outgoingNorm);
123
+ const currentAngleDeg = Math.acos(Math.max(-1, Math.min(1, dot))) * (180 / Math.PI);
124
+ // Check if constraint is violated
125
+ let targetAngleDeg = currentAngleDeg;
126
+ if (currentAngleDeg < this._minAngle) {
127
+ targetAngleDeg = this._minAngle;
128
+ } else if (currentAngleDeg > this._maxAngle) {
129
+ targetAngleDeg = this._maxAngle;
130
+ } else {
131
+ return;
132
+ }
133
+ // Apply the constraint
134
+ this._adjustJointAngle(incomingNorm, outgoingNorm, currentAngleDeg, targetAngleDeg, currentJoint, childJoint);
135
+ }
136
+ /**
137
+ * Adjust joint angle by rotating the outgoing bone.
138
+ */ _adjustJointAngle(incomingNorm, outgoingNorm, currentAngleDeg, targetAngleDeg, pivotJoint, targetJoint) {
139
+ // Add a dead zone to prevent oscillation
140
+ const angleDifference = Math.abs(targetAngleDeg - currentAngleDeg);
141
+ const isHardConstraint = Math.abs(this._maxAngle - this._minAngle) < 0.01;
142
+ const deadZone = isHardConstraint ? 0.2 : 0.1;
143
+ if (angleDifference < deadZone) {
144
+ return; // Too close to target, avoid over-correction
145
+ }
146
+ // Calculate rotation axis (perpendicular to both bone vectors)
147
+ const axis = Vector3.cross(incomingNorm, outgoingNorm, new Vector3());
148
+ const axisLen = axis.magnitude;
149
+ // Use a smaller threshold to allow constraint to work at small angles
150
+ if (axisLen < 0.0001) {
151
+ return; // Vectors are too close to parallel or anti-parallel
152
+ }
153
+ axis.scaleBy(1 / axisLen);
154
+ // Calculate the angle we need to rotate
155
+ const targetAngleRad = targetAngleDeg * (Math.PI / 180);
156
+ const currentAngleRad = currentAngleDeg * (Math.PI / 180);
157
+ let deltaAngle = targetAngleRad - currentAngleRad;
158
+ // Apply full correction without damping to ensure constraints are enforced
159
+ // This is necessary because FABRIK will try to undo the constraint in the next iteration
160
+ // So we need strong constraint enforcement
161
+ // Rotate the outgoing bone vector around the axis by deltaAngle
162
+ const cos = Math.cos(deltaAngle);
163
+ const sin = Math.sin(deltaAngle);
164
+ const oneMinusCos = 1 - cos;
165
+ // Rodrigues' rotation formula
166
+ const rotated = new Vector3();
167
+ rotated.x = outgoingNorm.x * (cos + axis.x * axis.x * oneMinusCos) + outgoingNorm.y * (axis.x * axis.y * oneMinusCos - axis.z * sin) + outgoingNorm.z * (axis.x * axis.z * oneMinusCos + axis.y * sin);
168
+ rotated.y = outgoingNorm.x * (axis.y * axis.x * oneMinusCos + axis.z * sin) + outgoingNorm.y * (cos + axis.y * axis.y * oneMinusCos) + outgoingNorm.z * (axis.y * axis.z * oneMinusCos - axis.x * sin);
169
+ rotated.z = outgoingNorm.x * (axis.z * axis.x * oneMinusCos - axis.y * sin) + outgoingNorm.y * (axis.z * axis.y * oneMinusCos + axis.x * sin) + outgoingNorm.z * (cos + axis.z * axis.z * oneMinusCos);
170
+ // Update target joint position using the rotated bone vector
171
+ const boneLength = pivotJoint.boneLength;
172
+ rotated.scaleBy(boneLength);
173
+ Vector3.add(pivotJoint.position, rotated, targetJoint.position);
174
+ // Note: We do NOT recursively update subsequent joints here.
175
+ // Instead, we let FABRIK algorithm handle the propagation in subsequent iterations.
176
+ // This ensures that each joint's constraint is properly applied.
177
+ }
178
+ }
179
+
180
+ export { IKAngleConstraint };
181
+ //# sourceMappingURL=ik_angle_constraint.js.map