@zephyr3d/scene 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation/animationset.js +198 -1
- package/dist/animation/animationset.js.map +1 -1
- package/dist/animation/ik/ccd_solver.js +3 -4
- package/dist/animation/ik/ccd_solver.js.map +1 -1
- package/dist/animation/ik/fabrik_solver.js +3 -4
- package/dist/animation/ik/fabrik_solver.js.map +1 -1
- package/dist/animation/ik/ik_pole_constraint.js +7 -2
- package/dist/animation/ik/ik_pole_constraint.js.map +1 -1
- package/dist/animation/ik/ik_utils.js +0 -79
- package/dist/animation/ik/ik_utils.js.map +1 -1
- package/dist/animation/ik/two_bone_ik_solver.js +3 -4
- package/dist/animation/ik/two_bone_ik_solver.js.map +1 -1
- package/dist/animation/spring/spring_bone.js +240 -0
- package/dist/animation/spring/spring_bone.js.map +1 -0
- package/dist/animation/spring/spring_bone_collider.js +198 -0
- package/dist/animation/spring/spring_bone_collider.js.map +1 -0
- package/dist/animation/spring/spring_bone_constraint.js +170 -0
- package/dist/animation/spring/spring_bone_constraint.js.map +1 -0
- package/dist/animation/spring/spring_bone_system.js +328 -0
- package/dist/animation/spring/spring_bone_system.js.map +1 -0
- package/dist/asset/model.js +2 -2
- package/dist/index.d.ts +15 -0
- package/dist/material/mixins/pbr/common.js +20 -17
- package/dist/material/mixins/pbr/common.js.map +1 -1
- package/dist/render/gpu_picking.js +100 -0
- package/dist/render/gpu_picking.js.map +1 -0
- package/dist/render/rendergraph/device_pool_allocator.js +41 -0
- package/dist/render/rendergraph/device_pool_allocator.js.map +1 -0
- package/dist/render/rendergraph/executor.js +146 -0
- package/dist/render/rendergraph/executor.js.map +1 -0
- package/dist/render/rendergraph/forward_plus_builder.js +414 -0
- package/dist/render/rendergraph/forward_plus_builder.js.map +1 -0
- package/dist/render/rendergraph/rendergraph.js +306 -0
- package/dist/render/rendergraph/rendergraph.js.map +1 -0
- package/dist/render/rendergraph/types.js +57 -0
- package/dist/render/rendergraph/types.js.map +1 -0
- package/dist/render/sky_motion_vector.js +85 -0
- package/dist/render/sky_motion_vector.js.map +1 -0
- package/dist/utility/serialization/scene/animation.js +3 -3
- package/dist/utility/serialization/scene/node.js +1 -1
- package/package.json +2 -2
- package/dist/animation/ik/ik_chain_builder.js +0 -68
- package/dist/animation/ik/ik_chain_builder.js.map +0 -1
- package/dist/node_modules/@zephyr3d/runtime/dist/runtime/runtimemgr.js +0 -38
- package/dist/node_modules/@zephyr3d/runtime/dist/runtime/runtimemgr.js.map +0 -1
- package/dist/node_modules/@zephyr3d/runtime/dist/runtime/runtimescript.js +0 -10
- package/dist/node_modules/@zephyr3d/runtime/dist/runtime/runtimescript.js.map +0 -1
- package/dist/node_modules/@zephyr3d/runtime/dist/runtime/scriptingsystem.js +0 -127
- package/dist/node_modules/@zephyr3d/runtime/dist/runtime/scriptingsystem.js.map +0 -1
- package/dist/node_modules/@zephyr3d/runtime/dist/runtime/scriptregistry.js +0 -263
- package/dist/node_modules/@zephyr3d/runtime/dist/runtime/scriptregistry.js.map +0 -1
- package/dist/src/animation/animation.js +0 -127
- package/dist/src/animation/animation.js.map +0 -1
- package/dist/src/animation/animationset.js +0 -255
- package/dist/src/animation/animationset.js.map +0 -1
- package/dist/src/animation/animationtrack.js +0 -34
- package/dist/src/animation/animationtrack.js.map +0 -1
- package/dist/src/animation/eulerrotationtrack.js +0 -52
- package/dist/src/animation/eulerrotationtrack.js.map +0 -1
- package/dist/src/animation/morphtarget.js +0 -93
- package/dist/src/animation/morphtarget.js.map +0 -1
- package/dist/src/animation/morphtrack.js +0 -70
- package/dist/src/animation/morphtrack.js.map +0 -1
- package/dist/src/animation/proptrack.js +0 -161
- package/dist/src/animation/proptrack.js.map +0 -1
- package/dist/src/animation/rotationtrack.js +0 -51
- package/dist/src/animation/rotationtrack.js.map +0 -1
- package/dist/src/animation/scaletrack.js +0 -50
- package/dist/src/animation/scaletrack.js.map +0 -1
- package/dist/src/animation/skeleton.js +0 -204
- package/dist/src/animation/skeleton.js.map +0 -1
- package/dist/src/animation/translationtrack.js +0 -50
- package/dist/src/animation/translationtrack.js.map +0 -1
- package/dist/src/app/app.js +0 -129
- package/dist/src/app/app.js.map +0 -1
- package/dist/src/app/inputmgr.js +0 -267
- package/dist/src/app/inputmgr.js.map +0 -1
- package/dist/src/asset/assetmanager.js +0 -404
- package/dist/src/asset/assetmanager.js.map +0 -1
- package/dist/src/asset/builtin.js +0 -337
- package/dist/src/asset/builtin.js.map +0 -1
- package/dist/src/asset/loaders/dds/dds.js +0 -470
- package/dist/src/asset/loaders/dds/dds.js.map +0 -1
- package/dist/src/asset/loaders/dds/dds_loader.js +0 -28
- package/dist/src/asset/loaders/dds/dds_loader.js.map +0 -1
- package/dist/src/asset/loaders/gltf/gltf_loader.js +0 -1265
- package/dist/src/asset/loaders/gltf/gltf_loader.js.map +0 -1
- package/dist/src/asset/loaders/gltf/helpers.js +0 -327
- package/dist/src/asset/loaders/gltf/helpers.js.map +0 -1
- package/dist/src/asset/loaders/hdr/hdr.js +0 -180
- package/dist/src/asset/loaders/hdr/hdr.js.map +0 -1
- package/dist/src/asset/loaders/image/tga_Loader.js +0 -116
- package/dist/src/asset/loaders/image/tga_Loader.js.map +0 -1
- package/dist/src/asset/loaders/image/webimage_loader.js +0 -63
- package/dist/src/asset/loaders/image/webimage_loader.js.map +0 -1
- package/dist/src/asset/loaders/loader.js +0 -45
- package/dist/src/asset/loaders/loader.js.map +0 -1
- package/dist/src/asset/model.js +0 -414
- package/dist/src/asset/model.js.map +0 -1
- package/dist/src/blitter/bilateralblur.js +0 -221
- package/dist/src/blitter/bilateralblur.js.map +0 -1
- package/dist/src/blitter/blitter.js +0 -390
- package/dist/src/blitter/blitter.js.map +0 -1
- package/dist/src/blitter/box.js +0 -118
- package/dist/src/blitter/box.js.map +0 -1
- package/dist/src/blitter/copy.js +0 -22
- package/dist/src/blitter/copy.js.map +0 -1
- package/dist/src/blitter/gaussianblur.js +0 -228
- package/dist/src/blitter/gaussianblur.js.map +0 -1
- package/dist/src/camera/base.js +0 -92
- package/dist/src/camera/base.js.map +0 -1
- package/dist/src/camera/camera.js +0 -1005
- package/dist/src/camera/camera.js.map +0 -1
- package/dist/src/camera/fps.js +0 -238
- package/dist/src/camera/fps.js.map +0 -1
- package/dist/src/camera/orbit.js +0 -245
- package/dist/src/camera/orbit.js.map +0 -1
- package/dist/src/camera/orthocamera.js +0 -167
- package/dist/src/camera/orthocamera.js.map +0 -1
- package/dist/src/camera/perspectivecamera.js +0 -141
- package/dist/src/camera/perspectivecamera.js.map +0 -1
- package/dist/src/index.js +0 -120
- package/dist/src/index.js.map +0 -1
- package/dist/src/material/blinn.js +0 -81
- package/dist/src/material/blinn.js.map +0 -1
- package/dist/src/material/grassmaterial.js +0 -113
- package/dist/src/material/grassmaterial.js.map +0 -1
- package/dist/src/material/lambert.js +0 -92
- package/dist/src/material/lambert.js.map +0 -1
- package/dist/src/material/material.js +0 -301
- package/dist/src/material/material.js.map +0 -1
- package/dist/src/material/meshmaterial.js +0 -704
- package/dist/src/material/meshmaterial.js.map +0 -1
- package/dist/src/material/mixins/albedocolor.js +0 -76
- package/dist/src/material/mixins/albedocolor.js.map +0 -1
- package/dist/src/material/mixins/foliage.js +0 -47
- package/dist/src/material/mixins/foliage.js.map +0 -1
- package/dist/src/material/mixins/lightmodel/blinnphong.js +0 -112
- package/dist/src/material/mixins/lightmodel/blinnphong.js.map +0 -1
- package/dist/src/material/mixins/lightmodel/lambert.js +0 -58
- package/dist/src/material/mixins/lightmodel/lambert.js.map +0 -1
- package/dist/src/material/mixins/lightmodel/pbrmetallicroughness.js +0 -178
- package/dist/src/material/mixins/lightmodel/pbrmetallicroughness.js.map +0 -1
- package/dist/src/material/mixins/lightmodel/pbrspecularglossness.js +0 -139
- package/dist/src/material/mixins/lightmodel/pbrspecularglossness.js.map +0 -1
- package/dist/src/material/mixins/lit.js +0 -476
- package/dist/src/material/mixins/lit.js.map +0 -1
- package/dist/src/material/mixins/pbr/common.js +0 -918
- package/dist/src/material/mixins/pbr/common.js.map +0 -1
- package/dist/src/material/mixins/texture.js +0 -172
- package/dist/src/material/mixins/texture.js.map +0 -1
- package/dist/src/material/mixins/vertexcolor.js +0 -56
- package/dist/src/material/mixins/vertexcolor.js.map +0 -1
- package/dist/src/material/particle.js +0 -178
- package/dist/src/material/particle.js.map +0 -1
- package/dist/src/material/pbrmr.js +0 -97
- package/dist/src/material/pbrmr.js.map +0 -1
- package/dist/src/material/pbrsg.js +0 -97
- package/dist/src/material/pbrsg.js.map +0 -1
- package/dist/src/material/shader/helper.js +0 -1209
- package/dist/src/material/shader/helper.js.map +0 -1
- package/dist/src/material/terrain-cm.js +0 -606
- package/dist/src/material/terrain-cm.js.map +0 -1
- package/dist/src/material/terrainmaterial.js +0 -375
- package/dist/src/material/terrainmaterial.js.map +0 -1
- package/dist/src/material/unlit.js +0 -41
- package/dist/src/material/unlit.js.map +0 -1
- package/dist/src/material/water.js +0 -417
- package/dist/src/material/water.js.map +0 -1
- package/dist/src/posteffect/bloom.js +0 -361
- package/dist/src/posteffect/bloom.js.map +0 -1
- package/dist/src/posteffect/compositor.js +0 -226
- package/dist/src/posteffect/compositor.js.map +0 -1
- package/dist/src/posteffect/fxaa.js +0 -273
- package/dist/src/posteffect/fxaa.js.map +0 -1
- package/dist/src/posteffect/grayscale.js +0 -69
- package/dist/src/posteffect/grayscale.js.map +0 -1
- package/dist/src/posteffect/motionblur.js +0 -96
- package/dist/src/posteffect/motionblur.js.map +0 -1
- package/dist/src/posteffect/posteffect.js +0 -126
- package/dist/src/posteffect/posteffect.js.map +0 -1
- package/dist/src/posteffect/sao.js +0 -324
- package/dist/src/posteffect/sao.js.map +0 -1
- package/dist/src/posteffect/ssr.js +0 -489
- package/dist/src/posteffect/ssr.js.map +0 -1
- package/dist/src/posteffect/taa.js +0 -172
- package/dist/src/posteffect/taa.js.map +0 -1
- package/dist/src/posteffect/tonemap.js +0 -94
- package/dist/src/posteffect/tonemap.js.map +0 -1
- package/dist/src/render/abuffer_oit.js +0 -361
- package/dist/src/render/abuffer_oit.js.map +0 -1
- package/dist/src/render/clipmap.js +0 -851
- package/dist/src/render/clipmap.js.map +0 -1
- package/dist/src/render/cluster_light.js +0 -333
- package/dist/src/render/cluster_light.js.map +0 -1
- package/dist/src/render/cull_visitor.js +0 -187
- package/dist/src/render/cull_visitor.js.map +0 -1
- package/dist/src/render/depthpass.js +0 -68
- package/dist/src/render/depthpass.js.map +0 -1
- package/dist/src/render/drawable_mixin.js +0 -227
- package/dist/src/render/drawable_mixin.js.map +0 -1
- package/dist/src/render/envlight.js +0 -463
- package/dist/src/render/envlight.js.map +0 -1
- package/dist/src/render/fbm_wavegenerator.js +0 -251
- package/dist/src/render/fbm_wavegenerator.js.map +0 -1
- package/dist/src/render/fft_wavegenerator.js +0 -1006
- package/dist/src/render/fft_wavegenerator.js.map +0 -1
- package/dist/src/render/fullscreenquad.js +0 -38
- package/dist/src/render/fullscreenquad.js.map +0 -1
- package/dist/src/render/gerstner_wavegenerator.js +0 -314
- package/dist/src/render/gerstner_wavegenerator.js.map +0 -1
- package/dist/src/render/globalbindgroup_allocator.js +0 -60
- package/dist/src/render/globalbindgroup_allocator.js.map +0 -1
- package/dist/src/render/hzb.js +0 -273
- package/dist/src/render/hzb.js.map +0 -1
- package/dist/src/render/lightpass.js +0 -172
- package/dist/src/render/lightpass.js.map +0 -1
- package/dist/src/render/objectcolorpass.js +0 -51
- package/dist/src/render/objectcolorpass.js.map +0 -1
- package/dist/src/render/primitive.js +0 -364
- package/dist/src/render/primitive.js.map +0 -1
- package/dist/src/render/render_queue.js +0 -467
- package/dist/src/render/render_queue.js.map +0 -1
- package/dist/src/render/renderbundle_wrapper.js +0 -152
- package/dist/src/render/renderbundle_wrapper.js.map +0 -1
- package/dist/src/render/renderer.js +0 -455
- package/dist/src/render/renderer.js.map +0 -1
- package/dist/src/render/renderpass.js +0 -200
- package/dist/src/render/renderpass.js.map +0 -1
- package/dist/src/render/shadowmap_pass.js +0 -56
- package/dist/src/render/shadowmap_pass.js.map +0 -1
- package/dist/src/render/sky.js +0 -1103
- package/dist/src/render/sky.js.map +0 -1
- package/dist/src/render/weightedblended_oit.js +0 -168
- package/dist/src/render/weightedblended_oit.js.map +0 -1
- package/dist/src/scene/batchgroup.js +0 -162
- package/dist/src/scene/batchgroup.js.map +0 -1
- package/dist/src/scene/environment.js +0 -209
- package/dist/src/scene/environment.js.map +0 -1
- package/dist/src/scene/graph_node.js +0 -72
- package/dist/src/scene/graph_node.js.map +0 -1
- package/dist/src/scene/light.js +0 -416
- package/dist/src/scene/light.js.map +0 -1
- package/dist/src/scene/mesh.js +0 -341
- package/dist/src/scene/mesh.js.map +0 -1
- package/dist/src/scene/octree.js +0 -649
- package/dist/src/scene/octree.js.map +0 -1
- package/dist/src/scene/particlesys.js +0 -738
- package/dist/src/scene/particlesys.js.map +0 -1
- package/dist/src/scene/raycast_visitor.js +0 -103
- package/dist/src/scene/raycast_visitor.js.map +0 -1
- package/dist/src/scene/scene.js +0 -284
- package/dist/src/scene/scene.js.map +0 -1
- package/dist/src/scene/scene_node.js +0 -732
- package/dist/src/scene/scene_node.js.map +0 -1
- package/dist/src/scene/terrain/grass.js +0 -278
- package/dist/src/scene/terrain/grass.js.map +0 -1
- package/dist/src/scene/terrain/heightfield.js +0 -475
- package/dist/src/scene/terrain/heightfield.js.map +0 -1
- package/dist/src/scene/terrain/patch.js +0 -530
- package/dist/src/scene/terrain/patch.js.map +0 -1
- package/dist/src/scene/terrain/quadtree.js +0 -461
- package/dist/src/scene/terrain/quadtree.js.map +0 -1
- package/dist/src/scene/terrain/terrain.js +0 -246
- package/dist/src/scene/terrain/terrain.js.map +0 -1
- package/dist/src/scene/terrain-cm/grass.js +0 -594
- package/dist/src/scene/terrain-cm/grass.js.map +0 -1
- package/dist/src/scene/terrain-cm/grassmaterial.js +0 -159
- package/dist/src/scene/terrain-cm/grassmaterial.js.map +0 -1
- package/dist/src/scene/terrain-cm/terrain-cm.js +0 -538
- package/dist/src/scene/terrain-cm/terrain-cm.js.map +0 -1
- package/dist/src/scene/water.js +0 -374
- package/dist/src/scene/water.js.map +0 -1
- package/dist/src/shaders/atmosphere.js +0 -957
- package/dist/src/shaders/atmosphere.js.map +0 -1
- package/dist/src/shaders/fog.js +0 -112
- package/dist/src/shaders/fog.js.map +0 -1
- package/dist/src/shaders/misc.js +0 -266
- package/dist/src/shaders/misc.js.map +0 -1
- package/dist/src/shaders/noise.js +0 -222
- package/dist/src/shaders/noise.js.map +0 -1
- package/dist/src/shaders/pbr.js +0 -51
- package/dist/src/shaders/pbr.js.map +0 -1
- package/dist/src/shaders/shadow.js +0 -636
- package/dist/src/shaders/shadow.js.map +0 -1
- package/dist/src/shaders/ssr.js +0 -490
- package/dist/src/shaders/ssr.js.map +0 -1
- package/dist/src/shaders/temporal.js +0 -215
- package/dist/src/shaders/temporal.js.map +0 -1
- package/dist/src/shaders/water.js +0 -756
- package/dist/src/shaders/water.js.map +0 -1
- package/dist/src/shadow/esm.js +0 -237
- package/dist/src/shadow/esm.js.map +0 -1
- package/dist/src/shadow/pcf_opt.js +0 -181
- package/dist/src/shadow/pcf_opt.js.map +0 -1
- package/dist/src/shadow/pcf_pd.js +0 -189
- package/dist/src/shadow/pcf_pd.js.map +0 -1
- package/dist/src/shadow/shader.js +0 -37
- package/dist/src/shadow/shader.js.map +0 -1
- package/dist/src/shadow/shadow_impl.js +0 -15
- package/dist/src/shadow/shadow_impl.js.map +0 -1
- package/dist/src/shadow/shadowmapper.js +0 -790
- package/dist/src/shadow/shadowmapper.js.map +0 -1
- package/dist/src/shadow/ssm.js +0 -159
- package/dist/src/shadow/ssm.js.map +0 -1
- package/dist/src/shadow/vsm.js +0 -297
- package/dist/src/shadow/vsm.js.map +0 -1
- package/dist/src/shapes/box.js +0 -386
- package/dist/src/shapes/box.js.map +0 -1
- package/dist/src/shapes/cylinder.js +0 -125
- package/dist/src/shapes/cylinder.js.map +0 -1
- package/dist/src/shapes/plane.js +0 -88
- package/dist/src/shapes/plane.js.map +0 -1
- package/dist/src/shapes/shape.js +0 -87
- package/dist/src/shapes/shape.js.map +0 -1
- package/dist/src/shapes/sphere.js +0 -114
- package/dist/src/shapes/sphere.js.map +0 -1
- package/dist/src/shapes/tetrahedron.js +0 -188
- package/dist/src/shapes/tetrahedron.js.map +0 -1
- package/dist/src/shapes/torus.js +0 -111
- package/dist/src/shapes/torus.js.map +0 -1
- package/dist/src/utility/aabbtree.js +0 -400
- package/dist/src/utility/aabbtree.js.map +0 -1
- package/dist/src/utility/bounding_volume.js +0 -29
- package/dist/src/utility/bounding_volume.js.map +0 -1
- package/dist/src/utility/debug.js +0 -28
- package/dist/src/utility/debug.js.map +0 -1
- package/dist/src/utility/draco/decoder.js +0 -116
- package/dist/src/utility/draco/decoder.js.map +0 -1
- package/dist/src/utility/misc.js +0 -105
- package/dist/src/utility/misc.js.map +0 -1
- package/dist/src/utility/panorama.js +0 -163
- package/dist/src/utility/panorama.js.map +0 -1
- package/dist/src/utility/pmrem.js +0 -354
- package/dist/src/utility/pmrem.js.map +0 -1
- package/dist/src/utility/rendermipmap.js +0 -115
- package/dist/src/utility/rendermipmap.js.map +0 -1
- package/dist/src/utility/serialization/json.js +0 -402
- package/dist/src/utility/serialization/json.js.map +0 -1
- package/dist/src/utility/serialization/manager.js +0 -623
- package/dist/src/utility/serialization/manager.js.map +0 -1
- package/dist/src/utility/serialization/scene/animation.js +0 -248
- package/dist/src/utility/serialization/scene/animation.js.map +0 -1
- package/dist/src/utility/serialization/scene/batch.js +0 -59
- package/dist/src/utility/serialization/scene/batch.js.map +0 -1
- package/dist/src/utility/serialization/scene/camera.js +0 -790
- package/dist/src/utility/serialization/scene/camera.js.map +0 -1
- package/dist/src/utility/serialization/scene/common.js +0 -222
- package/dist/src/utility/serialization/scene/common.js.map +0 -1
- package/dist/src/utility/serialization/scene/light.js +0 -575
- package/dist/src/utility/serialization/scene/light.js.map +0 -1
- package/dist/src/utility/serialization/scene/material.js +0 -1111
- package/dist/src/utility/serialization/scene/material.js.map +0 -1
- package/dist/src/utility/serialization/scene/mesh.js +0 -148
- package/dist/src/utility/serialization/scene/mesh.js.map +0 -1
- package/dist/src/utility/serialization/scene/misc.js +0 -39
- package/dist/src/utility/serialization/scene/misc.js.map +0 -1
- package/dist/src/utility/serialization/scene/node.js +0 -451
- package/dist/src/utility/serialization/scene/node.js.map +0 -1
- package/dist/src/utility/serialization/scene/particle.js +0 -425
- package/dist/src/utility/serialization/scene/particle.js.map +0 -1
- package/dist/src/utility/serialization/scene/primitive.js +0 -692
- package/dist/src/utility/serialization/scene/primitive.js.map +0 -1
- package/dist/src/utility/serialization/scene/scene.js +0 -704
- package/dist/src/utility/serialization/scene/scene.js.map +0 -1
- package/dist/src/utility/serialization/scene/terrain.js +0 -488
- package/dist/src/utility/serialization/scene/terrain.js.map +0 -1
- package/dist/src/utility/serialization/scene/water.js +0 -465
- package/dist/src/utility/serialization/scene/water.js.map +0 -1
- package/dist/src/utility/shprojector.js +0 -297
- package/dist/src/utility/shprojector.js.map +0 -1
- package/dist/src/utility/textures/ggxlut.js +0 -213
- package/dist/src/utility/textures/ggxlut.js.map +0 -1
- package/dist/src/utility/textures/gradientnoise.js +0 -62
- package/dist/src/utility/textures/gradientnoise.js.map +0 -1
- package/dist/src/utility/textures/randomnoise.js +0 -41
- package/dist/src/utility/textures/randomnoise.js.map +0 -1
- package/dist/src/values.js +0 -162
- package/dist/src/values.js.map +0 -1
- package/dist/utility/blueprint/material/common.js +0 -7
- package/dist/utility/blueprint/material/common.js.map +0 -1
- package/dist/utility/serialization/blueprint/constants.js +0 -255
- package/dist/utility/serialization/blueprint/constants.js.map +0 -1
- package/dist/utility/serialization/blueprint/material/constants.js +0 -203
- package/dist/utility/serialization/blueprint/material/constants.js.map +0 -1
- package/dist/utility/serialization/blueprint/material/texture.js +0 -165
- package/dist/utility/serialization/blueprint/material/texture.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fabrik_solver.js","sources":["../../../src/animation/ik/fabrik_solver.ts"],"sourcesContent":["import { Vector3, Quaternion } from '@zephyr3d/base';\r\nimport { IKSolver } from './ik_solver';\r\nimport type { IKChain } from './ik_chain';\r\nimport { IKUtils } from './ik_utils';\r\nimport type { TwistConstraint } from './ik_constraint';\r\n\r\n/**\r\n * Pole vector configuration for a specific joint.\r\n */\r\ninterface PoleVectorConfig {\r\n /** Pole vector position in world space */\r\n position: Vector3;\r\n /** Weight of the pole vector constraint (0-1) */\r\n weight: number;\r\n}\r\n\r\n/**\r\n * FABRIK (Forward And Backward Reaching Inverse Kinematics) solver.\r\n *\r\n * @remarks\r\n * FABRIK is an iterative IK algorithm that alternates between:\r\n * 1. Forward pass: Move from end effector to root, pulling joints toward target\r\n * 2. Backward pass: Move from root to end effector, restoring root position\r\n *\r\n * Supports multiple pole vectors to control the bending direction of different joints.\r\n *\r\n * @public\r\n */\r\nexport class FABRIKSolver extends IKSolver {\r\n /** Map of joint index to pole vector configuration */\r\n private _poleVectors: Map<number, PoleVectorConfig>;\r\n /** Twist constraints for each joint (indexed by joint index) */\r\n private _twistConstraints: Map<number, TwistConstraint>;\r\n\r\n /**\r\n * Create a FABRIK solver.\r\n *\r\n * @param chain - The IK chain to solve\r\n * @param maxIterations - Maximum number of iterations (default: 15)\r\n * @param tolerance - Convergence tolerance in world units (default: 0.001)\r\n */\r\n constructor(chain: IKChain, maxIterations = 15, tolerance = 0.001) {\r\n super(chain, maxIterations, tolerance);\r\n this._poleVectors = new Map();\r\n this._twistConstraints = new Map();\r\n\r\n // Set default twist constraints for all joints\r\n for (let i = 0; i < chain.joints.length - 1; i++) {\r\n // Middle joints have more restrictive twist limits\r\n const isMiddleJoint = i > 0 && i < chain.joints.length - 2;\r\n this._twistConstraints.set(i, {\r\n minTwist: isMiddleJoint ? -Math.PI * 0.2 : -Math.PI * 0.3,\r\n maxTwist: isMiddleJoint ? Math.PI * 0.2 : Math.PI * 0.3,\r\n smoothFactor: 0.3\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Set twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @param minTwist - Minimum twist angle in radians\r\n * @param maxTwist - Maximum twist angle in radians\r\n * @param smoothFactor - Smoothing factor [0-1] (default: 0.3)\r\n */\r\n setTwistConstraint(\r\n jointIndex: number,\r\n minTwist: number,\r\n maxTwist: number,\r\n smoothFactor: number = 0.3\r\n ): void {\r\n if (jointIndex < 0 || jointIndex >= this._chain.joints.length - 1) {\r\n throw new Error(`Invalid joint index: ${jointIndex}`);\r\n }\r\n\r\n this._twistConstraints.set(jointIndex, {\r\n minTwist,\r\n maxTwist,\r\n smoothFactor: Math.max(0, Math.min(1, smoothFactor))\r\n });\r\n }\r\n\r\n /**\r\n * Get twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns Twist constraint or undefined if not set\r\n */\r\n getTwistConstraint(jointIndex: number): TwistConstraint | undefined {\r\n return this._twistConstraints.get(jointIndex);\r\n }\r\n\r\n /**\r\n * Remove twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns True if a constraint was removed\r\n */\r\n removeTwistConstraint(jointIndex: number): boolean {\r\n return this._twistConstraints.delete(jointIndex);\r\n }\r\n\r\n /**\r\n * Clear all twist constraints.\r\n */\r\n clearTwistConstraints(): void {\r\n this._twistConstraints.clear();\r\n }\r\n\r\n /**\r\n * Set pole vector for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint to apply pole vector to\r\n * @param poleVector - Pole vector position in world space\r\n * @param weight - Weight of the pole vector constraint (0-1, default: 1)\r\n */\r\n setPoleVector(jointIndex: number, poleVector: Vector3, weight = 1): void {\r\n if (jointIndex < 0 || jointIndex >= this._chain.joints.length) {\r\n throw new Error(`Invalid joint index: ${jointIndex}`);\r\n }\r\n\r\n this._poleVectors.set(jointIndex, {\r\n position: poleVector.clone(),\r\n weight: Math.max(0, Math.min(1, weight))\r\n });\r\n }\r\n\r\n /**\r\n * Remove pole vector for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint to remove pole vector from\r\n * @returns True if a pole vector was removed, false if none existed\r\n */\r\n removePoleVector(jointIndex: number): boolean {\r\n return this._poleVectors.delete(jointIndex);\r\n }\r\n\r\n /**\r\n * Clear all pole vectors.\r\n */\r\n clearPoleVectors(): void {\r\n this._poleVectors.clear();\r\n }\r\n\r\n /**\r\n * Get pole vector configuration for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns Pole vector configuration or undefined if not set\r\n */\r\n getPoleVector(jointIndex: number): { position: Vector3; weight: number } | undefined {\r\n const config = this._poleVectors.get(jointIndex);\r\n if (config) {\r\n return {\r\n position: config.position.clone(),\r\n weight: config.weight\r\n };\r\n }\r\n return undefined;\r\n }\r\n\r\n /**\r\n * Check if a joint has a pole vector.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns True if the joint has a pole vector\r\n */\r\n hasPoleVector(jointIndex: number): boolean {\r\n return this._poleVectors.has(jointIndex);\r\n }\r\n\r\n /**\r\n * Solve the IK chain to reach the target position using FABRIK algorithm.\r\n *\r\n * @param target - Target position for the end effector\r\n * @returns True if converged within tolerance, false otherwise\r\n */\r\n solve(target: Vector3): boolean {\r\n const joints = this._chain.joints;\r\n\r\n // Update joint positions from scene nodes before solving\r\n this._chain.updateFromNodes();\r\n\r\n // Store original positions\r\n this._chain.storeOriginalPositions();\r\n\r\n const rootPos = joints[0].originalPosition.clone();\r\n\r\n // Check if target is reachable\r\n const distToTarget = Vector3.distance(rootPos, target);\r\n if (distToTarget > this._chain.totalLength) {\r\n // Target unreachable - stretch chain toward target\r\n this._stretchToward(target);\r\n return false;\r\n }\r\n\r\n let converged = false;\r\n for (let iteration = 0; iteration < this._maxIterations; iteration++) {\r\n // Check convergence\r\n const distToEnd = Vector3.distance(joints[joints.length - 1].position, target);\r\n if (distToEnd < this._tolerance) {\r\n converged = true;\r\n break;\r\n }\r\n\r\n // Forward pass: end effector to root\r\n this._forwardPass(target);\r\n\r\n // Backward pass: root to end effector (constraints are applied within the pass)\r\n this._backwardPass(rootPos);\r\n }\r\n\r\n return converged;\r\n }\r\n\r\n /**\r\n * Apply the solved joint positions to scene nodes as rotations.\r\n *\r\n * @param weight - Blend weight (0 = original, 1 = full IK, default: 1)\r\n */\r\n applyToNodes(weight = 1): void {\r\n const joints = this._chain.joints;\r\n\r\n for (let i = 0; i < joints.length - 1; i++) {\r\n const joint = joints[i];\r\n const nextJoint = joints[i + 1];\r\n\r\n // Calculate direction from current joint to next joint in world space\r\n const originalDir = Vector3.sub(nextJoint.originalPosition, joint.originalPosition, new Vector3());\r\n const newDir = Vector3.sub(nextJoint.position, joint.position, new Vector3());\r\n\r\n const originalDirNorm = Vector3.normalize(originalDir, new Vector3());\r\n const newDirNorm = Vector3.normalize(newDir, new Vector3());\r\n\r\n // Calculate basic rotation\r\n const deltaRotation = new Quaternion();\r\n IKUtils.fromToRotation(originalDirNorm, newDirNorm, deltaRotation);\r\n\r\n // Calculate new world rotation\r\n let worldRotation = Quaternion.multiply(deltaRotation, joint.originalRotation, new Quaternion());\r\n\r\n // Apply swing-twist constraint to prevent over-rotation\r\n const swing = new Quaternion();\r\n const twist = new Quaternion();\r\n IKUtils.decomposeSwingTwist(worldRotation, newDirNorm, swing, twist);\r\n\r\n // Get twist angle\r\n let twistAngle = IKUtils.getTwistAngle(twist, newDirNorm);\r\n\r\n // Get twist constraint for this joint\r\n const constraint = this._twistConstraints.get(i);\r\n if (constraint) {\r\n // Clamp and smooth twist\r\n twistAngle = IKUtils.clampAndSmoothTwist(\r\n twistAngle,\r\n joint.previousTwist,\r\n constraint.minTwist,\r\n constraint.maxTwist,\r\n constraint.smoothFactor\r\n );\r\n }\r\n\r\n // Store for next frame\r\n joint.previousTwist = twistAngle;\r\n\r\n // Reconstruct rotation from clamped twist: Q = Twist * Swing\r\n const clampedTwist = new Quaternion();\r\n IKUtils.createTwist(twistAngle, newDirNorm, clampedTwist);\r\n worldRotation = Quaternion.multiply(clampedTwist, swing, worldRotation);\r\n\r\n // Blend with original rotation based on weight\r\n if (weight < 1) {\r\n Quaternion.slerp(joint.originalRotation, worldRotation, weight, worldRotation);\r\n }\r\n\r\n // Store this frame's world rotation\r\n if (!joint.previousIKRotation) {\r\n joint.previousIKRotation = worldRotation.clone();\r\n } else {\r\n joint.previousIKRotation.set(worldRotation);\r\n }\r\n\r\n // Convert world rotation to local rotation (relative to parent)\r\n if (joint.node.parent) {\r\n const parentWorldRotation = new Quaternion();\r\n joint.node.parent.worldMatrix.decompose(null, parentWorldRotation, null);\r\n\r\n // localRotation = conjugate(parentWorldRotation) * worldRotation\r\n const parentInvRotation = Quaternion.conjugate(parentWorldRotation, new Quaternion());\r\n const localRotation = Quaternion.multiply(parentInvRotation, worldRotation, new Quaternion());\r\n\r\n joint.node.rotation = localRotation;\r\n } else {\r\n // Root node has no parent, world rotation is local rotation\r\n joint.node.rotation = worldRotation;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Forward pass: move from end effector toward root.\r\n * Each joint is pulled toward its child, maintaining bone length.\r\n * Constraints are applied immediately after each joint adjustment.\r\n *\r\n * @param target - Target position for end effector\r\n */\r\n private _forwardPass(target: Vector3): void {\r\n const joints = this._chain.joints;\r\n\r\n // Set end effector to target\r\n joints[joints.length - 1].position.set(target);\r\n\r\n // Move backward through chain\r\n for (let i = joints.length - 2; i >= 0; i--) {\r\n const joint = joints[i];\r\n const childJoint = joints[i + 1];\r\n\r\n // Calculate direction from child to current joint\r\n const direction = Vector3.sub(joint.position, childJoint.position, new Vector3());\r\n const distance = direction.magnitude;\r\n\r\n if (distance > 0.000001) {\r\n direction.scaleBy(1 / distance);\r\n // Place joint at correct distance from child\r\n Vector3.scale(direction, joint.boneLength, direction);\r\n Vector3.add(childJoint.position, direction, joint.position);\r\n }\r\n\r\n // Apply constraints immediately after adjusting this joint\r\n // This ensures constraints are integrated into the FABRIK algorithm\r\n if (i > 0) {\r\n // Apply constraints for joint i (not for root joint)\r\n this._applyConstraintsForJoint(i);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Backward pass: move from root toward end effector.\r\n * Each joint is pulled toward its parent, maintaining bone length.\r\n * Constraints are applied immediately after each joint adjustment.\r\n *\r\n * @param rootPos - Original root position to restore\r\n */\r\n private _backwardPass(rootPos: Vector3): void {\r\n const joints = this._chain.joints;\r\n\r\n // Restore root position\r\n joints[0].position.set(rootPos);\r\n\r\n // Move forward through chain\r\n for (let i = 0; i < joints.length - 1; i++) {\r\n const joint = joints[i];\r\n const childJoint = joints[i + 1];\r\n\r\n // Calculate direction from current joint to child\r\n const direction = Vector3.sub(childJoint.position, joint.position, new Vector3());\r\n const distance = direction.magnitude;\r\n\r\n if (distance > 0.000001) {\r\n direction.scaleBy(1 / distance);\r\n // Place child at correct distance from current joint\r\n Vector3.scale(direction, joint.boneLength, direction);\r\n Vector3.add(joint.position, direction, childJoint.position);\r\n }\r\n\r\n // Apply constraints immediately after adjusting this joint\r\n // This ensures constraints are integrated into the FABRIK algorithm\r\n this._applyConstraintsForJoint(i + 1);\r\n }\r\n }\r\n\r\n /**\r\n * Apply constraints for a specific joint.\r\n * This is called during the FABRIK passes to integrate constraints into the algorithm.\r\n *\r\n * @param jointIndex - Index of the joint to apply constraints to\r\n */\r\n private _applyConstraintsForJoint(jointIndex: number): void {\r\n const constraints = this._chain.constraints;\r\n\r\n // Apply non-pole-vector constraints\r\n // IKPoleVectorConstraint is deprecated and ignored in favor of built-in pole vectors\r\n for (const constraint of constraints) {\r\n if (constraint.jointIndex === jointIndex) {\r\n // Skip IKPoleVectorConstraint - use built-in pole vectors instead\r\n if (constraint.constructor.name === 'IKPoleVectorConstraint') {\r\n continue;\r\n }\r\n constraint.apply(this._chain.joints);\r\n }\r\n }\r\n\r\n // Apply built-in pole vector if configured for this joint\r\n const poleConfig = this._poleVectors.get(jointIndex);\r\n if (poleConfig && poleConfig.weight > 0.001) {\r\n this._applyPoleVectorTwist(jointIndex, poleConfig.position, poleConfig.weight);\r\n }\r\n }\r\n\r\n /**\r\n * Apply pole vector twist to a specific joint.\r\n *\r\n * @remarks\r\n * This method adjusts the joint position to align with the pole vector.\r\n * It uses the same algorithm as IKPoleVectorConstraint but is integrated\r\n * into the solver for better performance and control.\r\n *\r\n * @param jointIndex - Index of the pole joint\r\n * @param poleVector - Pole vector position in world space\r\n * @param weight - Weight of the pole vector constraint (0-1)\r\n */\r\n private _applyPoleVectorTwist(jointIndex: number, poleVector: Vector3, weight: number): void {\r\n const joints = this._chain.joints;\r\n\r\n // We need at least 3 joints to apply pole vector (parent, pole joint, child)\r\n if (jointIndex < 1 || jointIndex >= joints.length - 1) {\r\n return;\r\n }\r\n\r\n const parentJoint = joints[jointIndex - 1];\r\n const currentJoint = joints[jointIndex];\r\n const childJoint = joints[jointIndex + 1];\r\n\r\n const parentPos = parentJoint.position;\r\n const currentPos = currentJoint.position;\r\n const childPos = childJoint.position;\r\n\r\n // Calculate the plane defined by parent, child, and pole vector\r\n // Vector from parent to child (the \"line\" we're bending around)\r\n const parentToChild = Vector3.sub(childPos, parentPos, new Vector3());\r\n const lineLength = parentToChild.magnitude;\r\n\r\n if (lineLength < 0.000001) {\r\n return; // Parent and child are at same position\r\n }\r\n\r\n const lineDir = Vector3.scale(parentToChild, 1 / lineLength, new Vector3());\r\n\r\n // Project current joint onto the parent-child line\r\n const parentToCurrent = Vector3.sub(currentPos, parentPos, new Vector3());\r\n const projectionLength = Vector3.dot(parentToCurrent, lineDir);\r\n const projectionPoint = Vector3.scale(lineDir, projectionLength, new Vector3());\r\n Vector3.add(parentPos, projectionPoint, projectionPoint);\r\n\r\n // Vector from projection point to current joint (perpendicular to line)\r\n const perpendicular = Vector3.sub(currentPos, projectionPoint, new Vector3());\r\n const perpLength = perpendicular.magnitude;\r\n\r\n if (perpLength < 0.000001) {\r\n return; // Current joint is on the line\r\n }\r\n\r\n // Calculate desired direction toward pole vector\r\n const parentToPole = Vector3.sub(poleVector, parentPos, new Vector3());\r\n const poleProjectionLength = Vector3.dot(parentToPole, lineDir);\r\n const poleProjectionPoint = Vector3.scale(lineDir, poleProjectionLength, new Vector3());\r\n Vector3.add(parentPos, poleProjectionPoint, poleProjectionPoint);\r\n\r\n // Direction from projection to pole (perpendicular to line)\r\n const poleDirection = Vector3.sub(poleVector, poleProjectionPoint, new Vector3());\r\n const poleDirLength = poleDirection.magnitude;\r\n\r\n if (poleDirLength < 0.000001) {\r\n return; // Pole is on the line\r\n }\r\n\r\n poleDirection.scaleBy(1 / poleDirLength);\r\n\r\n // Calculate new position for current joint\r\n // Keep the same distance from the line, but rotate toward pole direction\r\n const desiredPerpendicular = Vector3.scale(poleDirection, perpLength, new Vector3());\r\n const newPosition = Vector3.add(projectionPoint, desiredPerpendicular, new Vector3());\r\n\r\n // Apply weight (blend between original and constrained position)\r\n if (weight < 0.999) {\r\n const blended = new Vector3();\r\n blended.x = currentPos.x + (newPosition.x - currentPos.x) * weight;\r\n blended.y = currentPos.y + (newPosition.y - currentPos.y) * weight;\r\n blended.z = currentPos.z + (newPosition.z - currentPos.z) * weight;\r\n currentJoint.position.set(blended);\r\n } else {\r\n currentJoint.position.set(newPosition);\r\n }\r\n }\r\n\r\n /**\r\n * Stretch the chain toward an unreachable target.\r\n * All joints are aligned in a straight line toward the target.\r\n *\r\n * @param target - Unreachable target position\r\n */\r\n private _stretchToward(target: Vector3): void {\r\n const joints = this._chain.joints;\r\n const rootPos = joints[0].originalPosition;\r\n\r\n // Calculate direction from root to target\r\n const direction = Vector3.sub(target, rootPos, new Vector3()).inplaceNormalize();\r\n\r\n // Place each joint along the direction at its bone length\r\n let currentPos = rootPos.clone();\r\n for (let i = 0; i < joints.length; i++) {\r\n joints[i].position.set(currentPos);\r\n if (i < joints.length - 1) {\r\n const offset = Vector3.scale(direction, joints[i].boneLength, new Vector3());\r\n currentPos.addBy(offset);\r\n }\r\n }\r\n }\r\n}\r\n"],"names":["FABRIKSolver","IKSolver","chain","maxIterations","tolerance","_poleVectors","Map","_twistConstraints","i","joints","length","isMiddleJoint","set","minTwist","Math","PI","maxTwist","smoothFactor","setTwistConstraint","jointIndex","_chain","Error","max","min","getTwistConstraint","get","removeTwistConstraint","delete","clearTwistConstraints","clear","setPoleVector","poleVector","weight","position","clone","removePoleVector","clearPoleVectors","getPoleVector","config","undefined","hasPoleVector","has","solve","target","updateFromNodes","storeOriginalPositions","rootPos","originalPosition","distToTarget","Vector3","distance","totalLength","_stretchToward","converged","iteration","_maxIterations","distToEnd","_tolerance","_forwardPass","_backwardPass","applyToNodes","joint","nextJoint","originalDir","sub","newDir","originalDirNorm","normalize","newDirNorm","deltaRotation","Quaternion","IKUtils","fromToRotation","worldRotation","multiply","originalRotation","swing","twist","decomposeSwingTwist","twistAngle","getTwistAngle","constraint","clampAndSmoothTwist","previousTwist","clampedTwist","createTwist","slerp","previousIKRotation","node","parent","parentWorldRotation","worldMatrix","decompose","parentInvRotation","conjugate","localRotation","rotation","childJoint","direction","magnitude","scaleBy","scale","boneLength","add","_applyConstraintsForJoint","constraints","name","apply","poleConfig","_applyPoleVectorTwist","parentJoint","currentJoint","parentPos","currentPos","childPos","parentToChild","lineLength","lineDir","parentToCurrent","projectionLength","dot","projectionPoint","perpendicular","perpLength","parentToPole","poleProjectionLength","poleProjectionPoint","poleDirection","poleDirLength","desiredPerpendicular","newPosition","blended","x","y","z","inplaceNormalize","offset","addBy"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fabrik_solver.js","sources":["../../../src/animation/ik/fabrik_solver.ts"],"sourcesContent":["import { Vector3, Quaternion } from '@zephyr3d/base';\r\nimport { IKSolver } from './ik_solver';\r\nimport type { IKChain } from './ik_chain';\r\nimport { IKUtils } from './ik_utils';\r\nimport type { TwistConstraint } from './ik_constraint';\r\n\r\n/**\r\n * Pole vector configuration for a specific joint.\r\n */\r\ninterface PoleVectorConfig {\r\n /** Pole vector position in world space */\r\n position: Vector3;\r\n /** Weight of the pole vector constraint (0-1) */\r\n weight: number;\r\n}\r\n\r\n/**\r\n * FABRIK (Forward And Backward Reaching Inverse Kinematics) solver.\r\n *\r\n * @remarks\r\n * FABRIK is an iterative IK algorithm that alternates between:\r\n * 1. Forward pass: Move from end effector to root, pulling joints toward target\r\n * 2. Backward pass: Move from root to end effector, restoring root position\r\n *\r\n * Supports multiple pole vectors to control the bending direction of different joints.\r\n *\r\n * @public\r\n */\r\nexport class FABRIKSolver extends IKSolver {\r\n /** Map of joint index to pole vector configuration */\r\n private _poleVectors: Map<number, PoleVectorConfig>;\r\n /** Twist constraints for each joint (indexed by joint index) */\r\n private _twistConstraints: Map<number, TwistConstraint>;\r\n\r\n /**\r\n * Create a FABRIK solver.\r\n *\r\n * @param chain - The IK chain to solve\r\n * @param maxIterations - Maximum number of iterations (default: 15)\r\n * @param tolerance - Convergence tolerance in world units (default: 0.001)\r\n */\r\n constructor(chain: IKChain, maxIterations = 15, tolerance = 0.001) {\r\n super(chain, maxIterations, tolerance);\r\n this._poleVectors = new Map();\r\n this._twistConstraints = new Map();\r\n\r\n // Set default twist constraints for all joints\r\n for (let i = 0; i < chain.joints.length - 1; i++) {\r\n // Middle joints have more restrictive twist limits\r\n const isMiddleJoint = i > 0 && i < chain.joints.length - 2;\r\n this._twistConstraints.set(i, {\r\n minTwist: isMiddleJoint ? -Math.PI * 0.2 : -Math.PI * 0.3,\r\n maxTwist: isMiddleJoint ? Math.PI * 0.2 : Math.PI * 0.3,\r\n smoothFactor: 0.3\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Set twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @param minTwist - Minimum twist angle in radians\r\n * @param maxTwist - Maximum twist angle in radians\r\n * @param smoothFactor - Smoothing factor [0-1] (default: 0.3)\r\n */\r\n setTwistConstraint(\r\n jointIndex: number,\r\n minTwist: number,\r\n maxTwist: number,\r\n smoothFactor: number = 0.3\r\n ): void {\r\n if (jointIndex < 0 || jointIndex >= this._chain.joints.length - 1) {\r\n throw new Error(`Invalid joint index: ${jointIndex}`);\r\n }\r\n\r\n this._twistConstraints.set(jointIndex, {\r\n minTwist,\r\n maxTwist,\r\n smoothFactor: Math.max(0, Math.min(1, smoothFactor))\r\n });\r\n }\r\n\r\n /**\r\n * Get twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns Twist constraint or undefined if not set\r\n */\r\n getTwistConstraint(jointIndex: number): TwistConstraint | undefined {\r\n return this._twistConstraints.get(jointIndex);\r\n }\r\n\r\n /**\r\n * Remove twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns True if a constraint was removed\r\n */\r\n removeTwistConstraint(jointIndex: number): boolean {\r\n return this._twistConstraints.delete(jointIndex);\r\n }\r\n\r\n /**\r\n * Clear all twist constraints.\r\n */\r\n clearTwistConstraints(): void {\r\n this._twistConstraints.clear();\r\n }\r\n\r\n /**\r\n * Set pole vector for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint to apply pole vector to\r\n * @param poleVector - Pole vector position in world space\r\n * @param weight - Weight of the pole vector constraint (0-1, default: 1)\r\n */\r\n setPoleVector(jointIndex: number, poleVector: Vector3, weight = 1): void {\r\n if (jointIndex < 0 || jointIndex >= this._chain.joints.length) {\r\n throw new Error(`Invalid joint index: ${jointIndex}`);\r\n }\r\n\r\n this._poleVectors.set(jointIndex, {\r\n position: poleVector.clone(),\r\n weight: Math.max(0, Math.min(1, weight))\r\n });\r\n }\r\n\r\n /**\r\n * Remove pole vector for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint to remove pole vector from\r\n * @returns True if a pole vector was removed, false if none existed\r\n */\r\n removePoleVector(jointIndex: number): boolean {\r\n return this._poleVectors.delete(jointIndex);\r\n }\r\n\r\n /**\r\n * Clear all pole vectors.\r\n */\r\n clearPoleVectors(): void {\r\n this._poleVectors.clear();\r\n }\r\n\r\n /**\r\n * Get pole vector configuration for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns Pole vector configuration or undefined if not set\r\n */\r\n getPoleVector(jointIndex: number): { position: Vector3; weight: number } | undefined {\r\n const config = this._poleVectors.get(jointIndex);\r\n if (config) {\r\n return {\r\n position: config.position.clone(),\r\n weight: config.weight\r\n };\r\n }\r\n return undefined;\r\n }\r\n\r\n /**\r\n * Check if a joint has a pole vector.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns True if the joint has a pole vector\r\n */\r\n hasPoleVector(jointIndex: number): boolean {\r\n return this._poleVectors.has(jointIndex);\r\n }\r\n\r\n /**\r\n * Solve the IK chain to reach the target position using FABRIK algorithm.\r\n *\r\n * @param target - Target position for the end effector\r\n * @returns True if converged within tolerance, false otherwise\r\n */\r\n solve(target: Vector3): boolean {\r\n const joints = this._chain.joints;\r\n\r\n // Update joint positions from scene nodes before solving\r\n this._chain.updateFromNodes();\r\n\r\n // Store original positions\r\n this._chain.storeOriginalPositions();\r\n\r\n const rootPos = joints[0].originalPosition.clone();\r\n\r\n // Check if target is reachable\r\n const distToTarget = Vector3.distance(rootPos, target);\r\n if (distToTarget > this._chain.totalLength) {\r\n // Target unreachable - stretch chain toward target\r\n this._stretchToward(target);\r\n return false;\r\n }\r\n\r\n let converged = false;\r\n for (let iteration = 0; iteration < this._maxIterations; iteration++) {\r\n // Check convergence\r\n const distToEnd = Vector3.distance(joints[joints.length - 1].position, target);\r\n if (distToEnd < this._tolerance) {\r\n converged = true;\r\n break;\r\n }\r\n\r\n // Forward pass: end effector to root\r\n this._forwardPass(target);\r\n\r\n // Backward pass: root to end effector (constraints are applied within the pass)\r\n this._backwardPass(rootPos);\r\n }\r\n\r\n return converged;\r\n }\r\n\r\n /**\r\n * Apply the solved joint positions to scene nodes as rotations.\r\n *\r\n * @param weight - Blend weight (0 = original, 1 = full IK, default: 1)\r\n */\r\n applyToNodes(weight = 1): void {\r\n const joints = this._chain.joints;\r\n\r\n for (let i = 0; i < joints.length - 1; i++) {\r\n const joint = joints[i];\r\n const nextJoint = joints[i + 1];\r\n\r\n // Calculate direction from current joint to next joint in world space\r\n const originalDir = Vector3.sub(nextJoint.originalPosition, joint.originalPosition, new Vector3());\r\n const newDir = Vector3.sub(nextJoint.position, joint.position, new Vector3());\r\n\r\n const originalDirNorm = Vector3.normalize(originalDir, new Vector3());\r\n const newDirNorm = Vector3.normalize(newDir, new Vector3());\r\n\r\n // Calculate basic rotation\r\n const deltaRotation = new Quaternion();\r\n IKUtils.fromToRotation(originalDirNorm, newDirNorm, deltaRotation);\r\n\r\n // Calculate new world rotation\r\n let worldRotation = Quaternion.multiply(deltaRotation, joint.originalRotation, new Quaternion());\r\n\r\n // Apply swing-twist constraint to prevent over-rotation\r\n const swing = new Quaternion();\r\n const twist = new Quaternion();\r\n worldRotation.decomposeSwingTwist(newDirNorm, swing, twist);\r\n\r\n // Get twist angle\r\n let twistAngle = twist.getTwistAngle(newDirNorm);\r\n\r\n // Get twist constraint for this joint\r\n const constraint = this._twistConstraints.get(i);\r\n if (constraint) {\r\n // Clamp and smooth twist\r\n twistAngle = IKUtils.clampAndSmoothTwist(\r\n twistAngle,\r\n joint.previousTwist,\r\n constraint.minTwist,\r\n constraint.maxTwist,\r\n constraint.smoothFactor\r\n );\r\n }\r\n\r\n // Store for next frame\r\n joint.previousTwist = twistAngle;\r\n\r\n // Reconstruct rotation from clamped twist: Q = Twist * Swing\r\n const clampedTwist = Quaternion.fromAxisAngle(newDirNorm, twistAngle);\r\n worldRotation = Quaternion.multiply(clampedTwist, swing, worldRotation);\r\n\r\n // Blend with original rotation based on weight\r\n if (weight < 1) {\r\n Quaternion.slerp(joint.originalRotation, worldRotation, weight, worldRotation);\r\n }\r\n\r\n // Store this frame's world rotation\r\n if (!joint.previousIKRotation) {\r\n joint.previousIKRotation = worldRotation.clone();\r\n } else {\r\n joint.previousIKRotation.set(worldRotation);\r\n }\r\n\r\n // Convert world rotation to local rotation (relative to parent)\r\n if (joint.node.parent) {\r\n const parentWorldRotation = new Quaternion();\r\n joint.node.parent.worldMatrix.decompose(null, parentWorldRotation, null);\r\n\r\n // localRotation = conjugate(parentWorldRotation) * worldRotation\r\n const parentInvRotation = Quaternion.conjugate(parentWorldRotation, new Quaternion());\r\n const localRotation = Quaternion.multiply(parentInvRotation, worldRotation, new Quaternion());\r\n\r\n joint.node.rotation = localRotation;\r\n } else {\r\n // Root node has no parent, world rotation is local rotation\r\n joint.node.rotation = worldRotation;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Forward pass: move from end effector toward root.\r\n * Each joint is pulled toward its child, maintaining bone length.\r\n * Constraints are applied immediately after each joint adjustment.\r\n *\r\n * @param target - Target position for end effector\r\n */\r\n private _forwardPass(target: Vector3): void {\r\n const joints = this._chain.joints;\r\n\r\n // Set end effector to target\r\n joints[joints.length - 1].position.set(target);\r\n\r\n // Move backward through chain\r\n for (let i = joints.length - 2; i >= 0; i--) {\r\n const joint = joints[i];\r\n const childJoint = joints[i + 1];\r\n\r\n // Calculate direction from child to current joint\r\n const direction = Vector3.sub(joint.position, childJoint.position, new Vector3());\r\n const distance = direction.magnitude;\r\n\r\n if (distance > 0.000001) {\r\n direction.scaleBy(1 / distance);\r\n // Place joint at correct distance from child\r\n Vector3.scale(direction, joint.boneLength, direction);\r\n Vector3.add(childJoint.position, direction, joint.position);\r\n }\r\n\r\n // Apply constraints immediately after adjusting this joint\r\n // This ensures constraints are integrated into the FABRIK algorithm\r\n if (i > 0) {\r\n // Apply constraints for joint i (not for root joint)\r\n this._applyConstraintsForJoint(i);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Backward pass: move from root toward end effector.\r\n * Each joint is pulled toward its parent, maintaining bone length.\r\n * Constraints are applied immediately after each joint adjustment.\r\n *\r\n * @param rootPos - Original root position to restore\r\n */\r\n private _backwardPass(rootPos: Vector3): void {\r\n const joints = this._chain.joints;\r\n\r\n // Restore root position\r\n joints[0].position.set(rootPos);\r\n\r\n // Move forward through chain\r\n for (let i = 0; i < joints.length - 1; i++) {\r\n const joint = joints[i];\r\n const childJoint = joints[i + 1];\r\n\r\n // Calculate direction from current joint to child\r\n const direction = Vector3.sub(childJoint.position, joint.position, new Vector3());\r\n const distance = direction.magnitude;\r\n\r\n if (distance > 0.000001) {\r\n direction.scaleBy(1 / distance);\r\n // Place child at correct distance from current joint\r\n Vector3.scale(direction, joint.boneLength, direction);\r\n Vector3.add(joint.position, direction, childJoint.position);\r\n }\r\n\r\n // Apply constraints immediately after adjusting this joint\r\n // This ensures constraints are integrated into the FABRIK algorithm\r\n this._applyConstraintsForJoint(i + 1);\r\n }\r\n }\r\n\r\n /**\r\n * Apply constraints for a specific joint.\r\n * This is called during the FABRIK passes to integrate constraints into the algorithm.\r\n *\r\n * @param jointIndex - Index of the joint to apply constraints to\r\n */\r\n private _applyConstraintsForJoint(jointIndex: number): void {\r\n const constraints = this._chain.constraints;\r\n\r\n // Apply non-pole-vector constraints\r\n // IKPoleVectorConstraint is deprecated and ignored in favor of built-in pole vectors\r\n for (const constraint of constraints) {\r\n if (constraint.jointIndex === jointIndex) {\r\n // Skip IKPoleVectorConstraint - use built-in pole vectors instead\r\n if (constraint.constructor.name === 'IKPoleVectorConstraint') {\r\n continue;\r\n }\r\n constraint.apply(this._chain.joints);\r\n }\r\n }\r\n\r\n // Apply built-in pole vector if configured for this joint\r\n const poleConfig = this._poleVectors.get(jointIndex);\r\n if (poleConfig && poleConfig.weight > 0.001) {\r\n this._applyPoleVectorTwist(jointIndex, poleConfig.position, poleConfig.weight);\r\n }\r\n }\r\n\r\n /**\r\n * Apply pole vector twist to a specific joint.\r\n *\r\n * @remarks\r\n * This method adjusts the joint position to align with the pole vector.\r\n * It uses the same algorithm as IKPoleVectorConstraint but is integrated\r\n * into the solver for better performance and control.\r\n *\r\n * @param jointIndex - Index of the pole joint\r\n * @param poleVector - Pole vector position in world space\r\n * @param weight - Weight of the pole vector constraint (0-1)\r\n */\r\n private _applyPoleVectorTwist(jointIndex: number, poleVector: Vector3, weight: number): void {\r\n const joints = this._chain.joints;\r\n\r\n // We need at least 3 joints to apply pole vector (parent, pole joint, child)\r\n if (jointIndex < 1 || jointIndex >= joints.length - 1) {\r\n return;\r\n }\r\n\r\n const parentJoint = joints[jointIndex - 1];\r\n const currentJoint = joints[jointIndex];\r\n const childJoint = joints[jointIndex + 1];\r\n\r\n const parentPos = parentJoint.position;\r\n const currentPos = currentJoint.position;\r\n const childPos = childJoint.position;\r\n\r\n // Calculate the plane defined by parent, child, and pole vector\r\n // Vector from parent to child (the \"line\" we're bending around)\r\n const parentToChild = Vector3.sub(childPos, parentPos, new Vector3());\r\n const lineLength = parentToChild.magnitude;\r\n\r\n if (lineLength < 0.000001) {\r\n return; // Parent and child are at same position\r\n }\r\n\r\n const lineDir = Vector3.scale(parentToChild, 1 / lineLength, new Vector3());\r\n\r\n // Project current joint onto the parent-child line\r\n const parentToCurrent = Vector3.sub(currentPos, parentPos, new Vector3());\r\n const projectionLength = Vector3.dot(parentToCurrent, lineDir);\r\n const projectionPoint = Vector3.scale(lineDir, projectionLength, new Vector3());\r\n Vector3.add(parentPos, projectionPoint, projectionPoint);\r\n\r\n // Vector from projection point to current joint (perpendicular to line)\r\n const perpendicular = Vector3.sub(currentPos, projectionPoint, new Vector3());\r\n const perpLength = perpendicular.magnitude;\r\n\r\n if (perpLength < 0.000001) {\r\n return; // Current joint is on the line\r\n }\r\n\r\n // Calculate desired direction toward pole vector\r\n const parentToPole = Vector3.sub(poleVector, parentPos, new Vector3());\r\n const poleProjectionLength = Vector3.dot(parentToPole, lineDir);\r\n const poleProjectionPoint = Vector3.scale(lineDir, poleProjectionLength, new Vector3());\r\n Vector3.add(parentPos, poleProjectionPoint, poleProjectionPoint);\r\n\r\n // Direction from projection to pole (perpendicular to line)\r\n const poleDirection = Vector3.sub(poleVector, poleProjectionPoint, new Vector3());\r\n const poleDirLength = poleDirection.magnitude;\r\n\r\n if (poleDirLength < 0.000001) {\r\n return; // Pole is on the line\r\n }\r\n\r\n poleDirection.scaleBy(1 / poleDirLength);\r\n\r\n // Calculate new position for current joint\r\n // Keep the same distance from the line, but rotate toward pole direction\r\n const desiredPerpendicular = Vector3.scale(poleDirection, perpLength, new Vector3());\r\n const newPosition = Vector3.add(projectionPoint, desiredPerpendicular, new Vector3());\r\n\r\n // Apply weight (blend between original and constrained position)\r\n if (weight < 0.999) {\r\n const blended = new Vector3();\r\n blended.x = currentPos.x + (newPosition.x - currentPos.x) * weight;\r\n blended.y = currentPos.y + (newPosition.y - currentPos.y) * weight;\r\n blended.z = currentPos.z + (newPosition.z - currentPos.z) * weight;\r\n currentJoint.position.set(blended);\r\n } else {\r\n currentJoint.position.set(newPosition);\r\n }\r\n }\r\n\r\n /**\r\n * Stretch the chain toward an unreachable target.\r\n * All joints are aligned in a straight line toward the target.\r\n *\r\n * @param target - Unreachable target position\r\n */\r\n private _stretchToward(target: Vector3): void {\r\n const joints = this._chain.joints;\r\n const rootPos = joints[0].originalPosition;\r\n\r\n // Calculate direction from root to target\r\n const direction = Vector3.sub(target, rootPos, new Vector3()).inplaceNormalize();\r\n\r\n // Place each joint along the direction at its bone length\r\n let currentPos = rootPos.clone();\r\n for (let i = 0; i < joints.length; i++) {\r\n joints[i].position.set(currentPos);\r\n if (i < joints.length - 1) {\r\n const offset = Vector3.scale(direction, joints[i].boneLength, new Vector3());\r\n currentPos.addBy(offset);\r\n }\r\n }\r\n }\r\n}\r\n"],"names":["FABRIKSolver","IKSolver","chain","maxIterations","tolerance","_poleVectors","Map","_twistConstraints","i","joints","length","isMiddleJoint","set","minTwist","Math","PI","maxTwist","smoothFactor","setTwistConstraint","jointIndex","_chain","Error","max","min","getTwistConstraint","get","removeTwistConstraint","delete","clearTwistConstraints","clear","setPoleVector","poleVector","weight","position","clone","removePoleVector","clearPoleVectors","getPoleVector","config","undefined","hasPoleVector","has","solve","target","updateFromNodes","storeOriginalPositions","rootPos","originalPosition","distToTarget","Vector3","distance","totalLength","_stretchToward","converged","iteration","_maxIterations","distToEnd","_tolerance","_forwardPass","_backwardPass","applyToNodes","joint","nextJoint","originalDir","sub","newDir","originalDirNorm","normalize","newDirNorm","deltaRotation","Quaternion","IKUtils","fromToRotation","worldRotation","multiply","originalRotation","swing","twist","decomposeSwingTwist","twistAngle","getTwistAngle","constraint","clampAndSmoothTwist","previousTwist","clampedTwist","fromAxisAngle","slerp","previousIKRotation","node","parent","parentWorldRotation","worldMatrix","decompose","parentInvRotation","conjugate","localRotation","rotation","childJoint","direction","magnitude","scaleBy","scale","boneLength","add","_applyConstraintsForJoint","constraints","name","apply","poleConfig","_applyPoleVectorTwist","parentJoint","currentJoint","parentPos","currentPos","childPos","parentToChild","lineLength","lineDir","parentToCurrent","projectionLength","dot","projectionPoint","perpendicular","perpLength","parentToPole","poleProjectionLength","poleProjectionPoint","poleDirection","poleDirLength","desiredPerpendicular","newPosition","blended","x","y","z","inplaceNormalize","offset","addBy"],"mappings":"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"}
|
|
@@ -4,8 +4,13 @@ import { IKConstraint } from './ik_constraint.js';
|
|
|
4
4
|
/**
|
|
5
5
|
* Pole vector constraint for IK chains.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* @deprecated Use the built-in pole vector methods on IK solvers instead:
|
|
8
|
+
* - {@link FABRIKSolver.setPoleVector}
|
|
9
|
+
* - {@link CCDSolver.setPoleVector}
|
|
10
|
+
* - {@link TwoBoneIKSolver.poleVector}
|
|
11
|
+
*
|
|
12
|
+
* This class is deprecated and will be removed in a future version.
|
|
13
|
+
* The built-in pole vector methods provide better performance and more control.
|
|
9
14
|
*
|
|
10
15
|
* @remarks
|
|
11
16
|
* This is commonly used for arms and legs to control which direction
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ik_pole_constraint.js","sources":["../../../src/animation/ik/ik_pole_constraint.ts"],"sourcesContent":["import { Vector3 } from '@zephyr3d/base';\r\nimport { IKConstraint } from './ik_constraint';\r\nimport type { IKJoint } from './ik_joint';\r\n\r\n/**\r\n * Pole vector constraint for IK chains.\r\n *\r\n *
|
|
1
|
+
{"version":3,"file":"ik_pole_constraint.js","sources":["../../../src/animation/ik/ik_pole_constraint.ts"],"sourcesContent":["import { Vector3 } from '@zephyr3d/base';\r\nimport { IKConstraint } from './ik_constraint';\r\nimport type { IKJoint } from './ik_joint';\r\n\r\n/**\r\n * Pole vector constraint for IK chains.\r\n *\r\n * @deprecated Use the built-in pole vector methods on IK solvers instead:\r\n * - {@link FABRIKSolver.setPoleVector}\r\n * - {@link CCDSolver.setPoleVector}\r\n * - {@link TwoBoneIKSolver.poleVector}\r\n *\r\n * This class is deprecated and will be removed in a future version.\r\n * The built-in pole vector methods provide better performance and more control.\r\n *\r\n * @remarks\r\n * This is commonly used for arms and legs to control which direction\r\n * the elbow or knee points. For example, ensuring an elbow points\r\n * backward or a knee points forward.\r\n *\r\n * The pole vector defines a plane, and the middle joint is constrained\r\n * to lie on this plane.\r\n *\r\n * @public\r\n */\r\nexport class IKPoleVectorConstraint extends IKConstraint {\r\n /** The pole vector position in world space */\r\n private _poleVector: Vector3;\r\n /** Weight of the constraint (0 = no effect, 1 = full effect) */\r\n private _weight: number;\r\n\r\n /**\r\n * Create a pole vector constraint.\r\n *\r\n * @param jointIndex - Index of the middle joint to constrain (typically elbow or knee)\r\n * @param poleVector - Position in world space that the joint should point toward\r\n * @param weight - Constraint weight (0-1, default: 1)\r\n */\r\n constructor(jointIndex: number, poleVector: Vector3, weight = 1) {\r\n super(jointIndex);\r\n this._poleVector = poleVector.clone();\r\n this._weight = Math.max(0, Math.min(1, weight));\r\n }\r\n\r\n /**\r\n * Get the pole vector position.\r\n */\r\n get poleVector(): Vector3 {\r\n return this._poleVector;\r\n }\r\n\r\n /**\r\n * Set the pole vector position.\r\n */\r\n set poleVector(value: Vector3) {\r\n this._poleVector.set(value);\r\n }\r\n\r\n /**\r\n * Get the constraint weight.\r\n */\r\n get weight(): number {\r\n return this._weight;\r\n }\r\n\r\n /**\r\n * Set the constraint weight (0-1).\r\n */\r\n set weight(value: number) {\r\n this._weight = Math.max(0, Math.min(1, value));\r\n }\r\n\r\n /**\r\n * Apply the pole vector constraint.\r\n *\r\n * This adjusts the middle joint position to align with the pole vector\r\n * while maintaining bone lengths.\r\n */\r\n apply(joints: IKJoint[]): void {\r\n const index = this._jointIndex;\r\n\r\n // Need at least 3 joints (parent, this, child)\r\n if (index < 1 || index >= joints.length - 1) {\r\n return;\r\n }\r\n\r\n if (this._weight < 0.001) {\r\n return; // No effect\r\n }\r\n\r\n const parentJoint = joints[index - 1];\r\n const currentJoint = joints[index];\r\n const childJoint = joints[index + 1];\r\n\r\n // Calculate the plane defined by parent, child, and pole vector\r\n const parentPos = parentJoint.position;\r\n const childPos = childJoint.position;\r\n const currentPos = currentJoint.position;\r\n\r\n // Vector from parent to child (the \"line\" we're bending around)\r\n const parentToChild = Vector3.sub(childPos, parentPos, new Vector3());\r\n const lineLength = parentToChild.magnitude;\r\n\r\n if (lineLength < 0.000001) {\r\n return; // Parent and child are at same position\r\n }\r\n\r\n const lineDir = Vector3.scale(parentToChild, 1 / lineLength, new Vector3());\r\n\r\n // Project current joint onto the parent-child line\r\n const parentToCurrent = Vector3.sub(currentPos, parentPos, new Vector3());\r\n const projectionLength = Vector3.dot(parentToCurrent, lineDir);\r\n const projectionPoint = Vector3.scale(lineDir, projectionLength, new Vector3());\r\n projectionPoint.addBy(parentPos);\r\n\r\n // Vector from projection point to current joint (perpendicular to line)\r\n const perpendicular = Vector3.sub(currentPos, projectionPoint, new Vector3());\r\n const perpLength = perpendicular.magnitude;\r\n\r\n if (perpLength < 0.000001) {\r\n return; // Current joint is on the line\r\n }\r\n\r\n // Calculate desired direction toward pole vector\r\n const parentToPole = Vector3.sub(this._poleVector, parentPos, new Vector3());\r\n const poleProjectionLength = Vector3.dot(parentToPole, lineDir);\r\n const poleProjectionPoint = Vector3.scale(lineDir, poleProjectionLength, new Vector3());\r\n poleProjectionPoint.addBy(parentPos);\r\n\r\n // Direction from projection to pole (perpendicular to line)\r\n const poleDirection = Vector3.sub(this._poleVector, poleProjectionPoint, new Vector3());\r\n const poleDirLength = poleDirection.magnitude;\r\n\r\n if (poleDirLength < 0.000001) {\r\n return; // Pole is on the line\r\n }\r\n\r\n poleDirection.scaleBy(1 / poleDirLength);\r\n\r\n // Calculate new position for current joint\r\n // Keep the same distance from the line, but rotate toward pole direction\r\n const desiredPerpendicular = Vector3.scale(poleDirection, perpLength, new Vector3());\r\n const newPosition = Vector3.add(projectionPoint, desiredPerpendicular, new Vector3());\r\n\r\n // Apply weight (blend between original and constrained position)\r\n if (this._weight < 0.999) {\r\n // Manual lerp: result = a + (b - a) * t\r\n const blended = new Vector3();\r\n blended.x = currentPos.x + (newPosition.x - currentPos.x) * this._weight;\r\n blended.y = currentPos.y + (newPosition.y - currentPos.y) * this._weight;\r\n blended.z = currentPos.z + (newPosition.z - currentPos.z) * this._weight;\r\n currentJoint.position.set(blended);\r\n } else {\r\n currentJoint.position.set(newPosition);\r\n }\r\n }\r\n}\r\n"],"names":["IKPoleVectorConstraint","IKConstraint","jointIndex","poleVector","weight","_poleVector","clone","_weight","Math","max","min","value","set","apply","joints","index","_jointIndex","length","parentJoint","currentJoint","childJoint","parentPos","position","childPos","currentPos","parentToChild","Vector3","sub","lineLength","magnitude","lineDir","scale","parentToCurrent","projectionLength","dot","projectionPoint","addBy","perpendicular","perpLength","parentToPole","poleProjectionLength","poleProjectionPoint","poleDirection","poleDirLength","scaleBy","desiredPerpendicular","newPosition","add","blended","x","y","z"],"mappings":";;;AAIA;;;;;;;;;;;;;;;;;;;;IAqBO,MAAMA,sBAA+BC,SAAAA,YAAAA,CAAAA;mDAE1C,WAA6B;qEAE7B,OAAwB;AAExB;;;;;;AAMC,MACD,YAAYC,UAAkB,EAAEC,UAAmB,EAAEC,MAAAA,GAAS,CAAC,CAAE;AAC/D,QAAA,KAAK,CAACF,UAAAA,CAAAA;AACN,QAAA,IAAI,CAACG,WAAW,GAAGF,UAAAA,CAAWG,KAAK,EAAA;QACnC,IAAI,CAACC,OAAO,GAAGC,IAAKC,CAAAA,GAAG,CAAC,CAAGD,EAAAA,IAAAA,CAAKE,GAAG,CAAC,CAAGN,EAAAA,MAAAA,CAAAA,CAAAA;AACzC;AAEA;;AAEC,MACD,IAAID,UAAsB,GAAA;QACxB,OAAO,IAAI,CAACE,WAAW;AACzB;AAEA;;MAGA,IAAIF,UAAWQ,CAAAA,KAAc,EAAE;AAC7B,QAAA,IAAI,CAACN,WAAW,CAACO,GAAG,CAACD,KAAAA,CAAAA;AACvB;AAEA;;AAEC,MACD,IAAIP,MAAiB,GAAA;QACnB,OAAO,IAAI,CAACG,OAAO;AACrB;AAEA;;MAGA,IAAIH,MAAOO,CAAAA,KAAa,EAAE;QACxB,IAAI,CAACJ,OAAO,GAAGC,IAAKC,CAAAA,GAAG,CAAC,CAAGD,EAAAA,IAAAA,CAAKE,GAAG,CAAC,CAAGC,EAAAA,KAAAA,CAAAA,CAAAA;AACzC;AAEA;;;;;MAMAE,KAAAA,CAAMC,MAAiB,EAAQ;QAC7B,MAAMC,KAAAA,GAAQ,IAAI,CAACC,WAAW;;AAG9B,QAAA,IAAID,QAAQ,CAAKA,IAAAA,KAAAA,IAASD,MAAOG,CAAAA,MAAM,GAAG,CAAG,EAAA;AAC3C,YAAA;AACF;AAEA,QAAA,IAAI,IAAI,CAACV,OAAO,GAAG,KAAO,EAAA;AACxB,YAAA,OAAA;AACF;AAEA,QAAA,MAAMW,WAAcJ,GAAAA,MAAM,CAACC,KAAAA,GAAQ,CAAE,CAAA;QACrC,MAAMI,YAAAA,GAAeL,MAAM,CAACC,KAAM,CAAA;AAClC,QAAA,MAAMK,UAAaN,GAAAA,MAAM,CAACC,KAAAA,GAAQ,CAAE,CAAA;;QAGpC,MAAMM,SAAAA,GAAYH,YAAYI,QAAQ;QACtC,MAAMC,QAAAA,GAAWH,WAAWE,QAAQ;QACpC,MAAME,UAAAA,GAAaL,aAAaG,QAAQ;;AAGxC,QAAA,MAAMG,gBAAgBC,OAAQC,CAAAA,GAAG,CAACJ,QAAAA,EAAUF,WAAW,IAAIK,OAAAA,EAAAA,CAAAA;QAC3D,MAAME,UAAAA,GAAaH,cAAcI,SAAS;AAE1C,QAAA,IAAID,aAAa,QAAU,EAAA;AACzB,YAAA,OAAA;AACF;AAEA,QAAA,MAAME,UAAUJ,OAAQK,CAAAA,KAAK,CAACN,aAAe,EAAA,CAAA,GAAIG,YAAY,IAAIF,OAAAA,EAAAA,CAAAA;;AAGjE,QAAA,MAAMM,kBAAkBN,OAAQC,CAAAA,GAAG,CAACH,UAAAA,EAAYH,WAAW,IAAIK,OAAAA,EAAAA,CAAAA;AAC/D,QAAA,MAAMO,gBAAmBP,GAAAA,OAAAA,CAAQQ,GAAG,CAACF,eAAiBF,EAAAA,OAAAA,CAAAA;AACtD,QAAA,MAAMK,kBAAkBT,OAAQK,CAAAA,KAAK,CAACD,OAAAA,EAASG,kBAAkB,IAAIP,OAAAA,EAAAA,CAAAA;AACrES,QAAAA,eAAAA,CAAgBC,KAAK,CAACf,SAAAA,CAAAA;;AAGtB,QAAA,MAAMgB,gBAAgBX,OAAQC,CAAAA,GAAG,CAACH,UAAAA,EAAYW,iBAAiB,IAAIT,OAAAA,EAAAA,CAAAA;QACnE,MAAMY,UAAAA,GAAaD,cAAcR,SAAS;AAE1C,QAAA,IAAIS,aAAa,QAAU,EAAA;AACzB,YAAA,OAAA;AACF;;QAGA,MAAMC,YAAAA,GAAeb,QAAQC,GAAG,CAAC,IAAI,CAACtB,WAAW,EAAEgB,SAAAA,EAAW,IAAIK,OAAAA,EAAAA,CAAAA;AAClE,QAAA,MAAMc,oBAAuBd,GAAAA,OAAAA,CAAQQ,GAAG,CAACK,YAAcT,EAAAA,OAAAA,CAAAA;AACvD,QAAA,MAAMW,sBAAsBf,OAAQK,CAAAA,KAAK,CAACD,OAAAA,EAASU,sBAAsB,IAAId,OAAAA,EAAAA,CAAAA;AAC7Ee,QAAAA,mBAAAA,CAAoBL,KAAK,CAACf,SAAAA,CAAAA;;QAG1B,MAAMqB,aAAAA,GAAgBhB,QAAQC,GAAG,CAAC,IAAI,CAACtB,WAAW,EAAEoC,mBAAAA,EAAqB,IAAIf,OAAAA,EAAAA,CAAAA;QAC7E,MAAMiB,aAAAA,GAAgBD,cAAcb,SAAS;AAE7C,QAAA,IAAIc,gBAAgB,QAAU,EAAA;AAC5B,YAAA,OAAA;AACF;QAEAD,aAAcE,CAAAA,OAAO,CAAC,CAAID,GAAAA,aAAAA,CAAAA;;;AAI1B,QAAA,MAAME,uBAAuBnB,OAAQK,CAAAA,KAAK,CAACW,aAAAA,EAAeJ,YAAY,IAAIZ,OAAAA,EAAAA,CAAAA;AAC1E,QAAA,MAAMoB,cAAcpB,OAAQqB,CAAAA,GAAG,CAACZ,eAAAA,EAAiBU,sBAAsB,IAAInB,OAAAA,EAAAA,CAAAA;;AAG3E,QAAA,IAAI,IAAI,CAACnB,OAAO,GAAG,KAAO,EAAA;;AAExB,YAAA,MAAMyC,UAAU,IAAItB,OAAAA,EAAAA;AACpBsB,YAAAA,OAAAA,CAAQC,CAAC,GAAGzB,UAAAA,CAAWyB,CAAC,GAAG,CAACH,WAAAA,CAAYG,CAAC,GAAGzB,WAAWyB,CAAAA,IAAK,IAAI,CAAC1C,OAAO;AACxEyC,YAAAA,OAAAA,CAAQE,CAAC,GAAG1B,UAAAA,CAAW0B,CAAC,GAAG,CAACJ,WAAAA,CAAYI,CAAC,GAAG1B,WAAW0B,CAAAA,IAAK,IAAI,CAAC3C,OAAO;AACxEyC,YAAAA,OAAAA,CAAQG,CAAC,GAAG3B,UAAAA,CAAW2B,CAAC,GAAG,CAACL,WAAAA,CAAYK,CAAC,GAAG3B,WAAW2B,CAAAA,IAAK,IAAI,CAAC5C,OAAO;YACxEY,YAAaG,CAAAA,QAAQ,CAACV,GAAG,CAACoC,OAAAA,CAAAA;SACrB,MAAA;YACL7B,YAAaG,CAAAA,QAAQ,CAACV,GAAG,CAACkC,WAAAA,CAAAA;AAC5B;AACF;AACF;;;;"}
|
|
@@ -46,85 +46,6 @@ import { Vector3, Quaternion } from '@zephyr3d/base';
|
|
|
46
46
|
return Vector3.distance(start, end);
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
|
-
* Decompose a quaternion into swing and twist components around a given axis.
|
|
50
|
-
*
|
|
51
|
-
* @remarks
|
|
52
|
-
* Given a rotation Q and an axis A, decompose Q into:
|
|
53
|
-
* - Twist: rotation around A
|
|
54
|
-
* - Swing: rotation perpendicular to A
|
|
55
|
-
* Such that Q = Twist * Swing
|
|
56
|
-
*
|
|
57
|
-
* Algorithm:
|
|
58
|
-
* 1. Project Q's imaginary part onto axis to get twist component
|
|
59
|
-
* 2. Normalize to get pure twist rotation
|
|
60
|
-
* 3. Calculate swing = twist^-1 * Q
|
|
61
|
-
*
|
|
62
|
-
* @param q - The quaternion to decompose
|
|
63
|
-
* @param axis - The twist axis (must be normalized)
|
|
64
|
-
* @param outSwing - Output swing rotation
|
|
65
|
-
* @param outTwist - Output twist rotation
|
|
66
|
-
*/ static decomposeSwingTwist(q, axis, outSwing, outTwist) {
|
|
67
|
-
// Project quaternion's imaginary part (xyz) onto twist axis
|
|
68
|
-
// twist quaternion = (w, (xyz · axis) * axis)
|
|
69
|
-
const dot = q.x * axis.x + q.y * axis.y + q.z * axis.z;
|
|
70
|
-
outTwist.x = axis.x * dot;
|
|
71
|
-
outTwist.y = axis.y * dot;
|
|
72
|
-
outTwist.z = axis.z * dot;
|
|
73
|
-
outTwist.w = q.w;
|
|
74
|
-
// Normalize twist quaternion
|
|
75
|
-
const twistLen = Math.sqrt(outTwist.x * outTwist.x + outTwist.y * outTwist.y + outTwist.z * outTwist.z + outTwist.w * outTwist.w);
|
|
76
|
-
if (twistLen < 0.000001) {
|
|
77
|
-
// No rotation or rotation perpendicular to axis
|
|
78
|
-
outTwist.identity();
|
|
79
|
-
outSwing.set(q);
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
outTwist.x /= twistLen;
|
|
83
|
-
outTwist.y /= twistLen;
|
|
84
|
-
outTwist.z /= twistLen;
|
|
85
|
-
outTwist.w /= twistLen;
|
|
86
|
-
// Calculate swing: Q = Twist * Swing => Swing = Twist^-1 * Q
|
|
87
|
-
const twistInv = Quaternion.conjugate(outTwist, new Quaternion());
|
|
88
|
-
Quaternion.multiply(twistInv, q, outSwing);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Get the twist angle (in radians) from a twist quaternion around an axis.
|
|
92
|
-
*
|
|
93
|
-
* @param twist - The twist quaternion
|
|
94
|
-
* @param axis - The twist axis (must be normalized)
|
|
95
|
-
* @returns Twist angle in radians, range [-PI, PI]
|
|
96
|
-
*/ static getTwistAngle(twist, axis) {
|
|
97
|
-
// For a twist quaternion around axis: twist = (cos(θ/2), sin(θ/2) * axis)
|
|
98
|
-
// We can extract the angle from the quaternion components
|
|
99
|
-
// Ensure twist is normalized
|
|
100
|
-
const len = Math.sqrt(twist.x * twist.x + twist.y * twist.y + twist.z * twist.z + twist.w * twist.w);
|
|
101
|
-
if (len < 0.000001) {
|
|
102
|
-
return 0;
|
|
103
|
-
}
|
|
104
|
-
const w = twist.w / len;
|
|
105
|
-
const halfAngle = Math.acos(Math.max(-1, Math.min(1, w)));
|
|
106
|
-
// Determine sign based on axis direction
|
|
107
|
-
const dot = twist.x * axis.x + twist.y * axis.y + twist.z * axis.z;
|
|
108
|
-
const sign = dot >= 0 ? 1 : -1;
|
|
109
|
-
return sign * 2 * halfAngle;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Create a twist quaternion from an angle and axis.
|
|
113
|
-
*
|
|
114
|
-
* @param angle - Twist angle in radians
|
|
115
|
-
* @param axis - The twist axis (must be normalized)
|
|
116
|
-
* @param result - Output quaternion
|
|
117
|
-
* @returns The twist quaternion
|
|
118
|
-
*/ static createTwist(angle, axis, result) {
|
|
119
|
-
const halfAngle = angle * 0.5;
|
|
120
|
-
const s = Math.sin(halfAngle);
|
|
121
|
-
result.x = axis.x * s;
|
|
122
|
-
result.y = axis.y * s;
|
|
123
|
-
result.z = axis.z * s;
|
|
124
|
-
result.w = Math.cos(halfAngle);
|
|
125
|
-
return result;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
49
|
* Clamp twist angle and optionally smooth with previous twist.
|
|
129
50
|
*
|
|
130
51
|
* @param currentTwist - Current twist angle in radians
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ik_utils.js","sources":["../../../src/animation/ik/ik_utils.ts"],"sourcesContent":["import { Vector3, Quaternion } from '@zephyr3d/base';\r\n\r\n/**\r\n * Utility functions for IK calculations.\r\n *\r\n * @internal\r\n */\r\nexport class IKUtils {\r\n /**\r\n * Calculate the rotation needed to align 'from' direction to 'to' direction.\r\n *\r\n * @param from - Starting direction vector\r\n * @param to - Target direction vector\r\n * @param result - Output quaternion\r\n * @returns The rotation quaternion\r\n */\r\n static fromToRotation(from: Vector3, to: Vector3, result: Quaternion): Quaternion {\r\n const fromNorm = Vector3.normalize(from, new Vector3());\r\n const toNorm = Vector3.normalize(to, new Vector3());\r\n\r\n const dot = Vector3.dot(fromNorm, toNorm);\r\n\r\n // Vectors are parallel\r\n if (dot >= 0.999999) {\r\n return result.identity();\r\n }\r\n\r\n // Vectors are opposite\r\n if (dot <= -0.999999) {\r\n // Find an orthogonal axis\r\n let axis = Vector3.cross(Vector3.axisPX(), fromNorm, new Vector3());\r\n const lenSq = axis.x * axis.x + axis.y * axis.y + axis.z * axis.z;\r\n if (lenSq < 0.000001) {\r\n axis = Vector3.cross(Vector3.axisPY(), fromNorm, new Vector3());\r\n }\r\n axis.inplaceNormalize();\r\n return result.fromAxisAngle(axis, Math.PI);\r\n }\r\n\r\n // General case\r\n const axis = Vector3.cross(fromNorm, toNorm).inplaceNormalize();\r\n const angle = Math.acos(dot);\r\n return result.fromAxisAngle(axis, angle);\r\n }\r\n\r\n /**\r\n * Calculate bone length between two positions.\r\n *\r\n * @param start - Start position\r\n * @param end - End position\r\n * @returns Distance between positions\r\n */\r\n static calculateBoneLength(start: Vector3, end: Vector3): number {\r\n return Vector3.distance(start, end);\r\n }\r\n\r\n /**\r\n * Decompose a quaternion into swing and twist components around a given axis.\r\n *\r\n * @remarks\r\n * Given a rotation Q and an axis A, decompose Q into:\r\n * - Twist: rotation around A\r\n * - Swing: rotation perpendicular to A\r\n * Such that Q = Twist * Swing\r\n *\r\n * Algorithm:\r\n * 1. Project Q's imaginary part onto axis to get twist component\r\n * 2. Normalize to get pure twist rotation\r\n * 3. Calculate swing = twist^-1 * Q\r\n *\r\n * @param q - The quaternion to decompose\r\n * @param axis - The twist axis (must be normalized)\r\n * @param outSwing - Output swing rotation\r\n * @param outTwist - Output twist rotation\r\n */\r\n static decomposeSwingTwist(q: Quaternion, axis: Vector3, outSwing: Quaternion, outTwist: Quaternion): void {\r\n // Project quaternion's imaginary part (xyz) onto twist axis\r\n // twist quaternion = (w, (xyz · axis) * axis)\r\n const dot = q.x * axis.x + q.y * axis.y + q.z * axis.z;\r\n\r\n outTwist.x = axis.x * dot;\r\n outTwist.y = axis.y * dot;\r\n outTwist.z = axis.z * dot;\r\n outTwist.w = q.w;\r\n\r\n // Normalize twist quaternion\r\n const twistLen = Math.sqrt(\r\n outTwist.x * outTwist.x + outTwist.y * outTwist.y + outTwist.z * outTwist.z + outTwist.w * outTwist.w\r\n );\r\n\r\n if (twistLen < 0.000001) {\r\n // No rotation or rotation perpendicular to axis\r\n outTwist.identity();\r\n outSwing.set(q);\r\n return;\r\n }\r\n\r\n outTwist.x /= twistLen;\r\n outTwist.y /= twistLen;\r\n outTwist.z /= twistLen;\r\n outTwist.w /= twistLen;\r\n\r\n // Calculate swing: Q = Twist * Swing => Swing = Twist^-1 * Q\r\n const twistInv = Quaternion.conjugate(outTwist, new Quaternion());\r\n Quaternion.multiply(twistInv, q, outSwing);\r\n }\r\n\r\n /**\r\n * Get the twist angle (in radians) from a twist quaternion around an axis.\r\n *\r\n * @param twist - The twist quaternion\r\n * @param axis - The twist axis (must be normalized)\r\n * @returns Twist angle in radians, range [-PI, PI]\r\n */\r\n static getTwistAngle(twist: Quaternion, axis: Vector3): number {\r\n // For a twist quaternion around axis: twist = (cos(θ/2), sin(θ/2) * axis)\r\n // We can extract the angle from the quaternion components\r\n\r\n // Ensure twist is normalized\r\n const len = Math.sqrt(twist.x * twist.x + twist.y * twist.y + twist.z * twist.z + twist.w * twist.w);\r\n if (len < 0.000001) {\r\n return 0;\r\n }\r\n\r\n const w = twist.w / len;\r\n const halfAngle = Math.acos(Math.max(-1, Math.min(1, w)));\r\n\r\n // Determine sign based on axis direction\r\n const dot = twist.x * axis.x + twist.y * axis.y + twist.z * axis.z;\r\n const sign = dot >= 0 ? 1 : -1;\r\n\r\n return sign * 2 * halfAngle;\r\n }\r\n\r\n /**\r\n * Create a twist quaternion from an angle and axis.\r\n *\r\n * @param angle - Twist angle in radians\r\n * @param axis - The twist axis (must be normalized)\r\n * @param result - Output quaternion\r\n * @returns The twist quaternion\r\n */\r\n static createTwist(angle: number, axis: Vector3, result: Quaternion): Quaternion {\r\n const halfAngle = angle * 0.5;\r\n const s = Math.sin(halfAngle);\r\n result.x = axis.x * s;\r\n result.y = axis.y * s;\r\n result.z = axis.z * s;\r\n result.w = Math.cos(halfAngle);\r\n return result;\r\n }\r\n\r\n /**\r\n * Clamp twist angle and optionally smooth with previous twist.\r\n *\r\n * @param currentTwist - Current twist angle in radians\r\n * @param previousTwist - Previous frame's twist angle in radians (optional)\r\n * @param minTwist - Minimum allowed twist angle in radians\r\n * @param maxTwist - Maximum allowed twist angle in radians\r\n * @param smoothFactor - Smoothing factor [0-1], 0 = no smoothing, 1 = full smoothing\r\n * @returns Clamped and smoothed twist angle\r\n */\r\n static clampAndSmoothTwist(\r\n currentTwist: number,\r\n previousTwist: number | undefined,\r\n minTwist: number,\r\n maxTwist: number,\r\n smoothFactor: number = 0.5\r\n ): number {\r\n // Clamp to range\r\n let clampedTwist = Math.max(minTwist, Math.min(maxTwist, currentTwist));\r\n\r\n // Smooth with previous frame if available\r\n if (previousTwist !== undefined && smoothFactor > 0.001) {\r\n // Normalize angle difference to [-PI, PI]\r\n let diff = clampedTwist - previousTwist;\r\n while (diff > Math.PI) {\r\n diff -= 2 * Math.PI;\r\n }\r\n while (diff < -Math.PI) {\r\n diff += 2 * Math.PI;\r\n }\r\n\r\n // Lerp\r\n clampedTwist = previousTwist + diff * (1 - smoothFactor);\r\n }\r\n\r\n return clampedTwist;\r\n }\r\n\r\n /**\r\n * Calculate a look-at rotation with twist constraint using a pole vector.\r\n *\r\n * @remarks\r\n * This creates a rotation that:\r\n * 1. Aligns 'forward' direction to 'targetDir'\r\n * 2. Keeps the perpendicular plane aligned with 'poleDir'\r\n *\r\n * This prevents unwanted twist around the bone axis by using an external\r\n * reference direction (pole vector) rather than relying on previous rotations.\r\n *\r\n * @param forward - Current forward direction (will be aligned to targetDir)\r\n * @param targetDir - Desired forward direction\r\n * @param poleDir - Direction that should be in the \"up\" hemisphere (from joint position)\r\n * @param result - Output quaternion\r\n * @returns The rotation quaternion\r\n */\r\n static lookAtRotationWithPole(\r\n forward: Vector3,\r\n targetDir: Vector3,\r\n poleDir: Vector3,\r\n result: Quaternion\r\n ): Quaternion {\r\n const forwardNorm = Vector3.normalize(forward, new Vector3());\r\n const targetDirNorm = Vector3.normalize(targetDir, new Vector3());\r\n const poleDirNorm = Vector3.normalize(poleDir, new Vector3());\r\n\r\n // First, align forward to targetDir (swing rotation)\r\n const swingRotation = new Quaternion();\r\n this.fromToRotation(forwardNorm, targetDirNorm, swingRotation);\r\n\r\n // Calculate the \"right\" vector perpendicular to targetDir and poleDir\r\n // This defines the plane that the bone should bend in\r\n const right = Vector3.cross(targetDirNorm, poleDirNorm, new Vector3());\r\n const rightLenSq = right.x * right.x + right.y * right.y + right.z * right.z;\r\n\r\n // If pole is parallel to target direction, no twist correction possible\r\n if (rightLenSq < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n right.scaleBy(1 / Math.sqrt(rightLenSq));\r\n\r\n // Calculate the \"up\" vector perpendicular to targetDir in the pole plane\r\n const up = Vector3.cross(right, targetDirNorm, new Vector3()).inplaceNormalize();\r\n\r\n // Now we need to find the twist rotation around targetDir\r\n // We want the local \"up\" axis to align with the calculated \"up\" vector\r\n\r\n // Get a perpendicular vector to forward in the original space\r\n let originalUp = Vector3.cross(forwardNorm, Vector3.axisPY(), new Vector3());\r\n const originalUpLenSq =\r\n originalUp.x * originalUp.x + originalUp.y * originalUp.y + originalUp.z * originalUp.z;\r\n if (originalUpLenSq < 0.000001) {\r\n originalUp = Vector3.cross(forwardNorm, Vector3.axisPX(), new Vector3());\r\n }\r\n originalUp.inplaceNormalize();\r\n\r\n // Rotate originalUp by swing rotation to see where it ends up\r\n const rotatedUp = swingRotation.transform(originalUp, new Vector3());\r\n\r\n // Project rotatedUp onto the plane perpendicular to targetDir\r\n const rotatedUpDot = Vector3.dot(rotatedUp, targetDirNorm);\r\n const rotatedUpProj = Vector3.scale(targetDirNorm, rotatedUpDot, new Vector3());\r\n const rotatedUpPerp = Vector3.sub(rotatedUp, rotatedUpProj, new Vector3());\r\n const rotatedUpPerpLen = rotatedUpPerp.magnitude;\r\n\r\n if (rotatedUpPerpLen < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n rotatedUpPerp.scaleBy(1 / rotatedUpPerpLen);\r\n\r\n // Calculate twist rotation to align rotatedUpPerp with up\r\n const twistRotation = new Quaternion();\r\n this.fromToRotation(rotatedUpPerp, up, twistRotation);\r\n\r\n // Combine swing and twist\r\n return Quaternion.multiply(twistRotation, swingRotation, result);\r\n }\r\n\r\n /**\r\n * Calculate a look-at rotation with twist constraint.\r\n *\r\n * @remarks\r\n * This creates a rotation that:\r\n * 1. Aligns 'forward' direction to 'targetDir'\r\n * 2. Keeps 'up' direction as close as possible to 'targetUp'\r\n *\r\n * This prevents unwanted twist around the bone axis.\r\n *\r\n * @param forward - Current forward direction (will be aligned to targetDir)\r\n * @param targetDir - Desired forward direction\r\n * @param up - Current up direction (perpendicular to forward)\r\n * @param targetUp - Desired up direction (will be projected perpendicular to targetDir)\r\n * @param result - Output quaternion\r\n * @returns The rotation quaternion\r\n */\r\n static lookAtRotation(\r\n forward: Vector3,\r\n targetDir: Vector3,\r\n up: Vector3,\r\n targetUp: Vector3,\r\n result: Quaternion\r\n ): Quaternion {\r\n const forwardNorm = Vector3.normalize(forward, new Vector3());\r\n const targetDirNorm = Vector3.normalize(targetDir, new Vector3());\r\n\r\n // First, align forward to targetDir (swing rotation)\r\n const swingRotation = new Quaternion();\r\n this.fromToRotation(forwardNorm, targetDirNorm, swingRotation);\r\n\r\n // Rotate the up vector by swing rotation\r\n const rotatedUp = swingRotation.transform(up, new Vector3());\r\n\r\n // Project targetUp onto plane perpendicular to targetDir\r\n const dot = Vector3.dot(targetUp, targetDirNorm);\r\n const projection = Vector3.scale(targetDirNorm, dot, new Vector3());\r\n const targetUpPerp = Vector3.sub(targetUp, projection, new Vector3());\r\n const targetUpPerpLen = targetUpPerp.magnitude;\r\n\r\n // If targetUp is parallel to targetDir, no twist correction needed\r\n if (targetUpPerpLen < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n targetUpPerp.scaleBy(1 / targetUpPerpLen);\r\n\r\n // Project rotatedUp onto the same plane\r\n const rotatedUpDot = Vector3.dot(rotatedUp, targetDirNorm);\r\n const rotatedUpProj = Vector3.scale(targetDirNorm, rotatedUpDot, new Vector3());\r\n const rotatedUpPerp = Vector3.sub(rotatedUp, rotatedUpProj, new Vector3());\r\n const rotatedUpPerpLen = rotatedUpPerp.magnitude;\r\n\r\n if (rotatedUpPerpLen < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n rotatedUpPerp.scaleBy(1 / rotatedUpPerpLen);\r\n\r\n // Calculate twist rotation around targetDir\r\n const twistRotation = new Quaternion();\r\n this.fromToRotation(rotatedUpPerp, targetUpPerp, twistRotation);\r\n\r\n // Combine swing and twist\r\n return Quaternion.multiply(twistRotation, swingRotation, result);\r\n }\r\n}\r\n"],"names":["IKUtils","fromToRotation","from","to","result","fromNorm","Vector3","normalize","toNorm","dot","identity","axis","cross","axisPX","lenSq","x","y","z","axisPY","inplaceNormalize","fromAxisAngle","Math","PI","angle","acos","calculateBoneLength","start","end","distance","decomposeSwingTwist","q","outSwing","outTwist","w","twistLen","sqrt","set","twistInv","Quaternion","conjugate","multiply","getTwistAngle","twist","len","halfAngle","max","min","sign","createTwist","s","sin","cos","clampAndSmoothTwist","currentTwist","previousTwist","minTwist","maxTwist","smoothFactor","clampedTwist","undefined","diff","lookAtRotationWithPole","forward","targetDir","poleDir","forwardNorm","targetDirNorm","poleDirNorm","swingRotation","right","rightLenSq","scaleBy","up","originalUp","originalUpLenSq","rotatedUp","transform","rotatedUpDot","rotatedUpProj","scale","rotatedUpPerp","sub","rotatedUpPerpLen","magnitude","twistRotation","lookAtRotation","targetUp","projection","targetUpPerp","targetUpPerpLen"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ik_utils.js","sources":["../../../src/animation/ik/ik_utils.ts"],"sourcesContent":["import { Vector3, Quaternion } from '@zephyr3d/base';\r\n\r\n/**\r\n * Utility functions for IK calculations.\r\n *\r\n * @internal\r\n */\r\nexport class IKUtils {\r\n /**\r\n * Calculate the rotation needed to align 'from' direction to 'to' direction.\r\n *\r\n * @param from - Starting direction vector\r\n * @param to - Target direction vector\r\n * @param result - Output quaternion\r\n * @returns The rotation quaternion\r\n */\r\n static fromToRotation(from: Vector3, to: Vector3, result: Quaternion): Quaternion {\r\n const fromNorm = Vector3.normalize(from, new Vector3());\r\n const toNorm = Vector3.normalize(to, new Vector3());\r\n\r\n const dot = Vector3.dot(fromNorm, toNorm);\r\n\r\n // Vectors are parallel\r\n if (dot >= 0.999999) {\r\n return result.identity();\r\n }\r\n\r\n // Vectors are opposite\r\n if (dot <= -0.999999) {\r\n // Find an orthogonal axis\r\n let axis = Vector3.cross(Vector3.axisPX(), fromNorm, new Vector3());\r\n const lenSq = axis.x * axis.x + axis.y * axis.y + axis.z * axis.z;\r\n if (lenSq < 0.000001) {\r\n axis = Vector3.cross(Vector3.axisPY(), fromNorm, new Vector3());\r\n }\r\n axis.inplaceNormalize();\r\n return result.fromAxisAngle(axis, Math.PI);\r\n }\r\n\r\n // General case\r\n const axis = Vector3.cross(fromNorm, toNorm).inplaceNormalize();\r\n const angle = Math.acos(dot);\r\n return result.fromAxisAngle(axis, angle);\r\n }\r\n\r\n /**\r\n * Calculate bone length between two positions.\r\n *\r\n * @param start - Start position\r\n * @param end - End position\r\n * @returns Distance between positions\r\n */\r\n static calculateBoneLength(start: Vector3, end: Vector3): number {\r\n return Vector3.distance(start, end);\r\n }\r\n\r\n /**\r\n * Clamp twist angle and optionally smooth with previous twist.\r\n *\r\n * @param currentTwist - Current twist angle in radians\r\n * @param previousTwist - Previous frame's twist angle in radians (optional)\r\n * @param minTwist - Minimum allowed twist angle in radians\r\n * @param maxTwist - Maximum allowed twist angle in radians\r\n * @param smoothFactor - Smoothing factor [0-1], 0 = no smoothing, 1 = full smoothing\r\n * @returns Clamped and smoothed twist angle\r\n */\r\n static clampAndSmoothTwist(\r\n currentTwist: number,\r\n previousTwist: number | undefined,\r\n minTwist: number,\r\n maxTwist: number,\r\n smoothFactor: number = 0.5\r\n ): number {\r\n // Clamp to range\r\n let clampedTwist = Math.max(minTwist, Math.min(maxTwist, currentTwist));\r\n\r\n // Smooth with previous frame if available\r\n if (previousTwist !== undefined && smoothFactor > 0.001) {\r\n // Normalize angle difference to [-PI, PI]\r\n let diff = clampedTwist - previousTwist;\r\n while (diff > Math.PI) {\r\n diff -= 2 * Math.PI;\r\n }\r\n while (diff < -Math.PI) {\r\n diff += 2 * Math.PI;\r\n }\r\n\r\n // Lerp\r\n clampedTwist = previousTwist + diff * (1 - smoothFactor);\r\n }\r\n\r\n return clampedTwist;\r\n }\r\n\r\n /**\r\n * Calculate a look-at rotation with twist constraint using a pole vector.\r\n *\r\n * @remarks\r\n * This creates a rotation that:\r\n * 1. Aligns 'forward' direction to 'targetDir'\r\n * 2. Keeps the perpendicular plane aligned with 'poleDir'\r\n *\r\n * This prevents unwanted twist around the bone axis by using an external\r\n * reference direction (pole vector) rather than relying on previous rotations.\r\n *\r\n * @param forward - Current forward direction (will be aligned to targetDir)\r\n * @param targetDir - Desired forward direction\r\n * @param poleDir - Direction that should be in the \"up\" hemisphere (from joint position)\r\n * @param result - Output quaternion\r\n * @returns The rotation quaternion\r\n */\r\n static lookAtRotationWithPole(\r\n forward: Vector3,\r\n targetDir: Vector3,\r\n poleDir: Vector3,\r\n result: Quaternion\r\n ): Quaternion {\r\n const forwardNorm = Vector3.normalize(forward, new Vector3());\r\n const targetDirNorm = Vector3.normalize(targetDir, new Vector3());\r\n const poleDirNorm = Vector3.normalize(poleDir, new Vector3());\r\n\r\n // First, align forward to targetDir (swing rotation)\r\n const swingRotation = new Quaternion();\r\n this.fromToRotation(forwardNorm, targetDirNorm, swingRotation);\r\n\r\n // Calculate the \"right\" vector perpendicular to targetDir and poleDir\r\n // This defines the plane that the bone should bend in\r\n const right = Vector3.cross(targetDirNorm, poleDirNorm, new Vector3());\r\n const rightLenSq = right.x * right.x + right.y * right.y + right.z * right.z;\r\n\r\n // If pole is parallel to target direction, no twist correction possible\r\n if (rightLenSq < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n right.scaleBy(1 / Math.sqrt(rightLenSq));\r\n\r\n // Calculate the \"up\" vector perpendicular to targetDir in the pole plane\r\n const up = Vector3.cross(right, targetDirNorm, new Vector3()).inplaceNormalize();\r\n\r\n // Now we need to find the twist rotation around targetDir\r\n // We want the local \"up\" axis to align with the calculated \"up\" vector\r\n\r\n // Get a perpendicular vector to forward in the original space\r\n let originalUp = Vector3.cross(forwardNorm, Vector3.axisPY(), new Vector3());\r\n const originalUpLenSq =\r\n originalUp.x * originalUp.x + originalUp.y * originalUp.y + originalUp.z * originalUp.z;\r\n if (originalUpLenSq < 0.000001) {\r\n originalUp = Vector3.cross(forwardNorm, Vector3.axisPX(), new Vector3());\r\n }\r\n originalUp.inplaceNormalize();\r\n\r\n // Rotate originalUp by swing rotation to see where it ends up\r\n const rotatedUp = swingRotation.transform(originalUp, new Vector3());\r\n\r\n // Project rotatedUp onto the plane perpendicular to targetDir\r\n const rotatedUpDot = Vector3.dot(rotatedUp, targetDirNorm);\r\n const rotatedUpProj = Vector3.scale(targetDirNorm, rotatedUpDot, new Vector3());\r\n const rotatedUpPerp = Vector3.sub(rotatedUp, rotatedUpProj, new Vector3());\r\n const rotatedUpPerpLen = rotatedUpPerp.magnitude;\r\n\r\n if (rotatedUpPerpLen < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n rotatedUpPerp.scaleBy(1 / rotatedUpPerpLen);\r\n\r\n // Calculate twist rotation to align rotatedUpPerp with up\r\n const twistRotation = new Quaternion();\r\n this.fromToRotation(rotatedUpPerp, up, twistRotation);\r\n\r\n // Combine swing and twist\r\n return Quaternion.multiply(twistRotation, swingRotation, result);\r\n }\r\n\r\n /**\r\n * Calculate a look-at rotation with twist constraint.\r\n *\r\n * @remarks\r\n * This creates a rotation that:\r\n * 1. Aligns 'forward' direction to 'targetDir'\r\n * 2. Keeps 'up' direction as close as possible to 'targetUp'\r\n *\r\n * This prevents unwanted twist around the bone axis.\r\n *\r\n * @param forward - Current forward direction (will be aligned to targetDir)\r\n * @param targetDir - Desired forward direction\r\n * @param up - Current up direction (perpendicular to forward)\r\n * @param targetUp - Desired up direction (will be projected perpendicular to targetDir)\r\n * @param result - Output quaternion\r\n * @returns The rotation quaternion\r\n */\r\n static lookAtRotation(\r\n forward: Vector3,\r\n targetDir: Vector3,\r\n up: Vector3,\r\n targetUp: Vector3,\r\n result: Quaternion\r\n ): Quaternion {\r\n const forwardNorm = Vector3.normalize(forward, new Vector3());\r\n const targetDirNorm = Vector3.normalize(targetDir, new Vector3());\r\n\r\n // First, align forward to targetDir (swing rotation)\r\n const swingRotation = new Quaternion();\r\n this.fromToRotation(forwardNorm, targetDirNorm, swingRotation);\r\n\r\n // Rotate the up vector by swing rotation\r\n const rotatedUp = swingRotation.transform(up, new Vector3());\r\n\r\n // Project targetUp onto plane perpendicular to targetDir\r\n const dot = Vector3.dot(targetUp, targetDirNorm);\r\n const projection = Vector3.scale(targetDirNorm, dot, new Vector3());\r\n const targetUpPerp = Vector3.sub(targetUp, projection, new Vector3());\r\n const targetUpPerpLen = targetUpPerp.magnitude;\r\n\r\n // If targetUp is parallel to targetDir, no twist correction needed\r\n if (targetUpPerpLen < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n targetUpPerp.scaleBy(1 / targetUpPerpLen);\r\n\r\n // Project rotatedUp onto the same plane\r\n const rotatedUpDot = Vector3.dot(rotatedUp, targetDirNorm);\r\n const rotatedUpProj = Vector3.scale(targetDirNorm, rotatedUpDot, new Vector3());\r\n const rotatedUpPerp = Vector3.sub(rotatedUp, rotatedUpProj, new Vector3());\r\n const rotatedUpPerpLen = rotatedUpPerp.magnitude;\r\n\r\n if (rotatedUpPerpLen < 0.000001) {\r\n result.set(swingRotation);\r\n return result;\r\n }\r\n\r\n rotatedUpPerp.scaleBy(1 / rotatedUpPerpLen);\r\n\r\n // Calculate twist rotation around targetDir\r\n const twistRotation = new Quaternion();\r\n this.fromToRotation(rotatedUpPerp, targetUpPerp, twistRotation);\r\n\r\n // Combine swing and twist\r\n return Quaternion.multiply(twistRotation, swingRotation, result);\r\n }\r\n}\r\n"],"names":["IKUtils","fromToRotation","from","to","result","fromNorm","Vector3","normalize","toNorm","dot","identity","axis","cross","axisPX","lenSq","x","y","z","axisPY","inplaceNormalize","fromAxisAngle","Math","PI","angle","acos","calculateBoneLength","start","end","distance","clampAndSmoothTwist","currentTwist","previousTwist","minTwist","maxTwist","smoothFactor","clampedTwist","max","min","undefined","diff","lookAtRotationWithPole","forward","targetDir","poleDir","forwardNorm","targetDirNorm","poleDirNorm","swingRotation","Quaternion","right","rightLenSq","set","scaleBy","sqrt","up","originalUp","originalUpLenSq","rotatedUp","transform","rotatedUpDot","rotatedUpProj","scale","rotatedUpPerp","sub","rotatedUpPerpLen","magnitude","twistRotation","multiply","lookAtRotation","targetUp","projection","targetUpPerp","targetUpPerpLen"],"mappings":";;AAEA;;;;AAIC,IACM,MAAMA,OAAAA,CAAAA;AACX;;;;;;;AAOC,MACD,OAAOC,cAAeC,CAAAA,IAAa,EAAEC,EAAW,EAAEC,MAAkB,EAAc;AAChF,QAAA,MAAMC,QAAWC,GAAAA,OAAAA,CAAQC,SAAS,CAACL,MAAM,IAAII,OAAAA,EAAAA,CAAAA;AAC7C,QAAA,MAAME,MAASF,GAAAA,OAAAA,CAAQC,SAAS,CAACJ,IAAI,IAAIG,OAAAA,EAAAA,CAAAA;AAEzC,QAAA,MAAMG,GAAMH,GAAAA,OAAAA,CAAQG,GAAG,CAACJ,QAAUG,EAAAA,MAAAA,CAAAA;;AAGlC,QAAA,IAAIC,OAAO,QAAU,EAAA;AACnB,YAAA,OAAOL,OAAOM,QAAQ,EAAA;AACxB;;QAGA,IAAID,GAAAA,IAAO,SAAW,EAAA;;YAEpB,IAAIE,IAAAA,GAAOL,QAAQM,KAAK,CAACN,QAAQO,MAAM,EAAA,EAAIR,UAAU,IAAIC,OAAAA,EAAAA,CAAAA;AACzD,YAAA,MAAMQ,QAAQH,IAAKI,CAAAA,CAAC,GAAGJ,IAAAA,CAAKI,CAAC,GAAGJ,IAAAA,CAAKK,CAAC,GAAGL,KAAKK,CAAC,GAAGL,KAAKM,CAAC,GAAGN,KAAKM,CAAC;AACjE,YAAA,IAAIH,QAAQ,QAAU,EAAA;AACpBH,gBAAAA,IAAAA,GAAOL,QAAQM,KAAK,CAACN,QAAQY,MAAM,EAAA,EAAIb,UAAU,IAAIC,OAAAA,EAAAA,CAAAA;AACvD;AACAK,YAAAA,IAAAA,CAAKQ,gBAAgB,EAAA;AACrB,YAAA,OAAOf,MAAOgB,CAAAA,aAAa,CAACT,IAAAA,EAAMU,KAAKC,EAAE,CAAA;AAC3C;;AAGA,QAAA,MAAMX,OAAOL,OAAQM,CAAAA,KAAK,CAACP,QAAAA,EAAUG,QAAQW,gBAAgB,EAAA;QAC7D,MAAMI,KAAAA,GAAQF,IAAKG,CAAAA,IAAI,CAACf,GAAAA,CAAAA;QACxB,OAAOL,MAAAA,CAAOgB,aAAa,CAACT,IAAMY,EAAAA,KAAAA,CAAAA;AACpC;AAEA;;;;;;AAMC,MACD,OAAOE,mBAAAA,CAAoBC,KAAc,EAAEC,GAAY,EAAU;QAC/D,OAAOrB,OAAAA,CAAQsB,QAAQ,CAACF,KAAOC,EAAAA,GAAAA,CAAAA;AACjC;AAEA;;;;;;;;;AASC,MACD,OAAOE,mBAAAA,CACLC,YAAoB,EACpBC,aAAiC,EACjCC,QAAgB,EAChBC,QAAgB,EAChBC,YAAuB,GAAA,GAAG,EAClB;;QAER,IAAIC,YAAAA,GAAed,KAAKe,GAAG,CAACJ,UAAUX,IAAKgB,CAAAA,GAAG,CAACJ,QAAUH,EAAAA,YAAAA,CAAAA,CAAAA;;QAGzD,IAAIC,aAAAA,KAAkBO,SAAaJ,IAAAA,YAAAA,GAAe,KAAO,EAAA;;AAEvD,YAAA,IAAIK,OAAOJ,YAAeJ,GAAAA,aAAAA;YAC1B,MAAOQ,IAAAA,GAAOlB,IAAKC,CAAAA,EAAE,CAAE;gBACrBiB,IAAQ,IAAA,CAAA,GAAIlB,KAAKC,EAAE;AACrB;AACA,YAAA,MAAOiB,IAAO,GAAA,CAAClB,IAAKC,CAAAA,EAAE,CAAE;gBACtBiB,IAAQ,IAAA,CAAA,GAAIlB,KAAKC,EAAE;AACrB;;AAGAa,YAAAA,YAAAA,GAAeJ,aAAgBQ,GAAAA,IAAAA,IAAQ,CAAA,GAAIL,YAAW,CAAA;AACxD;QAEA,OAAOC,YAAAA;AACT;AAEA;;;;;;;;;;;;;;;;MAiBA,OAAOK,uBACLC,OAAgB,EAChBC,SAAkB,EAClBC,OAAgB,EAChBvC,MAAkB,EACN;AACZ,QAAA,MAAMwC,WAActC,GAAAA,OAAAA,CAAQC,SAAS,CAACkC,SAAS,IAAInC,OAAAA,EAAAA,CAAAA;AACnD,QAAA,MAAMuC,aAAgBvC,GAAAA,OAAAA,CAAQC,SAAS,CAACmC,WAAW,IAAIpC,OAAAA,EAAAA,CAAAA;AACvD,QAAA,MAAMwC,WAAcxC,GAAAA,OAAAA,CAAQC,SAAS,CAACoC,SAAS,IAAIrC,OAAAA,EAAAA,CAAAA;;AAGnD,QAAA,MAAMyC,gBAAgB,IAAIC,UAAAA,EAAAA;AAC1B,QAAA,IAAI,CAAC/C,cAAc,CAAC2C,WAAAA,EAAaC,aAAeE,EAAAA,aAAAA,CAAAA;;;AAIhD,QAAA,MAAME,QAAQ3C,OAAQM,CAAAA,KAAK,CAACiC,aAAAA,EAAeC,aAAa,IAAIxC,OAAAA,EAAAA,CAAAA;AAC5D,QAAA,MAAM4C,aAAaD,KAAMlC,CAAAA,CAAC,GAAGkC,KAAAA,CAAMlC,CAAC,GAAGkC,KAAAA,CAAMjC,CAAC,GAAGiC,MAAMjC,CAAC,GAAGiC,MAAMhC,CAAC,GAAGgC,MAAMhC,CAAC;;AAG5E,QAAA,IAAIiC,aAAa,QAAU,EAAA;AACzB9C,YAAAA,MAAAA,CAAO+C,GAAG,CAACJ,aAAAA,CAAAA;YACX,OAAO3C,MAAAA;AACT;AAEA6C,QAAAA,KAAAA,CAAMG,OAAO,CAAC,CAAI/B,GAAAA,IAAAA,CAAKgC,IAAI,CAACH,UAAAA,CAAAA,CAAAA;;QAG5B,MAAMI,EAAAA,GAAKhD,QAAQM,KAAK,CAACqC,OAAOJ,aAAe,EAAA,IAAIvC,WAAWa,gBAAgB,EAAA;;;;QAM9E,IAAIoC,UAAAA,GAAajD,QAAQM,KAAK,CAACgC,aAAatC,OAAQY,CAAAA,MAAM,IAAI,IAAIZ,OAAAA,EAAAA,CAAAA;AAClE,QAAA,MAAMkD,kBACJD,UAAWxC,CAAAA,CAAC,GAAGwC,UAAAA,CAAWxC,CAAC,GAAGwC,UAAAA,CAAWvC,CAAC,GAAGuC,WAAWvC,CAAC,GAAGuC,WAAWtC,CAAC,GAAGsC,WAAWtC,CAAC;AACzF,QAAA,IAAIuC,kBAAkB,QAAU,EAAA;AAC9BD,YAAAA,UAAAA,GAAajD,QAAQM,KAAK,CAACgC,aAAatC,OAAQO,CAAAA,MAAM,IAAI,IAAIP,OAAAA,EAAAA,CAAAA;AAChE;AACAiD,QAAAA,UAAAA,CAAWpC,gBAAgB,EAAA;;AAG3B,QAAA,MAAMsC,SAAYV,GAAAA,aAAAA,CAAcW,SAAS,CAACH,YAAY,IAAIjD,OAAAA,EAAAA,CAAAA;;AAG1D,QAAA,MAAMqD,YAAerD,GAAAA,OAAAA,CAAQG,GAAG,CAACgD,SAAWZ,EAAAA,aAAAA,CAAAA;AAC5C,QAAA,MAAMe,gBAAgBtD,OAAQuD,CAAAA,KAAK,CAAChB,aAAAA,EAAec,cAAc,IAAIrD,OAAAA,EAAAA,CAAAA;AACrE,QAAA,MAAMwD,gBAAgBxD,OAAQyD,CAAAA,GAAG,CAACN,SAAAA,EAAWG,eAAe,IAAItD,OAAAA,EAAAA,CAAAA;QAChE,MAAM0D,gBAAAA,GAAmBF,cAAcG,SAAS;AAEhD,QAAA,IAAID,mBAAmB,QAAU,EAAA;AAC/B5D,YAAAA,MAAAA,CAAO+C,GAAG,CAACJ,aAAAA,CAAAA;YACX,OAAO3C,MAAAA;AACT;QAEA0D,aAAcV,CAAAA,OAAO,CAAC,CAAIY,GAAAA,gBAAAA,CAAAA;;AAG1B,QAAA,MAAME,gBAAgB,IAAIlB,UAAAA,EAAAA;AAC1B,QAAA,IAAI,CAAC/C,cAAc,CAAC6D,aAAAA,EAAeR,EAAIY,EAAAA,aAAAA,CAAAA;;AAGvC,QAAA,OAAOlB,UAAWmB,CAAAA,QAAQ,CAACD,aAAAA,EAAenB,aAAe3C,EAAAA,MAAAA,CAAAA;AAC3D;AAEA;;;;;;;;;;;;;;;;MAiBA,OAAOgE,cACL3B,CAAAA,OAAgB,EAChBC,SAAkB,EAClBY,EAAW,EACXe,QAAiB,EACjBjE,MAAkB,EACN;AACZ,QAAA,MAAMwC,WAActC,GAAAA,OAAAA,CAAQC,SAAS,CAACkC,SAAS,IAAInC,OAAAA,EAAAA,CAAAA;AACnD,QAAA,MAAMuC,aAAgBvC,GAAAA,OAAAA,CAAQC,SAAS,CAACmC,WAAW,IAAIpC,OAAAA,EAAAA,CAAAA;;AAGvD,QAAA,MAAMyC,gBAAgB,IAAIC,UAAAA,EAAAA;AAC1B,QAAA,IAAI,CAAC/C,cAAc,CAAC2C,WAAAA,EAAaC,aAAeE,EAAAA,aAAAA,CAAAA;;AAGhD,QAAA,MAAMU,SAAYV,GAAAA,aAAAA,CAAcW,SAAS,CAACJ,IAAI,IAAIhD,OAAAA,EAAAA,CAAAA;;AAGlD,QAAA,MAAMG,GAAMH,GAAAA,OAAAA,CAAQG,GAAG,CAAC4D,QAAUxB,EAAAA,aAAAA,CAAAA;AAClC,QAAA,MAAMyB,aAAahE,OAAQuD,CAAAA,KAAK,CAAChB,aAAAA,EAAepC,KAAK,IAAIH,OAAAA,EAAAA,CAAAA;AACzD,QAAA,MAAMiE,eAAejE,OAAQyD,CAAAA,GAAG,CAACM,QAAAA,EAAUC,YAAY,IAAIhE,OAAAA,EAAAA,CAAAA;QAC3D,MAAMkE,eAAAA,GAAkBD,aAAaN,SAAS;;AAG9C,QAAA,IAAIO,kBAAkB,QAAU,EAAA;AAC9BpE,YAAAA,MAAAA,CAAO+C,GAAG,CAACJ,aAAAA,CAAAA;YACX,OAAO3C,MAAAA;AACT;QAEAmE,YAAanB,CAAAA,OAAO,CAAC,CAAIoB,GAAAA,eAAAA,CAAAA;;AAGzB,QAAA,MAAMb,YAAerD,GAAAA,OAAAA,CAAQG,GAAG,CAACgD,SAAWZ,EAAAA,aAAAA,CAAAA;AAC5C,QAAA,MAAMe,gBAAgBtD,OAAQuD,CAAAA,KAAK,CAAChB,aAAAA,EAAec,cAAc,IAAIrD,OAAAA,EAAAA,CAAAA;AACrE,QAAA,MAAMwD,gBAAgBxD,OAAQyD,CAAAA,GAAG,CAACN,SAAAA,EAAWG,eAAe,IAAItD,OAAAA,EAAAA,CAAAA;QAChE,MAAM0D,gBAAAA,GAAmBF,cAAcG,SAAS;AAEhD,QAAA,IAAID,mBAAmB,QAAU,EAAA;AAC/B5D,YAAAA,MAAAA,CAAO+C,GAAG,CAACJ,aAAAA,CAAAA;YACX,OAAO3C,MAAAA;AACT;QAEA0D,aAAcV,CAAAA,OAAO,CAAC,CAAIY,GAAAA,gBAAAA,CAAAA;;AAG1B,QAAA,MAAME,gBAAgB,IAAIlB,UAAAA,EAAAA;AAC1B,QAAA,IAAI,CAAC/C,cAAc,CAAC6D,aAAAA,EAAeS,YAAcL,EAAAA,aAAAA,CAAAA;;AAGjD,QAAA,OAAOlB,UAAWmB,CAAAA,QAAQ,CAACD,aAAAA,EAAenB,aAAe3C,EAAAA,MAAAA,CAAAA;AAC3D;AACF;;;;"}
|
|
@@ -270,9 +270,9 @@ import { IKUtils } from './ik_utils.js';
|
|
|
270
270
|
// Decompose rotation around bone axis
|
|
271
271
|
const swing = new Quaternion();
|
|
272
272
|
const twist = new Quaternion();
|
|
273
|
-
|
|
273
|
+
worldRotation.decomposeSwingTwist(newDirNorm, swing, twist);
|
|
274
274
|
// Get twist angle
|
|
275
|
-
let twistAngle =
|
|
275
|
+
let twistAngle = twist.getTwistAngle(newDirNorm);
|
|
276
276
|
// Get twist constraint for this joint
|
|
277
277
|
const constraint = this._twistConstraints.get(i);
|
|
278
278
|
if (constraint) {
|
|
@@ -282,8 +282,7 @@ import { IKUtils } from './ik_utils.js';
|
|
|
282
282
|
// Store for next frame
|
|
283
283
|
joint.previousTwist = twistAngle;
|
|
284
284
|
// Reconstruct rotation from clamped twist: Q = Twist * Swing
|
|
285
|
-
const clampedTwist =
|
|
286
|
-
IKUtils.createTwist(twistAngle, newDirNorm, clampedTwist);
|
|
285
|
+
const clampedTwist = Quaternion.fromAxisAngle(newDirNorm, twistAngle);
|
|
287
286
|
worldRotation = Quaternion.multiply(clampedTwist, swing, worldRotation);
|
|
288
287
|
// Blend with original rotation based on weight
|
|
289
288
|
if (weight < 1) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"two_bone_ik_solver.js","sources":["../../../src/animation/ik/two_bone_ik_solver.ts"],"sourcesContent":["import { Vector3, Quaternion } from '@zephyr3d/base';\r\nimport { IKSolver } from './ik_solver';\r\nimport type { IKChain } from './ik_chain';\r\nimport { IKUtils } from './ik_utils';\r\nimport type { TwistConstraint } from './ik_constraint';\r\n\r\n/**\r\n * Two Bone IK solver for chains with exactly 3 joints (2 bones).\r\n *\r\n * @remarks\r\n * This solver uses an analytical solution specifically optimized for\r\n * two-bone chains like arms (shoulder-elbow-wrist) or legs (hip-knee-ankle).\r\n * It's faster and more stable than iterative methods like FABRIK for this case.\r\n *\r\n * The solver supports an optional pole vector to control the bending direction\r\n * of the middle joint (elbow/knee).\r\n *\r\n * @public\r\n */\r\nexport class TwoBoneIKSolver extends IKSolver {\r\n /** Optional pole vector position in world space */\r\n private _poleVector: Vector3 | null;\r\n /** Weight of the pole vector constraint (0-1) */\r\n private _poleWeight: number;\r\n /** Twist constraints for each joint (indexed by joint index) */\r\n private _twistConstraints: Map<number, TwistConstraint>;\r\n\r\n /**\r\n * Create a Two Bone IK solver.\r\n *\r\n * @param chain - The IK chain to solve (must have exactly 3 joints)\r\n * @param poleVector - Optional pole vector position in world space\r\n * @param poleWeight - Weight of the pole vector constraint (0-1, default: 1)\r\n */\r\n constructor(chain: IKChain, poleVector: Vector3 | null = null, poleWeight = 1) {\r\n super(chain, 1, 0.001); // Two bone IK doesn't need iterations\r\n\r\n if (chain.joints.length !== 3) {\r\n throw new Error('Two Bone IK requires exactly 3 joints (2 bones)');\r\n }\r\n\r\n this._poleVector = poleVector ? poleVector.clone() : null;\r\n this._poleWeight = Math.max(0, Math.min(1, poleWeight));\r\n this._twistConstraints = new Map();\r\n\r\n // Set default twist constraints\r\n // Root joint (shoulder/hip) - moderate twist\r\n this._twistConstraints.set(0, {\r\n minTwist: -Math.PI * 0.25, // -45 degrees\r\n maxTwist: Math.PI * 0.25, // +45 degrees\r\n smoothFactor: 0.3\r\n });\r\n\r\n // Middle joint (elbow/knee) - very limited twist\r\n this._twistConstraints.set(1, {\r\n minTwist: -Math.PI * 0.15, // -27 degrees\r\n maxTwist: Math.PI * 0.15, // +27 degrees\r\n smoothFactor: 0.3\r\n });\r\n }\r\n\r\n /**\r\n * Set twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint (0 = root, 1 = middle)\r\n * @param minTwist - Minimum twist angle in radians\r\n * @param maxTwist - Maximum twist angle in radians\r\n * @param smoothFactor - Smoothing factor [0-1] (default: 0.3)\r\n */\r\n setTwistConstraint(\r\n jointIndex: number,\r\n minTwist: number,\r\n maxTwist: number,\r\n smoothFactor: number = 0.3\r\n ): void {\r\n if (jointIndex < 0 || jointIndex >= this._chain.joints.length - 1) {\r\n throw new Error(`Invalid joint index: ${jointIndex}`);\r\n }\r\n\r\n this._twistConstraints.set(jointIndex, {\r\n minTwist,\r\n maxTwist,\r\n smoothFactor: Math.max(0, Math.min(1, smoothFactor))\r\n });\r\n }\r\n\r\n /**\r\n * Get twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns Twist constraint or undefined if not set\r\n */\r\n getTwistConstraint(jointIndex: number): TwistConstraint | undefined {\r\n return this._twistConstraints.get(jointIndex);\r\n }\r\n\r\n /**\r\n * Remove twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns True if a constraint was removed\r\n */\r\n removeTwistConstraint(jointIndex: number): boolean {\r\n return this._twistConstraints.delete(jointIndex);\r\n }\r\n\r\n /**\r\n * Clear all twist constraints.\r\n */\r\n clearTwistConstraints(): void {\r\n this._twistConstraints.clear();\r\n }\r\n\r\n /**\r\n * Get the pole vector position.\r\n */\r\n get poleVector(): Vector3 | null {\r\n return this._poleVector;\r\n }\r\n\r\n /**\r\n * Set the pole vector position.\r\n */\r\n set poleVector(value: Vector3 | null) {\r\n if (value) {\r\n if (!this._poleVector) {\r\n this._poleVector = value.clone();\r\n } else {\r\n this._poleVector.set(value);\r\n }\r\n } else {\r\n this._poleVector = null;\r\n }\r\n }\r\n\r\n /**\r\n * Get the pole vector weight.\r\n */\r\n get poleWeight(): number {\r\n return this._poleWeight;\r\n }\r\n\r\n /**\r\n * Set the pole vector weight (0-1).\r\n */\r\n set poleWeight(value: number) {\r\n this._poleWeight = Math.max(0, Math.min(1, value));\r\n }\r\n\r\n /**\r\n * Solve the IK chain to reach the target position using Two Bone IK algorithm.\r\n *\r\n * @param target - Target position for the end effector\r\n * @returns True if the target is reachable, false if stretched to maximum\r\n */\r\n solve(target: Vector3): boolean {\r\n const joints = this._chain.joints;\r\n\r\n // Update joint positions from scene nodes before solving\r\n this._chain.updateFromNodes();\r\n\r\n // Store original positions\r\n this._chain.storeOriginalPositions();\r\n\r\n const root = joints[0];\r\n const middle = joints[1];\r\n const end = joints[2];\r\n\r\n const rootPos = root.position;\r\n const upperLength = root.boneLength; // Length from root to middle\r\n const lowerLength = middle.boneLength; // Length from middle to end\r\n const totalLength = upperLength + lowerLength;\r\n\r\n // Calculate direction and distance from root to target\r\n const rootToTarget = Vector3.sub(target, rootPos, new Vector3());\r\n const targetDistance = rootToTarget.magnitude;\r\n\r\n // Check if target is reachable\r\n if (targetDistance < 0.000001) {\r\n // Target is at root position, keep original pose\r\n return true;\r\n }\r\n\r\n let reachable = true;\r\n\r\n // If target is unreachable, clamp to maximum distance\r\n let effectiveTarget = target;\r\n if (targetDistance >= totalLength - 0.0001) {\r\n // Stretch to maximum length\r\n const direction = Vector3.scale(rootToTarget, 1 / targetDistance, new Vector3());\r\n effectiveTarget = Vector3.add(\r\n rootPos,\r\n Vector3.scale(direction, totalLength - 0.0001, new Vector3()),\r\n new Vector3()\r\n );\r\n reachable = false;\r\n }\r\n\r\n // Calculate the distance from root to effective target\r\n const rootToEffectiveTarget = Vector3.sub(effectiveTarget, rootPos, new Vector3());\r\n const distance = rootToEffectiveTarget.magnitude;\r\n\r\n // Use law of cosines to find the angle at the root joint\r\n // cos(rootAngle) = (a² + c² - b²) / (2ac)\r\n const cosRootAngle =\r\n (upperLength * upperLength + distance * distance - lowerLength * lowerLength) /\r\n (2 * upperLength * distance);\r\n const clampedCosRootAngle = Math.max(-1, Math.min(1, cosRootAngle));\r\n const rootAngle = Math.acos(clampedCosRootAngle);\r\n\r\n // Determine the plane of bending\r\n let bendNormal: Vector3;\r\n\r\n if (this._poleVector && this._poleWeight > 0.001) {\r\n // Use pole vector to determine bend direction\r\n const rootToTargetDir = Vector3.normalize(rootToEffectiveTarget, new Vector3());\r\n const rootToPole = Vector3.sub(this._poleVector, rootPos, new Vector3());\r\n\r\n // Project pole vector onto plane perpendicular to root-target direction\r\n const projectionLength = Vector3.dot(rootToPole, rootToTargetDir);\r\n const projection = Vector3.scale(rootToTargetDir, projectionLength, new Vector3());\r\n const perpendicular = Vector3.sub(rootToPole, projection, new Vector3());\r\n\r\n const perpLength = perpendicular.magnitude;\r\n if (perpLength > 0.000001) {\r\n // Bend normal is perpendicular to both root-target and pole direction\r\n bendNormal = Vector3.cross(rootToTargetDir, perpendicular, new Vector3()).inplaceNormalize();\r\n } else {\r\n // Pole is on the line, use default bend direction\r\n bendNormal = this._getDefaultBendNormal(rootToEffectiveTarget);\r\n }\r\n\r\n // Apply pole weight\r\n if (this._poleWeight < 0.999) {\r\n const defaultNormal = this._getDefaultBendNormal(rootToEffectiveTarget);\r\n // Slerp between default and pole-based normal\r\n const angle = Math.acos(Math.max(-1, Math.min(1, Vector3.dot(defaultNormal, bendNormal))));\r\n if (angle > 0.001) {\r\n const axis = Vector3.cross(defaultNormal, bendNormal, new Vector3()).inplaceNormalize();\r\n const rotation = new Quaternion().fromAxisAngle(axis, angle * this._poleWeight);\r\n bendNormal = rotation.transform(defaultNormal, new Vector3());\r\n }\r\n }\r\n } else {\r\n // No pole vector, use default bend direction\r\n bendNormal = this._getDefaultBendNormal(rootToEffectiveTarget);\r\n }\r\n\r\n // Calculate middle joint position\r\n const rootToTargetDir = Vector3.normalize(rootToEffectiveTarget, new Vector3());\r\n\r\n // Rotate root-to-target direction by rootAngle around bendNormal\r\n const rotationToMiddle = new Quaternion().fromAxisAngle(bendNormal, rootAngle);\r\n const rootToMiddleDir = rotationToMiddle.transform(rootToTargetDir, new Vector3());\r\n\r\n // Place middle joint\r\n middle.position.set(\r\n Vector3.add(rootPos, Vector3.scale(rootToMiddleDir, upperLength, new Vector3()), new Vector3())\r\n );\r\n\r\n // Place end joint at target\r\n end.position.set(effectiveTarget);\r\n\r\n // Apply constraints after solving\r\n // Note: Constraints may modify joint positions, which could affect bone lengths\r\n // For Two Bone IK, we apply constraints and then restore bone lengths\r\n this._applyConstraints();\r\n\r\n return reachable;\r\n }\r\n\r\n /**\r\n * Apply all constraints to the joint chain.\r\n * After applying constraints, we need to restore bone lengths.\r\n */\r\n private _applyConstraints(): void {\r\n const constraints = this._chain.constraints;\r\n if (constraints.length === 0) {\r\n return;\r\n }\r\n\r\n const joints = this._chain.joints;\r\n\r\n // Apply each constraint\r\n for (const constraint of constraints) {\r\n constraint.apply(joints);\r\n }\r\n\r\n // After constraints are applied, we need to restore bone lengths\r\n // because constraints may have moved joints in ways that change bone lengths\r\n // For Two Bone IK, we fix this by adjusting positions while maintaining the constraint\r\n this._restoreBoneLengths();\r\n }\r\n\r\n /**\r\n * Restore bone lengths after constraints have been applied.\r\n * This ensures that the chain maintains correct bone lengths.\r\n */\r\n private _restoreBoneLengths(): void {\r\n const joints = this._chain.joints;\r\n const root = joints[0];\r\n const middle = joints[1];\r\n const end = joints[2];\r\n\r\n const upperLength = root.boneLength;\r\n const lowerLength = middle.boneLength;\r\n\r\n // Fix middle joint position to maintain upper bone length\r\n const rootToMiddle = Vector3.sub(middle.position, root.position, new Vector3());\r\n const rootToMiddleDist = rootToMiddle.magnitude;\r\n\r\n if (rootToMiddleDist > 0.000001 && Math.abs(rootToMiddleDist - upperLength) > 0.0001) {\r\n const rootToMiddleDir = Vector3.scale(rootToMiddle, 1 / rootToMiddleDist, new Vector3());\r\n middle.position.set(\r\n Vector3.add(root.position, Vector3.scale(rootToMiddleDir, upperLength, new Vector3()), new Vector3())\r\n );\r\n }\r\n\r\n // Fix end joint position to maintain lower bone length\r\n const middleToEnd = Vector3.sub(end.position, middle.position, new Vector3());\r\n const middleToEndDist = middleToEnd.magnitude;\r\n\r\n if (middleToEndDist > 0.000001 && Math.abs(middleToEndDist - lowerLength) > 0.0001) {\r\n const middleToEndDir = Vector3.scale(middleToEnd, 1 / middleToEndDist, new Vector3());\r\n end.position.set(\r\n Vector3.add(middle.position, Vector3.scale(middleToEndDir, lowerLength, new Vector3()), new Vector3())\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Apply the solved joint positions to scene nodes as rotations.\r\n *\r\n * @param weight - Blend weight (0 = original, 1 = full IK, default: 1)\r\n */\r\n applyToNodes(weight = 1): void {\r\n const joints = this._chain.joints;\r\n\r\n // Apply rotation for root and middle joints (end joint doesn't need rotation)\r\n for (let i = 0; i < joints.length - 1; i++) {\r\n const joint = joints[i];\r\n const nextJoint = joints[i + 1];\r\n\r\n // Calculate direction from current joint to next joint in world space\r\n const originalDir = Vector3.sub(nextJoint.originalPosition, joint.originalPosition, new Vector3());\r\n const newDir = Vector3.sub(nextJoint.position, joint.position, new Vector3());\r\n\r\n const originalDirNorm = Vector3.normalize(originalDir, new Vector3());\r\n const newDirNorm = Vector3.normalize(newDir, new Vector3());\r\n\r\n // Calculate basic rotation\r\n const deltaRotation = new Quaternion();\r\n IKUtils.fromToRotation(originalDirNorm, newDirNorm, deltaRotation);\r\n\r\n // Calculate new world rotation\r\n let worldRotation = Quaternion.multiply(deltaRotation, joint.originalRotation, new Quaternion());\r\n\r\n // Apply swing-twist constraint to prevent over-rotation\r\n // Decompose rotation around bone axis\r\n const swing = new Quaternion();\r\n const twist = new Quaternion();\r\n IKUtils.decomposeSwingTwist(worldRotation, newDirNorm, swing, twist);\r\n\r\n // Get twist angle\r\n let twistAngle = IKUtils.getTwistAngle(twist, newDirNorm);\r\n\r\n // Get twist constraint for this joint\r\n const constraint = this._twistConstraints.get(i);\r\n if (constraint) {\r\n // Clamp and smooth twist\r\n twistAngle = IKUtils.clampAndSmoothTwist(\r\n twistAngle,\r\n joint.previousTwist,\r\n constraint.minTwist,\r\n constraint.maxTwist,\r\n constraint.smoothFactor\r\n );\r\n }\r\n\r\n // Store for next frame\r\n joint.previousTwist = twistAngle;\r\n\r\n // Reconstruct rotation from clamped twist: Q = Twist * Swing\r\n const clampedTwist = new Quaternion();\r\n IKUtils.createTwist(twistAngle, newDirNorm, clampedTwist);\r\n worldRotation = Quaternion.multiply(clampedTwist, swing, worldRotation);\r\n\r\n // Blend with original rotation based on weight\r\n if (weight < 1) {\r\n Quaternion.slerp(joint.originalRotation, worldRotation, weight, worldRotation);\r\n }\r\n\r\n // Store this frame's world rotation for next frame's twist continuity\r\n if (!joint.previousIKRotation) {\r\n joint.previousIKRotation = worldRotation.clone();\r\n } else {\r\n joint.previousIKRotation.set(worldRotation);\r\n }\r\n\r\n // Convert world rotation to local rotation (relative to parent)\r\n if (joint.node.parent) {\r\n const parentWorldRotation = new Quaternion();\r\n joint.node.parent.worldMatrix.decompose(null, parentWorldRotation, null);\r\n\r\n // localRotation = conjugate(parentWorldRotation) * worldRotation\r\n const parentInvRotation = Quaternion.conjugate(parentWorldRotation, new Quaternion());\r\n const localRotation = Quaternion.multiply(parentInvRotation, worldRotation, new Quaternion());\r\n\r\n joint.node.rotation = localRotation;\r\n } else {\r\n // Root node has no parent, world rotation is local rotation\r\n joint.node.rotation = worldRotation;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get a default bend normal when no pole vector is specified.\r\n * This tries to find a reasonable perpendicular direction.\r\n *\r\n * @param rootToTarget - Direction from root to target\r\n * @returns A normalized perpendicular vector\r\n */\r\n private _getDefaultBendNormal(rootToTarget: Vector3): Vector3 {\r\n const rootToTargetDir = Vector3.normalize(rootToTarget, new Vector3());\r\n\r\n // Try to use world up (Y axis) as reference\r\n let bendNormal = Vector3.cross(rootToTargetDir, Vector3.axisPY(), new Vector3());\r\n const lenSq = bendNormal.x * bendNormal.x + bendNormal.y * bendNormal.y + bendNormal.z * bendNormal.z;\r\n\r\n // If root-to-target is parallel to Y axis, use X axis instead\r\n if (lenSq < 0.000001) {\r\n bendNormal = Vector3.cross(rootToTargetDir, Vector3.axisPX(), new Vector3());\r\n }\r\n\r\n return bendNormal.inplaceNormalize();\r\n }\r\n}\r\n"],"names":["TwoBoneIKSolver","IKSolver","chain","poleVector","poleWeight","joints","length","Error","_poleVector","clone","_poleWeight","Math","max","min","_twistConstraints","Map","set","minTwist","PI","maxTwist","smoothFactor","setTwistConstraint","jointIndex","_chain","getTwistConstraint","get","removeTwistConstraint","delete","clearTwistConstraints","clear","value","solve","target","updateFromNodes","storeOriginalPositions","root","middle","end","rootPos","position","upperLength","boneLength","lowerLength","totalLength","rootToTarget","Vector3","sub","targetDistance","magnitude","reachable","effectiveTarget","direction","scale","add","rootToEffectiveTarget","distance","cosRootAngle","clampedCosRootAngle","rootAngle","acos","bendNormal","rootToTargetDir","normalize","rootToPole","projectionLength","dot","projection","perpendicular","perpLength","cross","inplaceNormalize","_getDefaultBendNormal","defaultNormal","angle","axis","rotation","Quaternion","fromAxisAngle","transform","rotationToMiddle","rootToMiddleDir","_applyConstraints","constraints","constraint","apply","_restoreBoneLengths","rootToMiddle","rootToMiddleDist","abs","middleToEnd","middleToEndDist","middleToEndDir","applyToNodes","weight","i","joint","nextJoint","originalDir","originalPosition","newDir","originalDirNorm","newDirNorm","deltaRotation","IKUtils","fromToRotation","worldRotation","multiply","originalRotation","swing","twist","decomposeSwingTwist","twistAngle","getTwistAngle","clampAndSmoothTwist","previousTwist","clampedTwist","createTwist","slerp","previousIKRotation","node","parent","parentWorldRotation","worldMatrix","decompose","parentInvRotation","conjugate","localRotation","axisPY","lenSq","x","y","z","axisPX"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"two_bone_ik_solver.js","sources":["../../../src/animation/ik/two_bone_ik_solver.ts"],"sourcesContent":["import { Vector3, Quaternion } from '@zephyr3d/base';\r\nimport { IKSolver } from './ik_solver';\r\nimport type { IKChain } from './ik_chain';\r\nimport { IKUtils } from './ik_utils';\r\nimport type { TwistConstraint } from './ik_constraint';\r\n\r\n/**\r\n * Two Bone IK solver for chains with exactly 3 joints (2 bones).\r\n *\r\n * @remarks\r\n * This solver uses an analytical solution specifically optimized for\r\n * two-bone chains like arms (shoulder-elbow-wrist) or legs (hip-knee-ankle).\r\n * It's faster and more stable than iterative methods like FABRIK for this case.\r\n *\r\n * The solver supports an optional pole vector to control the bending direction\r\n * of the middle joint (elbow/knee).\r\n *\r\n * @public\r\n */\r\nexport class TwoBoneIKSolver extends IKSolver {\r\n /** Optional pole vector position in world space */\r\n private _poleVector: Vector3 | null;\r\n /** Weight of the pole vector constraint (0-1) */\r\n private _poleWeight: number;\r\n /** Twist constraints for each joint (indexed by joint index) */\r\n private _twistConstraints: Map<number, TwistConstraint>;\r\n\r\n /**\r\n * Create a Two Bone IK solver.\r\n *\r\n * @param chain - The IK chain to solve (must have exactly 3 joints)\r\n * @param poleVector - Optional pole vector position in world space\r\n * @param poleWeight - Weight of the pole vector constraint (0-1, default: 1)\r\n */\r\n constructor(chain: IKChain, poleVector: Vector3 | null = null, poleWeight = 1) {\r\n super(chain, 1, 0.001); // Two bone IK doesn't need iterations\r\n\r\n if (chain.joints.length !== 3) {\r\n throw new Error('Two Bone IK requires exactly 3 joints (2 bones)');\r\n }\r\n\r\n this._poleVector = poleVector ? poleVector.clone() : null;\r\n this._poleWeight = Math.max(0, Math.min(1, poleWeight));\r\n this._twistConstraints = new Map();\r\n\r\n // Set default twist constraints\r\n // Root joint (shoulder/hip) - moderate twist\r\n this._twistConstraints.set(0, {\r\n minTwist: -Math.PI * 0.25, // -45 degrees\r\n maxTwist: Math.PI * 0.25, // +45 degrees\r\n smoothFactor: 0.3\r\n });\r\n\r\n // Middle joint (elbow/knee) - very limited twist\r\n this._twistConstraints.set(1, {\r\n minTwist: -Math.PI * 0.15, // -27 degrees\r\n maxTwist: Math.PI * 0.15, // +27 degrees\r\n smoothFactor: 0.3\r\n });\r\n }\r\n\r\n /**\r\n * Set twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint (0 = root, 1 = middle)\r\n * @param minTwist - Minimum twist angle in radians\r\n * @param maxTwist - Maximum twist angle in radians\r\n * @param smoothFactor - Smoothing factor [0-1] (default: 0.3)\r\n */\r\n setTwistConstraint(\r\n jointIndex: number,\r\n minTwist: number,\r\n maxTwist: number,\r\n smoothFactor: number = 0.3\r\n ): void {\r\n if (jointIndex < 0 || jointIndex >= this._chain.joints.length - 1) {\r\n throw new Error(`Invalid joint index: ${jointIndex}`);\r\n }\r\n\r\n this._twistConstraints.set(jointIndex, {\r\n minTwist,\r\n maxTwist,\r\n smoothFactor: Math.max(0, Math.min(1, smoothFactor))\r\n });\r\n }\r\n\r\n /**\r\n * Get twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns Twist constraint or undefined if not set\r\n */\r\n getTwistConstraint(jointIndex: number): TwistConstraint | undefined {\r\n return this._twistConstraints.get(jointIndex);\r\n }\r\n\r\n /**\r\n * Remove twist constraint for a specific joint.\r\n *\r\n * @param jointIndex - Index of the joint\r\n * @returns True if a constraint was removed\r\n */\r\n removeTwistConstraint(jointIndex: number): boolean {\r\n return this._twistConstraints.delete(jointIndex);\r\n }\r\n\r\n /**\r\n * Clear all twist constraints.\r\n */\r\n clearTwistConstraints(): void {\r\n this._twistConstraints.clear();\r\n }\r\n\r\n /**\r\n * Get the pole vector position.\r\n */\r\n get poleVector(): Vector3 | null {\r\n return this._poleVector;\r\n }\r\n\r\n /**\r\n * Set the pole vector position.\r\n */\r\n set poleVector(value: Vector3 | null) {\r\n if (value) {\r\n if (!this._poleVector) {\r\n this._poleVector = value.clone();\r\n } else {\r\n this._poleVector.set(value);\r\n }\r\n } else {\r\n this._poleVector = null;\r\n }\r\n }\r\n\r\n /**\r\n * Get the pole vector weight.\r\n */\r\n get poleWeight(): number {\r\n return this._poleWeight;\r\n }\r\n\r\n /**\r\n * Set the pole vector weight (0-1).\r\n */\r\n set poleWeight(value: number) {\r\n this._poleWeight = Math.max(0, Math.min(1, value));\r\n }\r\n\r\n /**\r\n * Solve the IK chain to reach the target position using Two Bone IK algorithm.\r\n *\r\n * @param target - Target position for the end effector\r\n * @returns True if the target is reachable, false if stretched to maximum\r\n */\r\n solve(target: Vector3): boolean {\r\n const joints = this._chain.joints;\r\n\r\n // Update joint positions from scene nodes before solving\r\n this._chain.updateFromNodes();\r\n\r\n // Store original positions\r\n this._chain.storeOriginalPositions();\r\n\r\n const root = joints[0];\r\n const middle = joints[1];\r\n const end = joints[2];\r\n\r\n const rootPos = root.position;\r\n const upperLength = root.boneLength; // Length from root to middle\r\n const lowerLength = middle.boneLength; // Length from middle to end\r\n const totalLength = upperLength + lowerLength;\r\n\r\n // Calculate direction and distance from root to target\r\n const rootToTarget = Vector3.sub(target, rootPos, new Vector3());\r\n const targetDistance = rootToTarget.magnitude;\r\n\r\n // Check if target is reachable\r\n if (targetDistance < 0.000001) {\r\n // Target is at root position, keep original pose\r\n return true;\r\n }\r\n\r\n let reachable = true;\r\n\r\n // If target is unreachable, clamp to maximum distance\r\n let effectiveTarget = target;\r\n if (targetDistance >= totalLength - 0.0001) {\r\n // Stretch to maximum length\r\n const direction = Vector3.scale(rootToTarget, 1 / targetDistance, new Vector3());\r\n effectiveTarget = Vector3.add(\r\n rootPos,\r\n Vector3.scale(direction, totalLength - 0.0001, new Vector3()),\r\n new Vector3()\r\n );\r\n reachable = false;\r\n }\r\n\r\n // Calculate the distance from root to effective target\r\n const rootToEffectiveTarget = Vector3.sub(effectiveTarget, rootPos, new Vector3());\r\n const distance = rootToEffectiveTarget.magnitude;\r\n\r\n // Use law of cosines to find the angle at the root joint\r\n // cos(rootAngle) = (a² + c² - b²) / (2ac)\r\n const cosRootAngle =\r\n (upperLength * upperLength + distance * distance - lowerLength * lowerLength) /\r\n (2 * upperLength * distance);\r\n const clampedCosRootAngle = Math.max(-1, Math.min(1, cosRootAngle));\r\n const rootAngle = Math.acos(clampedCosRootAngle);\r\n\r\n // Determine the plane of bending\r\n let bendNormal: Vector3;\r\n\r\n if (this._poleVector && this._poleWeight > 0.001) {\r\n // Use pole vector to determine bend direction\r\n const rootToTargetDir = Vector3.normalize(rootToEffectiveTarget, new Vector3());\r\n const rootToPole = Vector3.sub(this._poleVector, rootPos, new Vector3());\r\n\r\n // Project pole vector onto plane perpendicular to root-target direction\r\n const projectionLength = Vector3.dot(rootToPole, rootToTargetDir);\r\n const projection = Vector3.scale(rootToTargetDir, projectionLength, new Vector3());\r\n const perpendicular = Vector3.sub(rootToPole, projection, new Vector3());\r\n\r\n const perpLength = perpendicular.magnitude;\r\n if (perpLength > 0.000001) {\r\n // Bend normal is perpendicular to both root-target and pole direction\r\n bendNormal = Vector3.cross(rootToTargetDir, perpendicular, new Vector3()).inplaceNormalize();\r\n } else {\r\n // Pole is on the line, use default bend direction\r\n bendNormal = this._getDefaultBendNormal(rootToEffectiveTarget);\r\n }\r\n\r\n // Apply pole weight\r\n if (this._poleWeight < 0.999) {\r\n const defaultNormal = this._getDefaultBendNormal(rootToEffectiveTarget);\r\n // Slerp between default and pole-based normal\r\n const angle = Math.acos(Math.max(-1, Math.min(1, Vector3.dot(defaultNormal, bendNormal))));\r\n if (angle > 0.001) {\r\n const axis = Vector3.cross(defaultNormal, bendNormal, new Vector3()).inplaceNormalize();\r\n const rotation = new Quaternion().fromAxisAngle(axis, angle * this._poleWeight);\r\n bendNormal = rotation.transform(defaultNormal, new Vector3());\r\n }\r\n }\r\n } else {\r\n // No pole vector, use default bend direction\r\n bendNormal = this._getDefaultBendNormal(rootToEffectiveTarget);\r\n }\r\n\r\n // Calculate middle joint position\r\n const rootToTargetDir = Vector3.normalize(rootToEffectiveTarget, new Vector3());\r\n\r\n // Rotate root-to-target direction by rootAngle around bendNormal\r\n const rotationToMiddle = new Quaternion().fromAxisAngle(bendNormal, rootAngle);\r\n const rootToMiddleDir = rotationToMiddle.transform(rootToTargetDir, new Vector3());\r\n\r\n // Place middle joint\r\n middle.position.set(\r\n Vector3.add(rootPos, Vector3.scale(rootToMiddleDir, upperLength, new Vector3()), new Vector3())\r\n );\r\n\r\n // Place end joint at target\r\n end.position.set(effectiveTarget);\r\n\r\n // Apply constraints after solving\r\n // Note: Constraints may modify joint positions, which could affect bone lengths\r\n // For Two Bone IK, we apply constraints and then restore bone lengths\r\n this._applyConstraints();\r\n\r\n return reachable;\r\n }\r\n\r\n /**\r\n * Apply all constraints to the joint chain.\r\n * After applying constraints, we need to restore bone lengths.\r\n */\r\n private _applyConstraints(): void {\r\n const constraints = this._chain.constraints;\r\n if (constraints.length === 0) {\r\n return;\r\n }\r\n\r\n const joints = this._chain.joints;\r\n\r\n // Apply each constraint\r\n for (const constraint of constraints) {\r\n constraint.apply(joints);\r\n }\r\n\r\n // After constraints are applied, we need to restore bone lengths\r\n // because constraints may have moved joints in ways that change bone lengths\r\n // For Two Bone IK, we fix this by adjusting positions while maintaining the constraint\r\n this._restoreBoneLengths();\r\n }\r\n\r\n /**\r\n * Restore bone lengths after constraints have been applied.\r\n * This ensures that the chain maintains correct bone lengths.\r\n */\r\n private _restoreBoneLengths(): void {\r\n const joints = this._chain.joints;\r\n const root = joints[0];\r\n const middle = joints[1];\r\n const end = joints[2];\r\n\r\n const upperLength = root.boneLength;\r\n const lowerLength = middle.boneLength;\r\n\r\n // Fix middle joint position to maintain upper bone length\r\n const rootToMiddle = Vector3.sub(middle.position, root.position, new Vector3());\r\n const rootToMiddleDist = rootToMiddle.magnitude;\r\n\r\n if (rootToMiddleDist > 0.000001 && Math.abs(rootToMiddleDist - upperLength) > 0.0001) {\r\n const rootToMiddleDir = Vector3.scale(rootToMiddle, 1 / rootToMiddleDist, new Vector3());\r\n middle.position.set(\r\n Vector3.add(root.position, Vector3.scale(rootToMiddleDir, upperLength, new Vector3()), new Vector3())\r\n );\r\n }\r\n\r\n // Fix end joint position to maintain lower bone length\r\n const middleToEnd = Vector3.sub(end.position, middle.position, new Vector3());\r\n const middleToEndDist = middleToEnd.magnitude;\r\n\r\n if (middleToEndDist > 0.000001 && Math.abs(middleToEndDist - lowerLength) > 0.0001) {\r\n const middleToEndDir = Vector3.scale(middleToEnd, 1 / middleToEndDist, new Vector3());\r\n end.position.set(\r\n Vector3.add(middle.position, Vector3.scale(middleToEndDir, lowerLength, new Vector3()), new Vector3())\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Apply the solved joint positions to scene nodes as rotations.\r\n *\r\n * @param weight - Blend weight (0 = original, 1 = full IK, default: 1)\r\n */\r\n applyToNodes(weight = 1): void {\r\n const joints = this._chain.joints;\r\n\r\n // Apply rotation for root and middle joints (end joint doesn't need rotation)\r\n for (let i = 0; i < joints.length - 1; i++) {\r\n const joint = joints[i];\r\n const nextJoint = joints[i + 1];\r\n\r\n // Calculate direction from current joint to next joint in world space\r\n const originalDir = Vector3.sub(nextJoint.originalPosition, joint.originalPosition, new Vector3());\r\n const newDir = Vector3.sub(nextJoint.position, joint.position, new Vector3());\r\n\r\n const originalDirNorm = Vector3.normalize(originalDir, new Vector3());\r\n const newDirNorm = Vector3.normalize(newDir, new Vector3());\r\n\r\n // Calculate basic rotation\r\n const deltaRotation = new Quaternion();\r\n IKUtils.fromToRotation(originalDirNorm, newDirNorm, deltaRotation);\r\n\r\n // Calculate new world rotation\r\n let worldRotation = Quaternion.multiply(deltaRotation, joint.originalRotation, new Quaternion());\r\n\r\n // Apply swing-twist constraint to prevent over-rotation\r\n // Decompose rotation around bone axis\r\n const swing = new Quaternion();\r\n const twist = new Quaternion();\r\n worldRotation.decomposeSwingTwist(newDirNorm, swing, twist);\r\n\r\n // Get twist angle\r\n let twistAngle = twist.getTwistAngle(newDirNorm);\r\n\r\n // Get twist constraint for this joint\r\n const constraint = this._twistConstraints.get(i);\r\n if (constraint) {\r\n // Clamp and smooth twist\r\n twistAngle = IKUtils.clampAndSmoothTwist(\r\n twistAngle,\r\n joint.previousTwist,\r\n constraint.minTwist,\r\n constraint.maxTwist,\r\n constraint.smoothFactor\r\n );\r\n }\r\n\r\n // Store for next frame\r\n joint.previousTwist = twistAngle;\r\n\r\n // Reconstruct rotation from clamped twist: Q = Twist * Swing\r\n const clampedTwist = Quaternion.fromAxisAngle(newDirNorm, twistAngle);\r\n worldRotation = Quaternion.multiply(clampedTwist, swing, worldRotation);\r\n\r\n // Blend with original rotation based on weight\r\n if (weight < 1) {\r\n Quaternion.slerp(joint.originalRotation, worldRotation, weight, worldRotation);\r\n }\r\n\r\n // Store this frame's world rotation for next frame's twist continuity\r\n if (!joint.previousIKRotation) {\r\n joint.previousIKRotation = worldRotation.clone();\r\n } else {\r\n joint.previousIKRotation.set(worldRotation);\r\n }\r\n\r\n // Convert world rotation to local rotation (relative to parent)\r\n if (joint.node.parent) {\r\n const parentWorldRotation = new Quaternion();\r\n joint.node.parent.worldMatrix.decompose(null, parentWorldRotation, null);\r\n\r\n // localRotation = conjugate(parentWorldRotation) * worldRotation\r\n const parentInvRotation = Quaternion.conjugate(parentWorldRotation, new Quaternion());\r\n const localRotation = Quaternion.multiply(parentInvRotation, worldRotation, new Quaternion());\r\n\r\n joint.node.rotation = localRotation;\r\n } else {\r\n // Root node has no parent, world rotation is local rotation\r\n joint.node.rotation = worldRotation;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get a default bend normal when no pole vector is specified.\r\n * This tries to find a reasonable perpendicular direction.\r\n *\r\n * @param rootToTarget - Direction from root to target\r\n * @returns A normalized perpendicular vector\r\n */\r\n private _getDefaultBendNormal(rootToTarget: Vector3): Vector3 {\r\n const rootToTargetDir = Vector3.normalize(rootToTarget, new Vector3());\r\n\r\n // Try to use world up (Y axis) as reference\r\n let bendNormal = Vector3.cross(rootToTargetDir, Vector3.axisPY(), new Vector3());\r\n const lenSq = bendNormal.x * bendNormal.x + bendNormal.y * bendNormal.y + bendNormal.z * bendNormal.z;\r\n\r\n // If root-to-target is parallel to Y axis, use X axis instead\r\n if (lenSq < 0.000001) {\r\n bendNormal = Vector3.cross(rootToTargetDir, Vector3.axisPX(), new Vector3());\r\n }\r\n\r\n return bendNormal.inplaceNormalize();\r\n }\r\n}\r\n"],"names":["TwoBoneIKSolver","IKSolver","chain","poleVector","poleWeight","joints","length","Error","_poleVector","clone","_poleWeight","Math","max","min","_twistConstraints","Map","set","minTwist","PI","maxTwist","smoothFactor","setTwistConstraint","jointIndex","_chain","getTwistConstraint","get","removeTwistConstraint","delete","clearTwistConstraints","clear","value","solve","target","updateFromNodes","storeOriginalPositions","root","middle","end","rootPos","position","upperLength","boneLength","lowerLength","totalLength","rootToTarget","Vector3","sub","targetDistance","magnitude","reachable","effectiveTarget","direction","scale","add","rootToEffectiveTarget","distance","cosRootAngle","clampedCosRootAngle","rootAngle","acos","bendNormal","rootToTargetDir","normalize","rootToPole","projectionLength","dot","projection","perpendicular","perpLength","cross","inplaceNormalize","_getDefaultBendNormal","defaultNormal","angle","axis","rotation","Quaternion","fromAxisAngle","transform","rotationToMiddle","rootToMiddleDir","_applyConstraints","constraints","constraint","apply","_restoreBoneLengths","rootToMiddle","rootToMiddleDist","abs","middleToEnd","middleToEndDist","middleToEndDir","applyToNodes","weight","i","joint","nextJoint","originalDir","originalPosition","newDir","originalDirNorm","newDirNorm","deltaRotation","IKUtils","fromToRotation","worldRotation","multiply","originalRotation","swing","twist","decomposeSwingTwist","twistAngle","getTwistAngle","clampAndSmoothTwist","previousTwist","clampedTwist","slerp","previousIKRotation","node","parent","parentWorldRotation","worldMatrix","decompose","parentInvRotation","conjugate","localRotation","axisPY","lenSq","x","y","z","axisPX"],"mappings":"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"}
|