@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,191 @@
1
+ import { Vector3, Quaternion } from '@zephyr3d/base';
2
+
3
+ /**
4
+ * Utility functions for IK calculations.
5
+ *
6
+ * @internal
7
+ */ class IKUtils {
8
+ /**
9
+ * Calculate the rotation needed to align 'from' direction to 'to' direction.
10
+ *
11
+ * @param from - Starting direction vector
12
+ * @param to - Target direction vector
13
+ * @param result - Output quaternion
14
+ * @returns The rotation quaternion
15
+ */ static fromToRotation(from, to, result) {
16
+ const fromNorm = Vector3.normalize(from, new Vector3());
17
+ const toNorm = Vector3.normalize(to, new Vector3());
18
+ const dot = Vector3.dot(fromNorm, toNorm);
19
+ // Vectors are parallel
20
+ if (dot >= 0.999999) {
21
+ return result.identity();
22
+ }
23
+ // Vectors are opposite
24
+ if (dot <= -0.999999) {
25
+ // Find an orthogonal axis
26
+ let axis = Vector3.cross(Vector3.axisPX(), fromNorm, new Vector3());
27
+ const lenSq = axis.x * axis.x + axis.y * axis.y + axis.z * axis.z;
28
+ if (lenSq < 0.000001) {
29
+ axis = Vector3.cross(Vector3.axisPY(), fromNorm, new Vector3());
30
+ }
31
+ axis.inplaceNormalize();
32
+ return result.fromAxisAngle(axis, Math.PI);
33
+ }
34
+ // General case
35
+ const axis = Vector3.cross(fromNorm, toNorm).inplaceNormalize();
36
+ const angle = Math.acos(dot);
37
+ return result.fromAxisAngle(axis, angle);
38
+ }
39
+ /**
40
+ * Calculate bone length between two positions.
41
+ *
42
+ * @param start - Start position
43
+ * @param end - End position
44
+ * @returns Distance between positions
45
+ */ static calculateBoneLength(start, end) {
46
+ return Vector3.distance(start, end);
47
+ }
48
+ /**
49
+ * Clamp twist angle and optionally smooth with previous twist.
50
+ *
51
+ * @param currentTwist - Current twist angle in radians
52
+ * @param previousTwist - Previous frame's twist angle in radians (optional)
53
+ * @param minTwist - Minimum allowed twist angle in radians
54
+ * @param maxTwist - Maximum allowed twist angle in radians
55
+ * @param smoothFactor - Smoothing factor [0-1], 0 = no smoothing, 1 = full smoothing
56
+ * @returns Clamped and smoothed twist angle
57
+ */ static clampAndSmoothTwist(currentTwist, previousTwist, minTwist, maxTwist, smoothFactor = 0.5) {
58
+ // Clamp to range
59
+ let clampedTwist = Math.max(minTwist, Math.min(maxTwist, currentTwist));
60
+ // Smooth with previous frame if available
61
+ if (previousTwist !== undefined && smoothFactor > 0.001) {
62
+ // Normalize angle difference to [-PI, PI]
63
+ let diff = clampedTwist - previousTwist;
64
+ while(diff > Math.PI){
65
+ diff -= 2 * Math.PI;
66
+ }
67
+ while(diff < -Math.PI){
68
+ diff += 2 * Math.PI;
69
+ }
70
+ // Lerp
71
+ clampedTwist = previousTwist + diff * (1 - smoothFactor);
72
+ }
73
+ return clampedTwist;
74
+ }
75
+ /**
76
+ * Calculate a look-at rotation with twist constraint using a pole vector.
77
+ *
78
+ * @remarks
79
+ * This creates a rotation that:
80
+ * 1. Aligns 'forward' direction to 'targetDir'
81
+ * 2. Keeps the perpendicular plane aligned with 'poleDir'
82
+ *
83
+ * This prevents unwanted twist around the bone axis by using an external
84
+ * reference direction (pole vector) rather than relying on previous rotations.
85
+ *
86
+ * @param forward - Current forward direction (will be aligned to targetDir)
87
+ * @param targetDir - Desired forward direction
88
+ * @param poleDir - Direction that should be in the "up" hemisphere (from joint position)
89
+ * @param result - Output quaternion
90
+ * @returns The rotation quaternion
91
+ */ static lookAtRotationWithPole(forward, targetDir, poleDir, result) {
92
+ const forwardNorm = Vector3.normalize(forward, new Vector3());
93
+ const targetDirNorm = Vector3.normalize(targetDir, new Vector3());
94
+ const poleDirNorm = Vector3.normalize(poleDir, new Vector3());
95
+ // First, align forward to targetDir (swing rotation)
96
+ const swingRotation = new Quaternion();
97
+ this.fromToRotation(forwardNorm, targetDirNorm, swingRotation);
98
+ // Calculate the "right" vector perpendicular to targetDir and poleDir
99
+ // This defines the plane that the bone should bend in
100
+ const right = Vector3.cross(targetDirNorm, poleDirNorm, new Vector3());
101
+ const rightLenSq = right.x * right.x + right.y * right.y + right.z * right.z;
102
+ // If pole is parallel to target direction, no twist correction possible
103
+ if (rightLenSq < 0.000001) {
104
+ result.set(swingRotation);
105
+ return result;
106
+ }
107
+ right.scaleBy(1 / Math.sqrt(rightLenSq));
108
+ // Calculate the "up" vector perpendicular to targetDir in the pole plane
109
+ const up = Vector3.cross(right, targetDirNorm, new Vector3()).inplaceNormalize();
110
+ // Now we need to find the twist rotation around targetDir
111
+ // We want the local "up" axis to align with the calculated "up" vector
112
+ // Get a perpendicular vector to forward in the original space
113
+ let originalUp = Vector3.cross(forwardNorm, Vector3.axisPY(), new Vector3());
114
+ const originalUpLenSq = originalUp.x * originalUp.x + originalUp.y * originalUp.y + originalUp.z * originalUp.z;
115
+ if (originalUpLenSq < 0.000001) {
116
+ originalUp = Vector3.cross(forwardNorm, Vector3.axisPX(), new Vector3());
117
+ }
118
+ originalUp.inplaceNormalize();
119
+ // Rotate originalUp by swing rotation to see where it ends up
120
+ const rotatedUp = swingRotation.transform(originalUp, new Vector3());
121
+ // Project rotatedUp onto the plane perpendicular to targetDir
122
+ const rotatedUpDot = Vector3.dot(rotatedUp, targetDirNorm);
123
+ const rotatedUpProj = Vector3.scale(targetDirNorm, rotatedUpDot, new Vector3());
124
+ const rotatedUpPerp = Vector3.sub(rotatedUp, rotatedUpProj, new Vector3());
125
+ const rotatedUpPerpLen = rotatedUpPerp.magnitude;
126
+ if (rotatedUpPerpLen < 0.000001) {
127
+ result.set(swingRotation);
128
+ return result;
129
+ }
130
+ rotatedUpPerp.scaleBy(1 / rotatedUpPerpLen);
131
+ // Calculate twist rotation to align rotatedUpPerp with up
132
+ const twistRotation = new Quaternion();
133
+ this.fromToRotation(rotatedUpPerp, up, twistRotation);
134
+ // Combine swing and twist
135
+ return Quaternion.multiply(twistRotation, swingRotation, result);
136
+ }
137
+ /**
138
+ * Calculate a look-at rotation with twist constraint.
139
+ *
140
+ * @remarks
141
+ * This creates a rotation that:
142
+ * 1. Aligns 'forward' direction to 'targetDir'
143
+ * 2. Keeps 'up' direction as close as possible to 'targetUp'
144
+ *
145
+ * This prevents unwanted twist around the bone axis.
146
+ *
147
+ * @param forward - Current forward direction (will be aligned to targetDir)
148
+ * @param targetDir - Desired forward direction
149
+ * @param up - Current up direction (perpendicular to forward)
150
+ * @param targetUp - Desired up direction (will be projected perpendicular to targetDir)
151
+ * @param result - Output quaternion
152
+ * @returns The rotation quaternion
153
+ */ static lookAtRotation(forward, targetDir, up, targetUp, result) {
154
+ const forwardNorm = Vector3.normalize(forward, new Vector3());
155
+ const targetDirNorm = Vector3.normalize(targetDir, new Vector3());
156
+ // First, align forward to targetDir (swing rotation)
157
+ const swingRotation = new Quaternion();
158
+ this.fromToRotation(forwardNorm, targetDirNorm, swingRotation);
159
+ // Rotate the up vector by swing rotation
160
+ const rotatedUp = swingRotation.transform(up, new Vector3());
161
+ // Project targetUp onto plane perpendicular to targetDir
162
+ const dot = Vector3.dot(targetUp, targetDirNorm);
163
+ const projection = Vector3.scale(targetDirNorm, dot, new Vector3());
164
+ const targetUpPerp = Vector3.sub(targetUp, projection, new Vector3());
165
+ const targetUpPerpLen = targetUpPerp.magnitude;
166
+ // If targetUp is parallel to targetDir, no twist correction needed
167
+ if (targetUpPerpLen < 0.000001) {
168
+ result.set(swingRotation);
169
+ return result;
170
+ }
171
+ targetUpPerp.scaleBy(1 / targetUpPerpLen);
172
+ // Project rotatedUp onto the same plane
173
+ const rotatedUpDot = Vector3.dot(rotatedUp, targetDirNorm);
174
+ const rotatedUpProj = Vector3.scale(targetDirNorm, rotatedUpDot, new Vector3());
175
+ const rotatedUpPerp = Vector3.sub(rotatedUp, rotatedUpProj, new Vector3());
176
+ const rotatedUpPerpLen = rotatedUpPerp.magnitude;
177
+ if (rotatedUpPerpLen < 0.000001) {
178
+ result.set(swingRotation);
179
+ return result;
180
+ }
181
+ rotatedUpPerp.scaleBy(1 / rotatedUpPerpLen);
182
+ // Calculate twist rotation around targetDir
183
+ const twistRotation = new Quaternion();
184
+ this.fromToRotation(rotatedUpPerp, targetUpPerp, twistRotation);
185
+ // Combine swing and twist
186
+ return Quaternion.multiply(twistRotation, swingRotation, result);
187
+ }
188
+ }
189
+
190
+ export { IKUtils };
191
+ //# sourceMappingURL=ik_utils.js.map
@@ -0,0 +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 * 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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"}
@@ -0,0 +1,331 @@
1
+ import { Vector3, Quaternion } from '@zephyr3d/base';
2
+ import { IKSolver } from './ik_solver.js';
3
+ import { IKUtils } from './ik_utils.js';
4
+
5
+ /**
6
+ * Two Bone IK solver for chains with exactly 3 joints (2 bones).
7
+ *
8
+ * @remarks
9
+ * This solver uses an analytical solution specifically optimized for
10
+ * two-bone chains like arms (shoulder-elbow-wrist) or legs (hip-knee-ankle).
11
+ * It's faster and more stable than iterative methods like FABRIK for this case.
12
+ *
13
+ * The solver supports an optional pole vector to control the bending direction
14
+ * of the middle joint (elbow/knee).
15
+ *
16
+ * @public
17
+ */ class TwoBoneIKSolver extends IKSolver {
18
+ /** Optional pole vector position in world space */ _poleVector;
19
+ /** Weight of the pole vector constraint (0-1) */ _poleWeight;
20
+ /** Twist constraints for each joint (indexed by joint index) */ _twistConstraints;
21
+ /**
22
+ * Create a Two Bone IK solver.
23
+ *
24
+ * @param chain - The IK chain to solve (must have exactly 3 joints)
25
+ * @param poleVector - Optional pole vector position in world space
26
+ * @param poleWeight - Weight of the pole vector constraint (0-1, default: 1)
27
+ */ constructor(chain, poleVector = null, poleWeight = 1){
28
+ super(chain, 1, 0.001); // Two bone IK doesn't need iterations
29
+ if (chain.joints.length !== 3) {
30
+ throw new Error('Two Bone IK requires exactly 3 joints (2 bones)');
31
+ }
32
+ this._poleVector = poleVector ? poleVector.clone() : null;
33
+ this._poleWeight = Math.max(0, Math.min(1, poleWeight));
34
+ this._twistConstraints = new Map();
35
+ // Set default twist constraints
36
+ // Root joint (shoulder/hip) - moderate twist
37
+ this._twistConstraints.set(0, {
38
+ minTwist: -Math.PI * 0.25,
39
+ maxTwist: Math.PI * 0.25,
40
+ smoothFactor: 0.3
41
+ });
42
+ // Middle joint (elbow/knee) - very limited twist
43
+ this._twistConstraints.set(1, {
44
+ minTwist: -Math.PI * 0.15,
45
+ maxTwist: Math.PI * 0.15,
46
+ smoothFactor: 0.3
47
+ });
48
+ }
49
+ /**
50
+ * Set twist constraint for a specific joint.
51
+ *
52
+ * @param jointIndex - Index of the joint (0 = root, 1 = middle)
53
+ * @param minTwist - Minimum twist angle in radians
54
+ * @param maxTwist - Maximum twist angle in radians
55
+ * @param smoothFactor - Smoothing factor [0-1] (default: 0.3)
56
+ */ setTwistConstraint(jointIndex, minTwist, maxTwist, smoothFactor = 0.3) {
57
+ if (jointIndex < 0 || jointIndex >= this._chain.joints.length - 1) {
58
+ throw new Error(`Invalid joint index: ${jointIndex}`);
59
+ }
60
+ this._twistConstraints.set(jointIndex, {
61
+ minTwist,
62
+ maxTwist,
63
+ smoothFactor: Math.max(0, Math.min(1, smoothFactor))
64
+ });
65
+ }
66
+ /**
67
+ * Get twist constraint for a specific joint.
68
+ *
69
+ * @param jointIndex - Index of the joint
70
+ * @returns Twist constraint or undefined if not set
71
+ */ getTwistConstraint(jointIndex) {
72
+ return this._twistConstraints.get(jointIndex);
73
+ }
74
+ /**
75
+ * Remove twist constraint for a specific joint.
76
+ *
77
+ * @param jointIndex - Index of the joint
78
+ * @returns True if a constraint was removed
79
+ */ removeTwistConstraint(jointIndex) {
80
+ return this._twistConstraints.delete(jointIndex);
81
+ }
82
+ /**
83
+ * Clear all twist constraints.
84
+ */ clearTwistConstraints() {
85
+ this._twistConstraints.clear();
86
+ }
87
+ /**
88
+ * Get the pole vector position.
89
+ */ get poleVector() {
90
+ return this._poleVector;
91
+ }
92
+ /**
93
+ * Set the pole vector position.
94
+ */ set poleVector(value) {
95
+ if (value) {
96
+ if (!this._poleVector) {
97
+ this._poleVector = value.clone();
98
+ } else {
99
+ this._poleVector.set(value);
100
+ }
101
+ } else {
102
+ this._poleVector = null;
103
+ }
104
+ }
105
+ /**
106
+ * Get the pole vector weight.
107
+ */ get poleWeight() {
108
+ return this._poleWeight;
109
+ }
110
+ /**
111
+ * Set the pole vector weight (0-1).
112
+ */ set poleWeight(value) {
113
+ this._poleWeight = Math.max(0, Math.min(1, value));
114
+ }
115
+ /**
116
+ * Solve the IK chain to reach the target position using Two Bone IK algorithm.
117
+ *
118
+ * @param target - Target position for the end effector
119
+ * @returns True if the target is reachable, false if stretched to maximum
120
+ */ solve(target) {
121
+ const joints = this._chain.joints;
122
+ // Update joint positions from scene nodes before solving
123
+ this._chain.updateFromNodes();
124
+ // Store original positions
125
+ this._chain.storeOriginalPositions();
126
+ const root = joints[0];
127
+ const middle = joints[1];
128
+ const end = joints[2];
129
+ const rootPos = root.position;
130
+ const upperLength = root.boneLength; // Length from root to middle
131
+ const lowerLength = middle.boneLength; // Length from middle to end
132
+ const totalLength = upperLength + lowerLength;
133
+ // Calculate direction and distance from root to target
134
+ const rootToTarget = Vector3.sub(target, rootPos, new Vector3());
135
+ const targetDistance = rootToTarget.magnitude;
136
+ // Check if target is reachable
137
+ if (targetDistance < 0.000001) {
138
+ // Target is at root position, keep original pose
139
+ return true;
140
+ }
141
+ let reachable = true;
142
+ // If target is unreachable, clamp to maximum distance
143
+ let effectiveTarget = target;
144
+ if (targetDistance >= totalLength - 0.0001) {
145
+ // Stretch to maximum length
146
+ const direction = Vector3.scale(rootToTarget, 1 / targetDistance, new Vector3());
147
+ effectiveTarget = Vector3.add(rootPos, Vector3.scale(direction, totalLength - 0.0001, new Vector3()), new Vector3());
148
+ reachable = false;
149
+ }
150
+ // Calculate the distance from root to effective target
151
+ const rootToEffectiveTarget = Vector3.sub(effectiveTarget, rootPos, new Vector3());
152
+ const distance = rootToEffectiveTarget.magnitude;
153
+ // Use law of cosines to find the angle at the root joint
154
+ // cos(rootAngle) = (a² + c² - b²) / (2ac)
155
+ const cosRootAngle = (upperLength * upperLength + distance * distance - lowerLength * lowerLength) / (2 * upperLength * distance);
156
+ const clampedCosRootAngle = Math.max(-1, Math.min(1, cosRootAngle));
157
+ const rootAngle = Math.acos(clampedCosRootAngle);
158
+ // Determine the plane of bending
159
+ let bendNormal;
160
+ if (this._poleVector && this._poleWeight > 0.001) {
161
+ // Use pole vector to determine bend direction
162
+ const rootToTargetDir = Vector3.normalize(rootToEffectiveTarget, new Vector3());
163
+ const rootToPole = Vector3.sub(this._poleVector, rootPos, new Vector3());
164
+ // Project pole vector onto plane perpendicular to root-target direction
165
+ const projectionLength = Vector3.dot(rootToPole, rootToTargetDir);
166
+ const projection = Vector3.scale(rootToTargetDir, projectionLength, new Vector3());
167
+ const perpendicular = Vector3.sub(rootToPole, projection, new Vector3());
168
+ const perpLength = perpendicular.magnitude;
169
+ if (perpLength > 0.000001) {
170
+ // Bend normal is perpendicular to both root-target and pole direction
171
+ bendNormal = Vector3.cross(rootToTargetDir, perpendicular, new Vector3()).inplaceNormalize();
172
+ } else {
173
+ // Pole is on the line, use default bend direction
174
+ bendNormal = this._getDefaultBendNormal(rootToEffectiveTarget);
175
+ }
176
+ // Apply pole weight
177
+ if (this._poleWeight < 0.999) {
178
+ const defaultNormal = this._getDefaultBendNormal(rootToEffectiveTarget);
179
+ // Slerp between default and pole-based normal
180
+ const angle = Math.acos(Math.max(-1, Math.min(1, Vector3.dot(defaultNormal, bendNormal))));
181
+ if (angle > 0.001) {
182
+ const axis = Vector3.cross(defaultNormal, bendNormal, new Vector3()).inplaceNormalize();
183
+ const rotation = new Quaternion().fromAxisAngle(axis, angle * this._poleWeight);
184
+ bendNormal = rotation.transform(defaultNormal, new Vector3());
185
+ }
186
+ }
187
+ } else {
188
+ // No pole vector, use default bend direction
189
+ bendNormal = this._getDefaultBendNormal(rootToEffectiveTarget);
190
+ }
191
+ // Calculate middle joint position
192
+ const rootToTargetDir = Vector3.normalize(rootToEffectiveTarget, new Vector3());
193
+ // Rotate root-to-target direction by rootAngle around bendNormal
194
+ const rotationToMiddle = new Quaternion().fromAxisAngle(bendNormal, rootAngle);
195
+ const rootToMiddleDir = rotationToMiddle.transform(rootToTargetDir, new Vector3());
196
+ // Place middle joint
197
+ middle.position.set(Vector3.add(rootPos, Vector3.scale(rootToMiddleDir, upperLength, new Vector3()), new Vector3()));
198
+ // Place end joint at target
199
+ end.position.set(effectiveTarget);
200
+ // Apply constraints after solving
201
+ // Note: Constraints may modify joint positions, which could affect bone lengths
202
+ // For Two Bone IK, we apply constraints and then restore bone lengths
203
+ this._applyConstraints();
204
+ return reachable;
205
+ }
206
+ /**
207
+ * Apply all constraints to the joint chain.
208
+ * After applying constraints, we need to restore bone lengths.
209
+ */ _applyConstraints() {
210
+ const constraints = this._chain.constraints;
211
+ if (constraints.length === 0) {
212
+ return;
213
+ }
214
+ const joints = this._chain.joints;
215
+ // Apply each constraint
216
+ for (const constraint of constraints){
217
+ constraint.apply(joints);
218
+ }
219
+ // After constraints are applied, we need to restore bone lengths
220
+ // because constraints may have moved joints in ways that change bone lengths
221
+ // For Two Bone IK, we fix this by adjusting positions while maintaining the constraint
222
+ this._restoreBoneLengths();
223
+ }
224
+ /**
225
+ * Restore bone lengths after constraints have been applied.
226
+ * This ensures that the chain maintains correct bone lengths.
227
+ */ _restoreBoneLengths() {
228
+ const joints = this._chain.joints;
229
+ const root = joints[0];
230
+ const middle = joints[1];
231
+ const end = joints[2];
232
+ const upperLength = root.boneLength;
233
+ const lowerLength = middle.boneLength;
234
+ // Fix middle joint position to maintain upper bone length
235
+ const rootToMiddle = Vector3.sub(middle.position, root.position, new Vector3());
236
+ const rootToMiddleDist = rootToMiddle.magnitude;
237
+ if (rootToMiddleDist > 0.000001 && Math.abs(rootToMiddleDist - upperLength) > 0.0001) {
238
+ const rootToMiddleDir = Vector3.scale(rootToMiddle, 1 / rootToMiddleDist, new Vector3());
239
+ middle.position.set(Vector3.add(root.position, Vector3.scale(rootToMiddleDir, upperLength, new Vector3()), new Vector3()));
240
+ }
241
+ // Fix end joint position to maintain lower bone length
242
+ const middleToEnd = Vector3.sub(end.position, middle.position, new Vector3());
243
+ const middleToEndDist = middleToEnd.magnitude;
244
+ if (middleToEndDist > 0.000001 && Math.abs(middleToEndDist - lowerLength) > 0.0001) {
245
+ const middleToEndDir = Vector3.scale(middleToEnd, 1 / middleToEndDist, new Vector3());
246
+ end.position.set(Vector3.add(middle.position, Vector3.scale(middleToEndDir, lowerLength, new Vector3()), new Vector3()));
247
+ }
248
+ }
249
+ /**
250
+ * Apply the solved joint positions to scene nodes as rotations.
251
+ *
252
+ * @param weight - Blend weight (0 = original, 1 = full IK, default: 1)
253
+ */ applyToNodes(weight = 1) {
254
+ const joints = this._chain.joints;
255
+ // Apply rotation for root and middle joints (end joint doesn't need rotation)
256
+ for(let i = 0; i < joints.length - 1; i++){
257
+ const joint = joints[i];
258
+ const nextJoint = joints[i + 1];
259
+ // Calculate direction from current joint to next joint in world space
260
+ const originalDir = Vector3.sub(nextJoint.originalPosition, joint.originalPosition, new Vector3());
261
+ const newDir = Vector3.sub(nextJoint.position, joint.position, new Vector3());
262
+ const originalDirNorm = Vector3.normalize(originalDir, new Vector3());
263
+ const newDirNorm = Vector3.normalize(newDir, new Vector3());
264
+ // Calculate basic rotation
265
+ const deltaRotation = new Quaternion();
266
+ IKUtils.fromToRotation(originalDirNorm, newDirNorm, deltaRotation);
267
+ // Calculate new world rotation
268
+ let worldRotation = Quaternion.multiply(deltaRotation, joint.originalRotation, new Quaternion());
269
+ // Apply swing-twist constraint to prevent over-rotation
270
+ // Decompose rotation around bone axis
271
+ const swing = new Quaternion();
272
+ const twist = new Quaternion();
273
+ worldRotation.decomposeSwingTwist(newDirNorm, swing, twist);
274
+ // Get twist angle
275
+ let twistAngle = twist.getTwistAngle(newDirNorm);
276
+ // Get twist constraint for this joint
277
+ const constraint = this._twistConstraints.get(i);
278
+ if (constraint) {
279
+ // Clamp and smooth twist
280
+ twistAngle = IKUtils.clampAndSmoothTwist(twistAngle, joint.previousTwist, constraint.minTwist, constraint.maxTwist, constraint.smoothFactor);
281
+ }
282
+ // Store for next frame
283
+ joint.previousTwist = twistAngle;
284
+ // Reconstruct rotation from clamped twist: Q = Twist * Swing
285
+ const clampedTwist = Quaternion.fromAxisAngle(newDirNorm, twistAngle);
286
+ worldRotation = Quaternion.multiply(clampedTwist, swing, worldRotation);
287
+ // Blend with original rotation based on weight
288
+ if (weight < 1) {
289
+ Quaternion.slerp(joint.originalRotation, worldRotation, weight, worldRotation);
290
+ }
291
+ // Store this frame's world rotation for next frame's twist continuity
292
+ if (!joint.previousIKRotation) {
293
+ joint.previousIKRotation = worldRotation.clone();
294
+ } else {
295
+ joint.previousIKRotation.set(worldRotation);
296
+ }
297
+ // Convert world rotation to local rotation (relative to parent)
298
+ if (joint.node.parent) {
299
+ const parentWorldRotation = new Quaternion();
300
+ joint.node.parent.worldMatrix.decompose(null, parentWorldRotation, null);
301
+ // localRotation = conjugate(parentWorldRotation) * worldRotation
302
+ const parentInvRotation = Quaternion.conjugate(parentWorldRotation, new Quaternion());
303
+ const localRotation = Quaternion.multiply(parentInvRotation, worldRotation, new Quaternion());
304
+ joint.node.rotation = localRotation;
305
+ } else {
306
+ // Root node has no parent, world rotation is local rotation
307
+ joint.node.rotation = worldRotation;
308
+ }
309
+ }
310
+ }
311
+ /**
312
+ * Get a default bend normal when no pole vector is specified.
313
+ * This tries to find a reasonable perpendicular direction.
314
+ *
315
+ * @param rootToTarget - Direction from root to target
316
+ * @returns A normalized perpendicular vector
317
+ */ _getDefaultBendNormal(rootToTarget) {
318
+ const rootToTargetDir = Vector3.normalize(rootToTarget, new Vector3());
319
+ // Try to use world up (Y axis) as reference
320
+ let bendNormal = Vector3.cross(rootToTargetDir, Vector3.axisPY(), new Vector3());
321
+ const lenSq = bendNormal.x * bendNormal.x + bendNormal.y * bendNormal.y + bendNormal.z * bendNormal.z;
322
+ // If root-to-target is parallel to Y axis, use X axis instead
323
+ if (lenSq < 0.000001) {
324
+ bendNormal = Vector3.cross(rootToTargetDir, Vector3.axisPX(), new Vector3());
325
+ }
326
+ return bendNormal.inplaceNormalize();
327
+ }
328
+ }
329
+
330
+ export { TwoBoneIKSolver };
331
+ //# sourceMappingURL=two_bone_ik_solver.js.map
@@ -0,0 +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 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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"}