@zephyr3d/scene 0.9.27 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -27
- package/dist/animation/animation_bank.js +634 -0
- package/dist/animation/animation_bank.js.map +1 -0
- package/dist/animation/animation_bank_gpu.js +256 -0
- package/dist/animation/animation_bank_gpu.js.map +1 -0
- package/dist/animation/animationset.js +54 -0
- package/dist/animation/animationset.js.map +1 -1
- package/dist/animation/cloth/gpu_cloth_component.js +406 -0
- package/dist/animation/cloth/gpu_cloth_component.js.map +1 -0
- package/dist/animation/cloth/gpu_cloth_system.js +332 -202
- package/dist/animation/cloth/gpu_cloth_system.js.map +1 -1
- package/dist/animation/gpu_animation_driver.js +289 -0
- package/dist/animation/gpu_animation_driver.js.map +1 -0
- package/dist/animation/joint_dynamics/collision.js +112 -1
- package/dist/animation/joint_dynamics/collision.js.map +1 -1
- package/dist/animation/joint_dynamics/controller.js +6 -0
- package/dist/animation/joint_dynamics/controller.js.map +1 -1
- package/dist/animation/joint_dynamics/joint_dynamics_system.js +11 -0
- package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
- package/dist/animation/joint_dynamics/solver.js +50 -12
- package/dist/animation/joint_dynamics/solver.js.map +1 -1
- package/dist/animation/joint_dynamics/types.js.map +1 -1
- package/dist/animation/skeleton.js +279 -55
- package/dist/animation/skeleton.js.map +1 -1
- package/dist/animation/skin_palette_atlas.js +252 -0
- package/dist/animation/skin_palette_atlas.js.map +1 -0
- package/dist/animation/spring/multi_chain_spring_system.js +298 -38
- package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
- package/dist/animation/spring/spring_chain.js +2 -0
- package/dist/animation/spring/spring_chain.js.map +1 -1
- package/dist/animation/spring/spring_collider.js +159 -21
- package/dist/animation/spring/spring_collider.js.map +1 -1
- package/dist/animation/spring/spring_particle.js +1 -0
- package/dist/animation/spring/spring_particle.js.map +1 -1
- package/dist/animation/spring/spring_solver.js +173 -0
- package/dist/animation/spring/spring_solver.js.map +1 -0
- package/dist/animation/spring/spring_system.js +249 -24
- package/dist/animation/spring/spring_system.js.map +1 -1
- package/dist/animation/spring_modifier.js +32 -1
- package/dist/animation/spring_modifier.js.map +1 -1
- package/dist/app/app.js +26 -0
- package/dist/app/app.js.map +1 -1
- package/dist/app/engine.js +86 -15
- package/dist/app/engine.js.map +1 -1
- package/dist/app/gamepad.js +191 -0
- package/dist/app/gamepad.js.map +1 -0
- package/dist/app/inputactions.js +271 -0
- package/dist/app/inputactions.js.map +1 -0
- package/dist/app/inputmgr.js +331 -22
- package/dist/app/inputmgr.js.map +1 -1
- package/dist/app/loading.js +138 -0
- package/dist/app/loading.js.map +1 -0
- package/dist/app/pipelinecache.js +209 -0
- package/dist/app/pipelinecache.js.map +1 -0
- package/dist/app/runtimescript.js +25 -0
- package/dist/app/runtimescript.js.map +1 -1
- package/dist/app/scriptingsystem.js +54 -0
- package/dist/app/scriptingsystem.js.map +1 -1
- package/dist/app/scriptregistry.js +7 -2
- package/dist/app/scriptregistry.js.map +1 -1
- package/dist/asset/asset_manifest.js +59 -0
- package/dist/asset/asset_manifest.js.map +1 -0
- package/dist/asset/asset_preload.js +258 -0
- package/dist/asset/asset_preload.js.map +1 -0
- package/dist/asset/assetmanager.js +117 -65
- package/dist/asset/assetmanager.js.map +1 -1
- package/dist/asset/loaders/ktx2/basis/LICENSE +201 -0
- package/dist/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
- package/dist/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
- package/dist/asset/loaders/ktx2/basis_location.js +17 -0
- package/dist/asset/loaders/ktx2/basis_location.js.map +1 -0
- package/dist/asset/loaders/ktx2/ktx2_loader.js +88 -0
- package/dist/asset/loaders/ktx2/ktx2_loader.js.map +1 -0
- package/dist/asset/loaders/ktx2/ktx2_targets.js +118 -0
- package/dist/asset/loaders/ktx2/ktx2_targets.js.map +1 -0
- package/dist/asset/loaders/ktx2/transcoder_pool.js +259 -0
- package/dist/asset/loaders/ktx2/transcoder_pool.js.map +1 -0
- package/dist/asset/mesh_lod_builder.js +104 -0
- package/dist/asset/mesh_lod_builder.js.map +1 -0
- package/dist/asset/mesh_settings.js +111 -0
- package/dist/asset/mesh_settings.js.map +1 -0
- package/dist/asset/meshopt_decoder.js +18 -0
- package/dist/asset/meshopt_decoder.js.map +1 -0
- package/dist/asset/meshopt_simplifier.js +26 -0
- package/dist/asset/meshopt_simplifier.js.map +1 -0
- package/dist/asset/model.js +171 -1
- package/dist/asset/model.js.map +1 -1
- package/dist/asset/texture_settings.js +231 -0
- package/dist/asset/texture_settings.js.map +1 -0
- package/dist/asset/zmsh_binary.js +131 -0
- package/dist/asset/zmsh_binary.js.map +1 -0
- package/dist/asset/zsdf_binary.js +111 -0
- package/dist/asset/zsdf_binary.js.map +1 -0
- package/dist/blitter/bilateralblur.js +1 -2
- package/dist/blitter/bilateralblur.js.map +1 -1
- package/dist/blitter/gaussianblur.js +1 -6
- package/dist/blitter/gaussianblur.js.map +1 -1
- package/dist/camera/base.js +31 -10
- package/dist/camera/base.js.map +1 -1
- package/dist/camera/camera.js +104 -178
- package/dist/camera/camera.js.map +1 -1
- package/dist/camera/follow.js +342 -0
- package/dist/camera/follow.js.map +1 -0
- package/dist/camera/fps.js +9 -7
- package/dist/camera/fps.js.map +1 -1
- package/dist/camera/orbit.js +46 -19
- package/dist/camera/orbit.js.map +1 -1
- package/dist/index.d.ts +25436 -15990
- package/dist/index.js +65 -11
- package/dist/index.js.map +1 -1
- package/dist/material/blinn.js +3 -0
- package/dist/material/blinn.js.map +1 -1
- package/dist/material/eye.js +1 -1
- package/dist/material/eye.js.map +1 -1
- package/dist/material/hair.js +2 -3
- package/dist/material/hair.js.map +1 -1
- package/dist/material/lambert.js +4 -1
- package/dist/material/lambert.js.map +1 -1
- package/dist/material/material.js +66 -4
- package/dist/material/material.js.map +1 -1
- package/dist/material/meshmaterial.js +118 -45
- package/dist/material/meshmaterial.js.map +1 -1
- package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
- package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
- package/dist/material/mixins/lightmodel/lambert.js +1 -1
- package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +34 -61
- package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +16 -2
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js +2 -1
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
- package/dist/material/mixins/lit.js +191 -83
- package/dist/material/mixins/lit.js.map +1 -1
- package/dist/material/mixins/pbr/common.js +31 -206
- package/dist/material/mixins/pbr/common.js.map +1 -1
- package/dist/material/mtoon.js +1 -1
- package/dist/material/mtoon.js.map +1 -1
- package/dist/material/pbrmr.js +3 -0
- package/dist/material/pbrmr.js.map +1 -1
- package/dist/material/pbrsg.js +3 -0
- package/dist/material/pbrsg.js.map +1 -1
- package/dist/material/sdf_debug.js +78 -0
- package/dist/material/sdf_debug.js.map +1 -0
- package/dist/material/shader/helper.js +333 -191
- package/dist/material/shader/helper.js.map +1 -1
- package/dist/material/shader/terrain_blend.js +204 -43
- package/dist/material/shader/terrain_blend.js.map +1 -1
- package/dist/material/skin.js +331 -297
- package/dist/material/skin.js.map +1 -1
- package/dist/material/skinprofile.js +1058 -0
- package/dist/material/skinprofile.js.map +1 -0
- package/dist/material/sss.js +353 -0
- package/dist/material/sss.js.map +1 -0
- package/dist/material/sss_kernel.js +265 -0
- package/dist/material/sss_kernel.js.map +1 -0
- package/dist/material/sssprofile.js +879 -0
- package/dist/material/sssprofile.js.map +1 -0
- package/dist/material/subsurfaceprofile.js +4 -8
- package/dist/material/subsurfaceprofile.js.map +1 -1
- package/dist/material/terrain-cm.js +464 -188
- package/dist/material/terrain-cm.js.map +1 -1
- package/dist/material/unlit.js +3 -0
- package/dist/material/unlit.js.map +1 -1
- package/dist/material/water.js +1261 -1438
- package/dist/material/water.js.map +1 -1
- package/dist/node_modules/meshoptimizer/LICENSE +21 -0
- package/dist/node_modules/meshoptimizer/meshopt_decoder.js +197 -0
- package/dist/node_modules/meshoptimizer/meshopt_decoder.js.map +1 -0
- package/dist/node_modules/meshoptimizer/meshopt_simplifier.js +677 -0
- package/dist/node_modules/meshoptimizer/meshopt_simplifier.js.map +1 -0
- package/dist/physics/character.js +226 -0
- package/dist/physics/character.js.map +1 -0
- package/dist/physics/collider.js +209 -0
- package/dist/physics/collider.js.map +1 -0
- package/dist/physics/events.js +79 -0
- package/dist/physics/events.js.map +1 -0
- package/dist/physics/joint.js +272 -0
- package/dist/physics/joint.js.map +1 -0
- package/dist/physics/node_physics.js +234 -0
- package/dist/physics/node_physics.js.map +1 -0
- package/dist/physics/part.js +91 -0
- package/dist/physics/part.js.map +1 -0
- package/dist/physics/rigid_body.js +379 -0
- package/dist/physics/rigid_body.js.map +1 -0
- package/dist/physics/vehicle.js +335 -0
- package/dist/physics/vehicle.js.map +1 -0
- package/dist/physics/world.js +25 -0
- package/dist/physics/world.js.map +1 -0
- package/dist/posteffect/bloom.js +49 -14
- package/dist/posteffect/bloom.js.map +1 -1
- package/dist/posteffect/motionblur.js +106 -106
- package/dist/posteffect/motionblur.js.map +1 -1
- package/dist/posteffect/postsss.js +572 -0
- package/dist/posteffect/postsss.js.map +1 -0
- package/dist/posteffect/sao.js +2 -6
- package/dist/posteffect/sao.js.map +1 -1
- package/dist/posteffect/skinsss.js +605 -355
- package/dist/posteffect/skinsss.js.map +1 -1
- package/dist/posteffect/ssgi.js +91 -162
- package/dist/posteffect/ssgi.js.map +1 -1
- package/dist/posteffect/ssr.js +3 -11
- package/dist/posteffect/ssr.js.map +1 -1
- package/dist/posteffect/sss.js +4 -13
- package/dist/posteffect/sss.js.map +1 -1
- package/dist/posteffect/taa.js +1 -0
- package/dist/posteffect/taa.js.map +1 -1
- package/dist/render/abuffer_oit.js +3 -2
- package/dist/render/abuffer_oit.js.map +1 -1
- package/dist/render/clipmap.js +179 -64
- package/dist/render/clipmap.js.map +1 -1
- package/dist/render/cluster_light.js +958 -224
- package/dist/render/cluster_light.js.map +1 -1
- package/dist/render/cull_visitor.js +25 -5
- package/dist/render/cull_visitor.js.map +1 -1
- package/dist/render/debug_views.js +37 -0
- package/dist/render/debug_views.js.map +1 -0
- package/dist/render/depthpass.js +5 -1
- package/dist/render/depthpass.js.map +1 -1
- package/dist/render/drawable_mixin.js +53 -6
- package/dist/render/drawable_mixin.js.map +1 -1
- package/dist/render/dualdepthpeeling_oit.js +5 -5
- package/dist/render/dualdepthpeeling_oit.js.map +1 -1
- package/dist/render/envlight.js +196 -113
- package/dist/render/envlight.js.map +1 -1
- package/dist/render/fbm_wavegenerator.js +5 -10
- package/dist/render/fbm_wavegenerator.js.map +1 -1
- package/dist/render/fft_wavegenerator.js +247 -157
- package/dist/render/fft_wavegenerator.js.map +1 -1
- package/dist/render/gerstner_wavegenerator.js +16 -38
- package/dist/render/gerstner_wavegenerator.js.map +1 -1
- package/dist/render/gi/probe_volume.js +1334 -0
- package/dist/render/gi/probe_volume.js.map +1 -0
- package/dist/render/gi/scene_gi.js +282 -0
- package/dist/render/gi/scene_gi.js.map +1 -0
- package/dist/render/gi/voxel_atlas.js +198 -0
- package/dist/render/gi/voxel_atlas.js.map +1 -0
- package/dist/render/gi/voxel_lighting.js +652 -0
- package/dist/render/gi/voxel_lighting.js.map +1 -0
- package/dist/render/gi/voxel_scene.js +642 -0
- package/dist/render/gi/voxel_scene.js.map +1 -0
- package/dist/render/gi/voxelize_pass.js +223 -0
- package/dist/render/gi/voxelize_pass.js.map +1 -0
- package/dist/render/globalbindgroup_allocator.js +3 -2
- package/dist/render/globalbindgroup_allocator.js.map +1 -1
- package/dist/render/gpu_picking.js +9 -36
- package/dist/render/gpu_picking.js.map +1 -1
- package/dist/render/instance_culling.js +499 -0
- package/dist/render/instance_culling.js.map +1 -0
- package/dist/render/lightpass.js +19 -8
- package/dist/render/lightpass.js.map +1 -1
- package/dist/render/lod.js +46 -0
- package/dist/render/lod.js.map +1 -0
- package/dist/render/primitive.js +301 -9
- package/dist/render/primitive.js.map +1 -1
- package/dist/render/primitive_readback.js +209 -0
- package/dist/render/primitive_readback.js.map +1 -0
- package/dist/render/render_queue.js +162 -11
- package/dist/render/render_queue.js.map +1 -1
- package/dist/render/renderer.js +10 -7
- package/dist/render/renderer.js.map +1 -1
- package/dist/render/rendergraph/blackboard.js +14 -1
- package/dist/render/rendergraph/blackboard.js.map +1 -1
- package/dist/render/rendergraph/executor.js +136 -0
- package/dist/render/rendergraph/executor.js.map +1 -1
- package/dist/render/rendergraph/forward_plus_builder.js +272 -55
- package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
- package/dist/render/rendergraph/frame_graph_context.js +41 -0
- package/dist/render/rendergraph/frame_graph_context.js.map +1 -0
- package/dist/render/rendergraph/scene_render_context.js +31 -2
- package/dist/render/rendergraph/scene_render_context.js.map +1 -1
- package/dist/render/rendergraph/types.js.map +1 -1
- package/dist/render/renderpass.js +28 -5
- package/dist/render/renderpass.js.map +1 -1
- package/dist/render/sdf/box_allocator.js +98 -0
- package/dist/render/sdf/box_allocator.js.map +1 -0
- package/dist/render/sdf/global_sdf.js +865 -0
- package/dist/render/sdf/global_sdf.js.map +1 -0
- package/dist/render/sdf/scene_sdf.js +562 -0
- package/dist/render/sdf/scene_sdf.js.map +1 -0
- package/dist/render/sdf/sdf_atlas.js +227 -0
- package/dist/render/sdf/sdf_atlas.js.map +1 -0
- package/dist/render/sdf/sdf_programs.js +42 -0
- package/dist/render/sdf/sdf_programs.js.map +1 -0
- package/dist/render/sdf/sdf_view.js +199 -0
- package/dist/render/sdf/sdf_view.js.map +1 -0
- package/dist/render/sdf/waterline.js +610 -0
- package/dist/render/sdf/waterline.js.map +1 -0
- package/dist/render/shadow_mask_pass.js +142 -25
- package/dist/render/shadow_mask_pass.js.map +1 -1
- package/dist/render/shore_wave_generator.js +1193 -0
- package/dist/render/shore_wave_generator.js.map +1 -0
- package/dist/render/sky.js +516 -86
- package/dist/render/sky.js.map +1 -1
- package/dist/render/transmission_thickness_pass.js +477 -0
- package/dist/render/transmission_thickness_pass.js.map +1 -0
- package/dist/render/underwater.js +58 -158
- package/dist/render/underwater.js.map +1 -1
- package/dist/render/virtualtexture/virtual_texture.js +1214 -0
- package/dist/render/virtualtexture/virtual_texture.js.map +1 -0
- package/dist/render/volumetric_cloud/cloud_common.js +472 -0
- package/dist/render/volumetric_cloud/cloud_common.js.map +1 -0
- package/dist/render/volumetric_cloud/cloud_noise.js +189 -0
- package/dist/render/volumetric_cloud/cloud_noise.js.map +1 -0
- package/dist/render/volumetric_cloud/debug_view.js +131 -0
- package/dist/render/volumetric_cloud/debug_view.js.map +1 -0
- package/dist/render/volumetric_cloud/resources.js +380 -0
- package/dist/render/volumetric_cloud/resources.js.map +1 -0
- package/dist/render/volumetric_cloud/sky_cache.js +380 -0
- package/dist/render/volumetric_cloud/sky_cache.js.map +1 -0
- package/dist/render/volumetric_cloud/volumetric_cloud.js +318 -0
- package/dist/render/volumetric_cloud/volumetric_cloud.js.map +1 -0
- package/dist/render/water_caustics.js +134 -319
- package/dist/render/water_caustics.js.map +1 -1
- package/dist/render/water_foam.js +627 -0
- package/dist/render/water_foam.js.map +1 -0
- package/dist/render/water_interaction.js +1795 -0
- package/dist/render/water_interaction.js.map +1 -0
- package/dist/render/weightedblended_oit.js +3 -3
- package/dist/render/weightedblended_oit.js.map +1 -1
- package/dist/scene/basesprite.js +9 -4
- package/dist/scene/basesprite.js.map +1 -1
- package/dist/scene/batchgroup.js +108 -12
- package/dist/scene/batchgroup.js.map +1 -1
- package/dist/scene/environment.js +28 -7
- package/dist/scene/environment.js.map +1 -1
- package/dist/scene/foliage.js +1020 -0
- package/dist/scene/foliage.js.map +1 -0
- package/dist/scene/foliage_buckets.js +147 -0
- package/dist/scene/foliage_buckets.js.map +1 -0
- package/dist/scene/foliage_mask.js +358 -0
- package/dist/scene/foliage_mask.js.map +1 -0
- package/dist/scene/hair.js +15 -4
- package/dist/scene/hair.js.map +1 -1
- package/dist/scene/light.js +179 -13
- package/dist/scene/light.js.map +1 -1
- package/dist/scene/mesh.js +327 -45
- package/dist/scene/mesh.js.map +1 -1
- package/dist/scene/meshdrawable.js +6 -0
- package/dist/scene/meshdrawable.js.map +1 -1
- package/dist/scene/msdftext.js +9 -3
- package/dist/scene/msdftext.js.map +1 -1
- package/dist/scene/msdftextsprite.js +9 -3
- package/dist/scene/msdftextsprite.js.map +1 -1
- package/dist/scene/particlesys.js +8 -2
- package/dist/scene/particlesys.js.map +1 -1
- package/dist/scene/physics_settings.js +157 -0
- package/dist/scene/physics_settings.js.map +1 -0
- package/dist/scene/scene.js +190 -44
- package/dist/scene/scene.js.map +1 -1
- package/dist/scene/scene_node.js +147 -6
- package/dist/scene/scene_node.js.map +1 -1
- package/dist/scene/terrain-cm/bladegrassmaterial.js +735 -0
- package/dist/scene/terrain-cm/bladegrassmaterial.js.map +1 -0
- package/dist/scene/terrain-cm/grass.js +881 -42
- package/dist/scene/terrain-cm/grass.js.map +1 -1
- package/dist/scene/terrain-cm/grass_gpu.js +929 -0
- package/dist/scene/terrain-cm/grass_gpu.js.map +1 -0
- package/dist/scene/terrain-cm/grassmaterial.js +180 -9
- package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
- package/dist/scene/terrain-cm/terrain-cm.js +465 -36
- package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
- package/dist/scene/terrain-cm/terrain_gi_albedo.js +257 -0
- package/dist/scene/terrain-cm/terrain_gi_albedo.js.map +1 -0
- package/dist/scene/terrain-cm/terrain_rvt.js +395 -0
- package/dist/scene/terrain-cm/terrain_rvt.js.map +1 -0
- package/dist/scene/update_queue.js +54 -0
- package/dist/scene/update_queue.js.map +1 -0
- package/dist/scene/water.js +633 -268
- package/dist/scene/water.js.map +1 -1
- package/dist/scene/water_surface_sampler.js +324 -0
- package/dist/scene/water_surface_sampler.js.map +1 -0
- package/dist/scene/wind.js +317 -0
- package/dist/scene/wind.js.map +1 -0
- package/dist/shaders/atmosphere.js +388 -166
- package/dist/shaders/atmosphere.js.map +1 -1
- package/dist/shaders/fog.js +100 -32
- package/dist/shaders/fog.js.map +1 -1
- package/dist/shaders/gi.js +365 -0
- package/dist/shaders/gi.js.map +1 -0
- package/dist/shaders/ltc_rect.js +202 -0
- package/dist/shaders/ltc_rect.js.map +1 -0
- package/dist/shaders/misc.js +1 -10
- package/dist/shaders/misc.js.map +1 -1
- package/dist/shaders/noise.js +5 -1
- package/dist/shaders/noise.js.map +1 -1
- package/dist/shaders/probes.js +309 -0
- package/dist/shaders/probes.js.map +1 -0
- package/dist/shaders/sdf.js +537 -0
- package/dist/shaders/sdf.js.map +1 -0
- package/dist/shaders/shadow.js +104 -70
- package/dist/shaders/shadow.js.map +1 -1
- package/dist/shaders/skin_brdf.js +243 -0
- package/dist/shaders/skin_brdf.js.map +1 -0
- package/dist/shaders/ssgi.js +63 -0
- package/dist/shaders/ssgi.js.map +1 -0
- package/dist/shaders/ssgi_reprojection.js +118 -0
- package/dist/shaders/ssgi_reprojection.js.map +1 -0
- package/dist/shaders/ssr.js +6 -159
- package/dist/shaders/ssr.js.map +1 -1
- package/dist/shaders/temporal.js +38 -27
- package/dist/shaders/temporal.js.map +1 -1
- package/dist/shaders/water.js +32 -82
- package/dist/shaders/water.js.map +1 -1
- package/dist/shaders/water_medium.js +7 -21
- package/dist/shaders/water_medium.js.map +1 -1
- package/dist/shadow/dom.js +110 -19
- package/dist/shadow/dom.js.map +1 -1
- package/dist/shadow/esm.js +3 -3
- package/dist/shadow/esm.js.map +1 -1
- package/dist/shadow/pcf_opt.js +15 -48
- package/dist/shadow/pcf_opt.js.map +1 -1
- package/dist/shadow/pcf_pd.js +15 -53
- package/dist/shadow/pcf_pd.js.map +1 -1
- package/dist/shadow/pcss.js +34 -9
- package/dist/shadow/pcss.js.map +1 -1
- package/dist/shadow/shadow_impl.js +3 -8
- package/dist/shadow/shadow_impl.js.map +1 -1
- package/dist/shadow/shadow_region.js +40 -2
- package/dist/shadow/shadow_region.js.map +1 -1
- package/dist/shadow/shadowmapper.js +93 -53
- package/dist/shadow/shadowmapper.js.map +1 -1
- package/dist/shadow/ssm.js +18 -72
- package/dist/shadow/ssm.js.map +1 -1
- package/dist/shadow/vsm.js +3 -3
- package/dist/shadow/vsm.js.map +1 -1
- package/dist/shapes/shape.js +44 -1
- package/dist/shapes/shape.js.map +1 -1
- package/dist/utility/buoyancy.js +287 -0
- package/dist/utility/buoyancy.js.map +1 -0
- package/dist/utility/physical.js +10 -1
- package/dist/utility/physical.js.map +1 -1
- package/dist/utility/pmrem.js +17 -43
- package/dist/utility/pmrem.js.map +1 -1
- package/dist/utility/sdf/bake.js +435 -0
- package/dist/utility/sdf/bake.js.map +1 -0
- package/dist/utility/sdf/bvh.js +576 -0
- package/dist/utility/sdf/bvh.js.map +1 -0
- package/dist/utility/serialization/manager.js +34 -6
- package/dist/utility/serialization/manager.js.map +1 -1
- package/dist/utility/serialization/scene/animation.js +46 -5
- package/dist/utility/serialization/scene/animation.js.map +1 -1
- package/dist/utility/serialization/scene/batch.js +11 -4
- package/dist/utility/serialization/scene/batch.js.map +1 -1
- package/dist/utility/serialization/scene/camera.js +87 -254
- package/dist/utility/serialization/scene/camera.js.map +1 -1
- package/dist/utility/serialization/scene/cloth.js +25 -0
- package/dist/utility/serialization/scene/cloth.js.map +1 -0
- package/dist/utility/serialization/scene/common.js +14 -6
- package/dist/utility/serialization/scene/common.js.map +1 -1
- package/dist/utility/serialization/scene/foliage.js +821 -0
- package/dist/utility/serialization/scene/foliage.js.map +1 -0
- package/dist/utility/serialization/scene/hair.js +11 -4
- package/dist/utility/serialization/scene/hair.js.map +1 -1
- package/dist/utility/serialization/scene/light.js +115 -7
- package/dist/utility/serialization/scene/light.js.map +1 -1
- package/dist/utility/serialization/scene/material.js +388 -220
- package/dist/utility/serialization/scene/material.js.map +1 -1
- package/dist/utility/serialization/scene/mesh.js +69 -4
- package/dist/utility/serialization/scene/mesh.js.map +1 -1
- package/dist/utility/serialization/scene/node.js +140 -5
- package/dist/utility/serialization/scene/node.js.map +1 -1
- package/dist/utility/serialization/scene/node_physics.js +1318 -0
- package/dist/utility/serialization/scene/node_physics.js.map +1 -0
- package/dist/utility/serialization/scene/particle.js +11 -4
- package/dist/utility/serialization/scene/particle.js.map +1 -1
- package/dist/utility/serialization/scene/physics.js +120 -0
- package/dist/utility/serialization/scene/physics.js.map +1 -0
- package/dist/utility/serialization/scene/primitive.js +124 -10
- package/dist/utility/serialization/scene/primitive.js.map +1 -1
- package/dist/utility/serialization/scene/scene.js +1687 -51
- package/dist/utility/serialization/scene/scene.js.map +1 -1
- package/dist/utility/serialization/scene/sprite.js +11 -4
- package/dist/utility/serialization/scene/sprite.js.map +1 -1
- package/dist/utility/serialization/scene/terrain.js +163 -33
- package/dist/utility/serialization/scene/terrain.js.map +1 -1
- package/dist/utility/serialization/scene/text.js +11 -4
- package/dist/utility/serialization/scene/text.js.map +1 -1
- package/dist/utility/serialization/scene/water.js +1543 -264
- package/dist/utility/serialization/scene/water.js.map +1 -1
- package/dist/utility/serialization/types.js.map +1 -1
- package/dist/utility/shprojector.js +10 -22
- package/dist/utility/shprojector.js.map +1 -1
- package/dist/utility/textures/foam.js +170 -0
- package/dist/utility/textures/foam.js.map +1 -0
- package/dist/utility/textures/ggxlut.js +17 -43
- package/dist/utility/textures/ggxlut.js.map +1 -1
- package/dist/utility/textures/ltcdata.js +4 -4
- package/dist/utility/textures/ltcdata.js.map +1 -1
- package/dist/utility/textures/ltclut.js +16 -6
- package/dist/utility/textures/ltclut.js.map +1 -1
- package/dist/utility/unsupported.js +24 -0
- package/dist/utility/unsupported.js.map +1 -0
- package/dist/values.js +13 -1
- package/dist/values.js.map +1 -1
- package/package.json +25 -12
- package/src/asset/loaders/ktx2/basis/LICENSE +201 -0
- package/src/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
- package/src/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
- package/src/asset/meshoptimizer/LICENSE +21 -0
- package/dist/animation/joint_dynamics/convex_collider.js +0 -320
- package/dist/animation/joint_dynamics/convex_collider.js.map +0 -1
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { Vector3 } from '@zephyr3d/base';
|
|
2
2
|
|
|
3
|
+
const COLLISION_DISTANCE_EPSILON_SQ = 1e-12;
|
|
4
|
+
function getCapsuleAxisFallbackNormal(axis, result) {
|
|
5
|
+
const reference = Math.abs(axis.z) < 0.9 ? Vector3.axisPZ() : Vector3.axisPX();
|
|
6
|
+
Vector3.sub(reference, Vector3.scale(axis, Vector3.dot(reference, axis), result), result);
|
|
7
|
+
return result.inplaceNormalize();
|
|
8
|
+
}
|
|
3
9
|
/**
|
|
4
10
|
* Creates a sphere collider
|
|
5
11
|
* @param centerOrOffset - Center position in world space, or local offset if node is provided
|
|
@@ -105,21 +111,64 @@ import { Vector3 } from '@zephyr3d/base';
|
|
|
105
111
|
};
|
|
106
112
|
}
|
|
107
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Creates an oriented box collider.
|
|
116
|
+
* @param centerOrOffset - Center position in world space, or local offset if node is provided
|
|
117
|
+
* @param halfExtents - Local/world half extents of the box
|
|
118
|
+
* @param node - Optional scene node to attach to
|
|
119
|
+
*
|
|
120
|
+
* @public
|
|
121
|
+
*/ function createBoxCollider(centerOrOffset, halfExtents, node) {
|
|
122
|
+
const localExtents = new Vector3(Math.max(0.0001, Math.abs(halfExtents.x)), Math.max(0.0001, Math.abs(halfExtents.y)), Math.max(0.0001, Math.abs(halfExtents.z)));
|
|
123
|
+
if (node) {
|
|
124
|
+
const worldMatrix = node.worldMatrix;
|
|
125
|
+
const center = worldMatrix.transformPointAffine(centerOrOffset, new Vector3());
|
|
126
|
+
const axes = createWorldAxes(worldMatrix);
|
|
127
|
+
const scales = getAxisScales(worldMatrix);
|
|
128
|
+
return {
|
|
129
|
+
type: 'box',
|
|
130
|
+
center,
|
|
131
|
+
halfExtents: new Vector3(localExtents.x * scales.x, localExtents.y * scales.y, localExtents.z * scales.z),
|
|
132
|
+
axes,
|
|
133
|
+
localOffset: centerOrOffset.clone(),
|
|
134
|
+
localHalfExtents: localExtents,
|
|
135
|
+
node,
|
|
136
|
+
enabled: true
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
type: 'box',
|
|
141
|
+
center: centerOrOffset.clone(),
|
|
142
|
+
halfExtents: localExtents,
|
|
143
|
+
axes: [
|
|
144
|
+
Vector3.axisPX(),
|
|
145
|
+
Vector3.axisPY(),
|
|
146
|
+
Vector3.axisPZ()
|
|
147
|
+
],
|
|
148
|
+
node: null,
|
|
149
|
+
enabled: true
|
|
150
|
+
};
|
|
151
|
+
}
|
|
108
152
|
/**
|
|
109
153
|
* Resolves collision between a particle and a sphere collider
|
|
110
154
|
* @returns true if collision occurred
|
|
111
155
|
*
|
|
112
156
|
* @public
|
|
113
|
-
*/ function resolveSphereCollision(particlePos, collider) {
|
|
157
|
+
*/ function resolveSphereCollision(particlePos, collider, particleRadius = 0) {
|
|
114
158
|
const toParticle = Vector3.sub(particlePos, collider.center, new Vector3());
|
|
115
159
|
const distSq = toParticle.magnitudeSq;
|
|
116
|
-
const
|
|
117
|
-
|
|
160
|
+
const contactRadius = collider.radius + Math.max(0, particleRadius);
|
|
161
|
+
const radiusSq = contactRadius * contactRadius;
|
|
162
|
+
if (distSq < radiusSq) {
|
|
118
163
|
// Particle is inside sphere, push it out
|
|
119
|
-
const dist = Math.sqrt(distSq);
|
|
120
|
-
const penetration =
|
|
164
|
+
const dist = distSq > COLLISION_DISTANCE_EPSILON_SQ ? Math.sqrt(distSq) : 0;
|
|
165
|
+
const penetration = contactRadius - dist;
|
|
121
166
|
// Push particle to sphere surface
|
|
122
|
-
|
|
167
|
+
if (dist > 0) {
|
|
168
|
+
toParticle.scaleBy(1 / dist);
|
|
169
|
+
} else {
|
|
170
|
+
toParticle.setXYZ(0, 1, 0);
|
|
171
|
+
}
|
|
123
172
|
toParticle.scaleBy(penetration);
|
|
124
173
|
Vector3.add(particlePos, toParticle, particlePos);
|
|
125
174
|
return true;
|
|
@@ -131,7 +180,8 @@ import { Vector3 } from '@zephyr3d/base';
|
|
|
131
180
|
* @returns true if collision occurred
|
|
132
181
|
*
|
|
133
182
|
* @public
|
|
134
|
-
*/ function resolveCapsuleCollision(particlePos, collider) {
|
|
183
|
+
*/ function resolveCapsuleCollision(particlePos, collider, particleRadius = 0) {
|
|
184
|
+
const contactRadius = collider.radius + Math.max(0, particleRadius);
|
|
135
185
|
// Find closest point on capsule axis
|
|
136
186
|
const axis = Vector3.sub(collider.end, collider.start, new Vector3());
|
|
137
187
|
const axisLength = axis.magnitude;
|
|
@@ -139,11 +189,15 @@ import { Vector3 } from '@zephyr3d/base';
|
|
|
139
189
|
// Degenerate capsule, treat as sphere
|
|
140
190
|
const toParticle = Vector3.sub(particlePos, collider.start, new Vector3());
|
|
141
191
|
const distSq = toParticle.magnitudeSq;
|
|
142
|
-
const radiusSq =
|
|
143
|
-
if (distSq < radiusSq
|
|
144
|
-
const dist = Math.sqrt(distSq);
|
|
145
|
-
const penetration =
|
|
146
|
-
|
|
192
|
+
const radiusSq = contactRadius * contactRadius;
|
|
193
|
+
if (distSq < radiusSq) {
|
|
194
|
+
const dist = distSq > COLLISION_DISTANCE_EPSILON_SQ ? Math.sqrt(distSq) : 0;
|
|
195
|
+
const penetration = contactRadius - dist;
|
|
196
|
+
if (dist > 0) {
|
|
197
|
+
toParticle.scaleBy(1 / dist);
|
|
198
|
+
} else {
|
|
199
|
+
toParticle.setXYZ(0, 1, 0);
|
|
200
|
+
}
|
|
147
201
|
toParticle.scaleBy(penetration);
|
|
148
202
|
Vector3.add(particlePos, toParticle, particlePos);
|
|
149
203
|
return true;
|
|
@@ -160,11 +214,15 @@ import { Vector3 } from '@zephyr3d/base';
|
|
|
160
214
|
// Check distance from closest point
|
|
161
215
|
const toParticleFromAxis = Vector3.sub(particlePos, closestPoint, new Vector3());
|
|
162
216
|
const distSq = toParticleFromAxis.magnitudeSq;
|
|
163
|
-
const radiusSq =
|
|
164
|
-
if (distSq < radiusSq
|
|
165
|
-
const dist = Math.sqrt(distSq);
|
|
166
|
-
const penetration =
|
|
167
|
-
|
|
217
|
+
const radiusSq = contactRadius * contactRadius;
|
|
218
|
+
if (distSq < radiusSq) {
|
|
219
|
+
const dist = distSq > COLLISION_DISTANCE_EPSILON_SQ ? Math.sqrt(distSq) : 0;
|
|
220
|
+
const penetration = contactRadius - dist;
|
|
221
|
+
if (dist > 0) {
|
|
222
|
+
toParticleFromAxis.scaleBy(1 / dist);
|
|
223
|
+
} else {
|
|
224
|
+
getCapsuleAxisFallbackNormal(axis, toParticleFromAxis);
|
|
225
|
+
}
|
|
168
226
|
toParticleFromAxis.scaleBy(penetration);
|
|
169
227
|
Vector3.add(particlePos, toParticleFromAxis, particlePos);
|
|
170
228
|
return true;
|
|
@@ -176,17 +234,60 @@ import { Vector3 } from '@zephyr3d/base';
|
|
|
176
234
|
* @returns true if collision occurred
|
|
177
235
|
*
|
|
178
236
|
* @public
|
|
179
|
-
*/ function resolvePlaneCollision(particlePos, collider) {
|
|
237
|
+
*/ function resolvePlaneCollision(particlePos, collider, particleRadius = 0) {
|
|
180
238
|
const toParticle = Vector3.sub(particlePos, collider.point, new Vector3());
|
|
181
239
|
const distance = Vector3.dot(toParticle, collider.normal);
|
|
182
|
-
|
|
240
|
+
const contactDistance = Math.max(0, particleRadius);
|
|
241
|
+
if (distance < contactDistance) {
|
|
183
242
|
// Particle is below plane, push it up
|
|
184
|
-
const correction = Vector3.scale(collider.normal, -distance, new Vector3());
|
|
243
|
+
const correction = Vector3.scale(collider.normal, contactDistance - distance, new Vector3());
|
|
185
244
|
Vector3.add(particlePos, correction, particlePos);
|
|
186
245
|
return true;
|
|
187
246
|
}
|
|
188
247
|
return false;
|
|
189
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* Resolves collision between a particle and an oriented box collider.
|
|
251
|
+
* @returns true if collision occurred
|
|
252
|
+
*
|
|
253
|
+
* @public
|
|
254
|
+
*/ function resolveBoxCollision(particlePos, collider, particleRadius = 0) {
|
|
255
|
+
const delta = Vector3.sub(particlePos, collider.center, new Vector3());
|
|
256
|
+
const local = new Vector3(Vector3.dot(delta, collider.axes[0]), Vector3.dot(delta, collider.axes[1]), Vector3.dot(delta, collider.axes[2]));
|
|
257
|
+
const radius = Math.max(0, particleRadius);
|
|
258
|
+
const inside = Math.abs(local.x) <= collider.halfExtents.x && Math.abs(local.y) <= collider.halfExtents.y && Math.abs(local.z) <= collider.halfExtents.z;
|
|
259
|
+
if (!inside) {
|
|
260
|
+
if (radius <= 0) {
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
const closest = new Vector3(Math.max(-collider.halfExtents.x, Math.min(collider.halfExtents.x, local.x)), Math.max(-collider.halfExtents.y, Math.min(collider.halfExtents.y, local.y)), Math.max(-collider.halfExtents.z, Math.min(collider.halfExtents.z, local.z)));
|
|
264
|
+
const fromClosest = Vector3.sub(local, closest, new Vector3());
|
|
265
|
+
const distanceSq = fromClosest.magnitudeSq;
|
|
266
|
+
if (distanceSq >= radius * radius || distanceSq <= COLLISION_DISTANCE_EPSILON_SQ) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
const distance = Math.sqrt(distanceSq);
|
|
270
|
+
fromClosest.scaleBy((radius - distance) / distance);
|
|
271
|
+
Vector3.add(particlePos, Vector3.add(Vector3.scale(collider.axes[0], fromClosest.x, new Vector3()), Vector3.add(Vector3.scale(collider.axes[1], fromClosest.y, new Vector3()), Vector3.scale(collider.axes[2], fromClosest.z, new Vector3()), new Vector3()), new Vector3()), particlePos);
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
const penetration = new Vector3(collider.halfExtents.x - Math.abs(local.x) + radius, collider.halfExtents.y - Math.abs(local.y) + radius, collider.halfExtents.z - Math.abs(local.z) + radius);
|
|
275
|
+
let axis = 0;
|
|
276
|
+
let minPenetration = penetration.x;
|
|
277
|
+
if (penetration.y < minPenetration) {
|
|
278
|
+
axis = 1;
|
|
279
|
+
minPenetration = penetration.y;
|
|
280
|
+
}
|
|
281
|
+
if (penetration.z < minPenetration) {
|
|
282
|
+
axis = 2;
|
|
283
|
+
minPenetration = penetration.z;
|
|
284
|
+
}
|
|
285
|
+
const localAxis = axis === 0 ? local.x : axis === 1 ? local.y : local.z;
|
|
286
|
+
const sign = localAxis < 0 ? -1 : 1;
|
|
287
|
+
const correction = Vector3.scale(collider.axes[axis], minPenetration * sign, new Vector3());
|
|
288
|
+
Vector3.add(particlePos, correction, particlePos);
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
190
291
|
/**
|
|
191
292
|
* Updates collider position from its associated node
|
|
192
293
|
*
|
|
@@ -256,8 +357,45 @@ import { Vector3 } from '@zephyr3d/base';
|
|
|
256
357
|
}
|
|
257
358
|
break;
|
|
258
359
|
}
|
|
360
|
+
case 'box':
|
|
361
|
+
{
|
|
362
|
+
const box = collider;
|
|
363
|
+
if (box.localOffset) {
|
|
364
|
+
worldMatrix.transformPointAffine(box.localOffset, box.center);
|
|
365
|
+
} else {
|
|
366
|
+
box.center.x = worldMatrix.m03;
|
|
367
|
+
box.center.y = worldMatrix.m13;
|
|
368
|
+
box.center.z = worldMatrix.m23;
|
|
369
|
+
}
|
|
370
|
+
const axes = createWorldAxes(worldMatrix);
|
|
371
|
+
box.axes[0].set(axes[0]);
|
|
372
|
+
box.axes[1].set(axes[1]);
|
|
373
|
+
box.axes[2].set(axes[2]);
|
|
374
|
+
if (box.localHalfExtents) {
|
|
375
|
+
const scales = getAxisScales(worldMatrix);
|
|
376
|
+
box.halfExtents.setXYZ(box.localHalfExtents.x * scales.x, box.localHalfExtents.y * scales.y, box.localHalfExtents.z * scales.z);
|
|
377
|
+
}
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
259
380
|
}
|
|
260
381
|
}
|
|
382
|
+
function createWorldAxes(worldMatrix) {
|
|
383
|
+
const x = worldMatrix.transformVectorAffine(Vector3.axisPX(), new Vector3()).inplaceNormalize();
|
|
384
|
+
const y = worldMatrix.transformVectorAffine(Vector3.axisPY(), new Vector3()).inplaceNormalize();
|
|
385
|
+
const z = worldMatrix.transformVectorAffine(Vector3.axisPZ(), new Vector3()).inplaceNormalize();
|
|
386
|
+
return [
|
|
387
|
+
x,
|
|
388
|
+
y,
|
|
389
|
+
z
|
|
390
|
+
];
|
|
391
|
+
}
|
|
392
|
+
function getAxisScales(worldMatrix) {
|
|
393
|
+
return {
|
|
394
|
+
x: Math.max(1e-6, worldMatrix.transformVectorAffine(Vector3.axisPX(), new Vector3()).magnitude),
|
|
395
|
+
y: Math.max(1e-6, worldMatrix.transformVectorAffine(Vector3.axisPY(), new Vector3()).magnitude),
|
|
396
|
+
z: Math.max(1e-6, worldMatrix.transformVectorAffine(Vector3.axisPZ(), new Vector3()).magnitude)
|
|
397
|
+
};
|
|
398
|
+
}
|
|
261
399
|
function getUniformScale(worldMatrix) {
|
|
262
400
|
const sx = worldMatrix.transformVectorAffine(Vector3.axisPX(), new Vector3()).magnitude;
|
|
263
401
|
const sy = worldMatrix.transformVectorAffine(Vector3.axisPY(), new Vector3()).magnitude;
|
|
@@ -274,5 +412,5 @@ function getPerpendicularScale(worldMatrix, axisLocal) {
|
|
|
274
412
|
return Math.max(1e-6, (su + sv) * 0.5);
|
|
275
413
|
}
|
|
276
414
|
|
|
277
|
-
export { createCapsuleCollider, createPlaneCollider, createSphereCollider, resolveCapsuleCollision, resolvePlaneCollision, resolveSphereCollision, updateColliderFromNode };
|
|
415
|
+
export { createBoxCollider, createCapsuleCollider, createPlaneCollider, createSphereCollider, resolveBoxCollision, resolveCapsuleCollision, resolvePlaneCollision, resolveSphereCollision, updateColliderFromNode };
|
|
278
416
|
//# sourceMappingURL=spring_collider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spring_collider.js","sources":["../../../src/animation/spring/spring_collider.ts"],"sourcesContent":["import type { Nullable } from '@zephyr3d/base';\r\nimport { Vector3 } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../../scene/scene_node';\r\n\r\n/**\r\n * Base interface for spring collision shapes\r\n *\r\n * @public\r\n */\r\nexport interface SpringCollider {\r\n /** Type of collider */\r\n type: 'sphere' | 'capsule' | 'plane';\r\n /** Associated scene node (optional, for dynamic colliders) */\r\n node?: Nullable<SceneNode>;\r\n /** Whether this collider is enabled */\r\n enabled: boolean;\r\n}\r\n\r\n/**\r\n * Sphere collider for spring collision detection\r\n *\r\n * @public\r\n */\r\nexport interface SphereCollider extends SpringCollider {\r\n type: 'sphere';\r\n /** Center position in world space */\r\n center: Vector3;\r\n /** Radius of the sphere */\r\n radius: number;\r\n /** Authoring-space radius before node scaling (if node is set) */\r\n localRadius?: number;\r\n /** Baseline world scale captured at creation for backward compatibility */\r\n localRadiusScaleRef?: number;\r\n /** Local offset from node (if node is set) */\r\n localOffset?: Vector3;\r\n}\r\n\r\n/**\r\n * Capsule collider for spring collision detection\r\n *\r\n * @public\r\n */\r\nexport interface CapsuleCollider extends SpringCollider {\r\n type: 'capsule';\r\n /** Start point of the capsule axis in world space */\r\n start: Vector3;\r\n /** End point of the capsule axis in world space */\r\n end: Vector3;\r\n /** Radius of the capsule */\r\n radius: number;\r\n /** Authoring-space radius before node scaling (if node is set) */\r\n localRadius?: number;\r\n /** Baseline perpendicular scale captured at creation for backward compatibility */\r\n localRadiusScaleRef?: number;\r\n /** Local start offset from node (if node is set) */\r\n localStartOffset?: Vector3;\r\n /** Local end offset from node (if node is set) */\r\n localEndOffset?: Vector3;\r\n}\r\n\r\n/**\r\n * Plane collider for spring collision detection\r\n *\r\n * @public\r\n */\r\nexport interface PlaneCollider extends SpringCollider {\r\n type: 'plane';\r\n /** Point on the plane in world space */\r\n point: Vector3;\r\n /** Normal vector of the plane (should be normalized) */\r\n normal: Vector3;\r\n /** Local point offset from node (if node is set) */\r\n localPointOffset?: Vector3;\r\n /** Local normal direction (if node is set) */\r\n localNormal?: Vector3;\r\n}\r\n\r\n/**\r\n * Creates a sphere collider\r\n * @param centerOrOffset - Center position in world space, or local offset if node is provided\r\n * @param radius - Radius of the sphere\r\n * @param node - Optional scene node to attach to (if provided, centerOrOffset is treated as local offset)\r\n *\r\n * @public\r\n */\r\nexport function createSphereCollider(\r\n centerOrOffset: Vector3,\r\n radius: number,\r\n node?: SceneNode\r\n): SphereCollider {\r\n if (node) {\r\n // If node is provided, treat centerOrOffset as local offset\r\n const worldMatrix = node.worldMatrix;\r\n const worldCenter = worldMatrix.transformPointAffine(centerOrOffset, new Vector3());\r\n\r\n return {\r\n type: 'sphere',\r\n center: worldCenter,\r\n radius,\r\n localRadius: radius,\r\n localRadiusScaleRef: getUniformScale(worldMatrix),\r\n node,\r\n enabled: true,\r\n localOffset: centerOrOffset.clone()\r\n };\r\n } else {\r\n // No node, use as world position\r\n return {\r\n type: 'sphere',\r\n center: centerOrOffset.clone(),\r\n radius,\r\n node: null,\r\n enabled: true\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Creates a capsule collider\r\n * @param startOrOffset - Start point in world space, or local offset if node is provided\r\n * @param endOrOffset - End point in world space, or local offset if node is provided\r\n * @param radius - Radius of the capsule\r\n * @param node - Optional scene node to attach to (if provided, offsets are treated as local)\r\n *\r\n * @public\r\n */\r\nexport function createCapsuleCollider(\r\n startOrOffset: Vector3,\r\n endOrOffset: Vector3,\r\n radius: number,\r\n node?: SceneNode\r\n): CapsuleCollider {\r\n if (node) {\r\n // If node is provided, treat as local offsets\r\n const worldMatrix = node.worldMatrix;\r\n const worldStart = worldMatrix.transformPointAffine(startOrOffset, new Vector3());\r\n const worldEnd = worldMatrix.transformPointAffine(endOrOffset, new Vector3());\r\n\r\n return {\r\n type: 'capsule',\r\n start: worldStart,\r\n end: worldEnd,\r\n radius,\r\n localRadius: radius,\r\n localRadiusScaleRef: getPerpendicularScale(\r\n worldMatrix,\r\n Vector3.sub(endOrOffset, startOrOffset, new Vector3())\r\n ),\r\n node,\r\n enabled: true,\r\n localStartOffset: startOrOffset.clone(),\r\n localEndOffset: endOrOffset.clone()\r\n };\r\n } else {\r\n // No node, use as world positions\r\n return {\r\n type: 'capsule',\r\n start: startOrOffset.clone(),\r\n end: endOrOffset.clone(),\r\n radius,\r\n node: null,\r\n enabled: true\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Creates a plane collider\r\n * @param pointOrOffset - Point on plane in world space, or local offset if node is provided\r\n * @param normal - Normal vector (will be normalized)\r\n * @param node - Optional scene node to attach to (if provided, pointOrOffset is treated as local offset)\r\n *\r\n * @public\r\n */\r\nexport function createPlaneCollider(\r\n pointOrOffset: Vector3,\r\n normal: Vector3,\r\n node?: SceneNode\r\n): PlaneCollider {\r\n const normalizedNormal = new Vector3();\r\n Vector3.normalize(normal, normalizedNormal);\r\n\r\n if (node) {\r\n // If node is provided, treat as local offset\r\n const worldMatrix = node.worldMatrix;\r\n const worldPoint = worldMatrix.transformPointAffine(pointOrOffset, new Vector3());\r\n\r\n return {\r\n type: 'plane',\r\n point: worldPoint,\r\n normal: normalizedNormal.clone(),\r\n node,\r\n enabled: true,\r\n localPointOffset: pointOrOffset.clone(),\r\n localNormal: normalizedNormal.clone()\r\n };\r\n } else {\r\n // No node, use as world position\r\n return {\r\n type: 'plane',\r\n point: pointOrOffset.clone(),\r\n normal: normalizedNormal,\r\n node: null,\r\n enabled: true\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and a sphere collider\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolveSphereCollision(particlePos: Vector3, collider: SphereCollider): boolean {\r\n const toParticle = Vector3.sub(particlePos, collider.center, new Vector3());\r\n const distSq = toParticle.magnitudeSq;\r\n const radiusSq = collider.radius * collider.radius;\r\n\r\n if (distSq < radiusSq && distSq > 0.0001) {\r\n // Particle is inside sphere, push it out\r\n const dist = Math.sqrt(distSq);\r\n const penetration = collider.radius - dist;\r\n\r\n // Push particle to sphere surface\r\n Vector3.normalize(toParticle, toParticle);\r\n toParticle.scaleBy(penetration);\r\n Vector3.add(particlePos, toParticle, particlePos);\r\n\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and a capsule collider\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolveCapsuleCollision(particlePos: Vector3, collider: CapsuleCollider): boolean {\r\n // Find closest point on capsule axis\r\n const axis = Vector3.sub(collider.end, collider.start, new Vector3());\r\n const axisLength = axis.magnitude;\r\n\r\n if (axisLength < 0.0001) {\r\n // Degenerate capsule, treat as sphere\r\n const toParticle = Vector3.sub(particlePos, collider.start, new Vector3());\r\n const distSq = toParticle.magnitudeSq;\r\n const radiusSq = collider.radius * collider.radius;\r\n\r\n if (distSq < radiusSq && distSq > 0.0001) {\r\n const dist = Math.sqrt(distSq);\r\n const penetration = collider.radius - dist;\r\n Vector3.normalize(toParticle, toParticle);\r\n toParticle.scaleBy(penetration);\r\n Vector3.add(particlePos, toParticle, particlePos);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n Vector3.normalize(axis, axis);\r\n\r\n const toParticle = Vector3.sub(particlePos, collider.start, new Vector3());\r\n const projection = Vector3.dot(toParticle, axis);\r\n\r\n // Clamp projection to capsule length\r\n const t = Math.max(0, Math.min(axisLength, projection));\r\n\r\n // Closest point on capsule axis\r\n const closestPoint = Vector3.add(collider.start, Vector3.scale(axis, t, new Vector3()), new Vector3());\r\n\r\n // Check distance from closest point\r\n const toParticleFromAxis = Vector3.sub(particlePos, closestPoint, new Vector3());\r\n const distSq = toParticleFromAxis.magnitudeSq;\r\n const radiusSq = collider.radius * collider.radius;\r\n\r\n if (distSq < radiusSq && distSq > 0.0001) {\r\n const dist = Math.sqrt(distSq);\r\n const penetration = collider.radius - dist;\r\n Vector3.normalize(toParticleFromAxis, toParticleFromAxis);\r\n toParticleFromAxis.scaleBy(penetration);\r\n Vector3.add(particlePos, toParticleFromAxis, particlePos);\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and a plane collider\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolvePlaneCollision(particlePos: Vector3, collider: PlaneCollider): boolean {\r\n const toParticle = Vector3.sub(particlePos, collider.point, new Vector3());\r\n const distance = Vector3.dot(toParticle, collider.normal);\r\n\r\n if (distance < 0) {\r\n // Particle is below plane, push it up\r\n const correction = Vector3.scale(collider.normal, -distance, new Vector3());\r\n Vector3.add(particlePos, correction, particlePos);\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Updates collider position from its associated node\r\n *\r\n * @public\r\n */\r\nexport function updateColliderFromNode(collider: SpringCollider, runtimeNode?: Nullable<SceneNode>): void {\r\n const node = runtimeNode ?? collider.node;\r\n if (!node || !collider.enabled) {\r\n return;\r\n }\r\n\r\n const worldMatrix = node.worldMatrix;\r\n\r\n switch (collider.type) {\r\n case 'sphere': {\r\n const sphere = collider as SphereCollider;\r\n if (sphere.localRadius !== undefined) {\r\n const currentScale = getUniformScale(worldMatrix);\r\n const refScale = Math.max(1e-6, sphere.localRadiusScaleRef ?? 1);\r\n sphere.radius = sphere.localRadius * (currentScale / refScale);\r\n }\r\n if (sphere.localOffset) {\r\n // Transform local offset to world space\r\n worldMatrix.transformPointAffine(sphere.localOffset, sphere.center);\r\n } else {\r\n // No local offset, just use node position\r\n sphere.center.x = worldMatrix.m03;\r\n sphere.center.y = worldMatrix.m13;\r\n sphere.center.z = worldMatrix.m23;\r\n }\r\n break;\r\n }\r\n\r\n case 'capsule': {\r\n const capsule = collider as CapsuleCollider;\r\n if (capsule.localRadius !== undefined) {\r\n const axisLocal =\r\n capsule.localStartOffset && capsule.localEndOffset\r\n ? Vector3.sub(capsule.localEndOffset, capsule.localStartOffset, new Vector3())\r\n : Vector3.axisPY();\r\n const currentScale = getPerpendicularScale(worldMatrix, axisLocal);\r\n const refScale = Math.max(1e-6, capsule.localRadiusScaleRef ?? 1);\r\n capsule.radius = capsule.localRadius * (currentScale / refScale);\r\n }\r\n if (capsule.localStartOffset && capsule.localEndOffset) {\r\n // Transform local offsets to world space\r\n worldMatrix.transformPointAffine(capsule.localStartOffset, capsule.start);\r\n worldMatrix.transformPointAffine(capsule.localEndOffset, capsule.end);\r\n } else {\r\n // No local offsets, just use node position for start\r\n capsule.start.x = worldMatrix.m03;\r\n capsule.start.y = worldMatrix.m13;\r\n capsule.start.z = worldMatrix.m23;\r\n }\r\n break;\r\n }\r\n\r\n case 'plane': {\r\n const plane = collider as PlaneCollider;\r\n if (plane.localPointOffset) {\r\n // Transform local offset to world space\r\n worldMatrix.transformPointAffine(plane.localPointOffset, plane.point);\r\n } else {\r\n // No local offset, just use node position\r\n plane.point.x = worldMatrix.m03;\r\n plane.point.y = worldMatrix.m13;\r\n plane.point.z = worldMatrix.m23;\r\n }\r\n\r\n if (plane.localNormal) {\r\n // Transform local normal to world space (rotation only)\r\n worldMatrix.transformVectorAffine(plane.localNormal, plane.normal).inplaceNormalize();\r\n }\r\n break;\r\n }\r\n }\r\n}\r\n\r\nfunction getUniformScale(worldMatrix: any): number {\r\n const sx = worldMatrix.transformVectorAffine(Vector3.axisPX(), new Vector3()).magnitude;\r\n const sy = worldMatrix.transformVectorAffine(Vector3.axisPY(), new Vector3()).magnitude;\r\n const sz = worldMatrix.transformVectorAffine(Vector3.axisPZ(), new Vector3()).magnitude;\r\n return Math.max(1e-6, (sx + sy + sz) / 3);\r\n}\r\n\r\nfunction getPerpendicularScale(worldMatrix: any, axisLocal: Vector3): number {\r\n const axis = axisLocal.magnitudeSq > 1e-8 ? axisLocal.clone().inplaceNormalize() : Vector3.axisPY();\r\n const helper = Math.abs(axis.y) < 0.99 ? Vector3.axisPY() : Vector3.axisPX();\r\n const u = Vector3.cross(axis, helper, new Vector3()).inplaceNormalize();\r\n const v = Vector3.cross(axis, u, new Vector3()).inplaceNormalize();\r\n const su = worldMatrix.transformVectorAffine(u, new Vector3()).magnitude;\r\n const sv = worldMatrix.transformVectorAffine(v, new Vector3()).magnitude;\r\n return Math.max(1e-6, (su + sv) * 0.5);\r\n}\r\n"],"names":["createSphereCollider","centerOrOffset","radius","node","worldMatrix","worldCenter","transformPointAffine","Vector3","type","center","localRadius","localRadiusScaleRef","getUniformScale","enabled","localOffset","clone","createCapsuleCollider","startOrOffset","endOrOffset","worldStart","worldEnd","start","end","getPerpendicularScale","sub","localStartOffset","localEndOffset","createPlaneCollider","pointOrOffset","normal","normalizedNormal","normalize","worldPoint","point","localPointOffset","localNormal","resolveSphereCollision","particlePos","collider","toParticle","distSq","magnitudeSq","radiusSq","dist","Math","sqrt","penetration","scaleBy","add","resolveCapsuleCollision","axis","axisLength","magnitude","projection","dot","t","max","min","closestPoint","scale","toParticleFromAxis","resolvePlaneCollision","distance","correction","updateColliderFromNode","runtimeNode","sphere","undefined","currentScale","refScale","x","m03","y","m13","z","m23","capsule","axisLocal","axisPY","plane","transformVectorAffine","inplaceNormalize","sx","axisPX","sy","sz","axisPZ","helper","abs","u","cross","v","su","sv"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"spring_collider.js","sources":["../../../src/animation/spring/spring_collider.ts"],"sourcesContent":["import type { Nullable } from '@zephyr3d/base';\r\nimport { Vector3 } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../../scene/scene_node';\r\n\r\nconst COLLISION_DISTANCE_EPSILON_SQ = 1e-12;\r\n\r\nfunction getCapsuleAxisFallbackNormal(axis: Vector3, result: Vector3): Vector3 {\r\n const reference = Math.abs(axis.z) < 0.9 ? Vector3.axisPZ() : Vector3.axisPX();\r\n Vector3.sub(reference, Vector3.scale(axis, Vector3.dot(reference, axis), result), result);\r\n return result.inplaceNormalize();\r\n}\r\n\r\n/**\r\n * Base interface for spring collision shapes\r\n *\r\n * @public\r\n */\r\nexport interface SpringCollider {\r\n /** Type of collider */\r\n type: 'sphere' | 'capsule' | 'plane' | 'box';\r\n /** Associated scene node (optional, for dynamic colliders) */\r\n node?: Nullable<SceneNode>;\r\n /** Whether this collider is enabled */\r\n enabled: boolean;\r\n}\r\n\r\n/**\r\n * Sphere collider for spring collision detection\r\n *\r\n * @public\r\n */\r\nexport interface SphereCollider extends SpringCollider {\r\n type: 'sphere';\r\n /** Center position in world space */\r\n center: Vector3;\r\n /** Radius of the sphere */\r\n radius: number;\r\n /** Authoring-space radius before node scaling (if node is set) */\r\n localRadius?: number;\r\n /** Baseline world scale captured at creation for backward compatibility */\r\n localRadiusScaleRef?: number;\r\n /** Local offset from node (if node is set) */\r\n localOffset?: Vector3;\r\n}\r\n\r\n/**\r\n * Capsule collider for spring collision detection\r\n *\r\n * @public\r\n */\r\nexport interface CapsuleCollider extends SpringCollider {\r\n type: 'capsule';\r\n /** Start point of the capsule axis in world space */\r\n start: Vector3;\r\n /** End point of the capsule axis in world space */\r\n end: Vector3;\r\n /** Radius of the capsule */\r\n radius: number;\r\n /** Authoring-space radius before node scaling (if node is set) */\r\n localRadius?: number;\r\n /** Baseline perpendicular scale captured at creation for backward compatibility */\r\n localRadiusScaleRef?: number;\r\n /** Local start offset from node (if node is set) */\r\n localStartOffset?: Vector3;\r\n /** Local end offset from node (if node is set) */\r\n localEndOffset?: Vector3;\r\n}\r\n\r\n/**\r\n * Plane collider for spring collision detection\r\n *\r\n * @public\r\n */\r\nexport interface PlaneCollider extends SpringCollider {\r\n type: 'plane';\r\n /** Point on the plane in world space */\r\n point: Vector3;\r\n /** Normal vector of the plane (should be normalized) */\r\n normal: Vector3;\r\n /** Local point offset from node (if node is set) */\r\n localPointOffset?: Vector3;\r\n /** Local normal direction (if node is set) */\r\n localNormal?: Vector3;\r\n}\r\n\r\n/**\r\n * Oriented box collider for spring collision detection.\r\n *\r\n * The three axes are normalized world-space directions and halfExtents are\r\n * measured along the corresponding axes.\r\n *\r\n * @public\r\n */\r\nexport interface BoxCollider extends SpringCollider {\r\n type: 'box';\r\n /** Center position in world space */\r\n center: Vector3;\r\n /** World-space half extents along each local axis */\r\n halfExtents: Vector3;\r\n /** Normalized world-space local X/Y/Z axes */\r\n axes: [Vector3, Vector3, Vector3];\r\n /** Local center offset from node */\r\n localOffset?: Vector3;\r\n /** Authoring-space half extents before node scaling */\r\n localHalfExtents?: Vector3;\r\n}\r\n\r\n/**\r\n * Creates a sphere collider\r\n * @param centerOrOffset - Center position in world space, or local offset if node is provided\r\n * @param radius - Radius of the sphere\r\n * @param node - Optional scene node to attach to (if provided, centerOrOffset is treated as local offset)\r\n *\r\n * @public\r\n */\r\nexport function createSphereCollider(\r\n centerOrOffset: Vector3,\r\n radius: number,\r\n node?: SceneNode\r\n): SphereCollider {\r\n if (node) {\r\n // If node is provided, treat centerOrOffset as local offset\r\n const worldMatrix = node.worldMatrix;\r\n const worldCenter = worldMatrix.transformPointAffine(centerOrOffset, new Vector3());\r\n\r\n return {\r\n type: 'sphere',\r\n center: worldCenter,\r\n radius,\r\n localRadius: radius,\r\n localRadiusScaleRef: getUniformScale(worldMatrix),\r\n node,\r\n enabled: true,\r\n localOffset: centerOrOffset.clone()\r\n };\r\n } else {\r\n // No node, use as world position\r\n return {\r\n type: 'sphere',\r\n center: centerOrOffset.clone(),\r\n radius,\r\n node: null,\r\n enabled: true\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Creates a capsule collider\r\n * @param startOrOffset - Start point in world space, or local offset if node is provided\r\n * @param endOrOffset - End point in world space, or local offset if node is provided\r\n * @param radius - Radius of the capsule\r\n * @param node - Optional scene node to attach to (if provided, offsets are treated as local)\r\n *\r\n * @public\r\n */\r\nexport function createCapsuleCollider(\r\n startOrOffset: Vector3,\r\n endOrOffset: Vector3,\r\n radius: number,\r\n node?: SceneNode\r\n): CapsuleCollider {\r\n if (node) {\r\n // If node is provided, treat as local offsets\r\n const worldMatrix = node.worldMatrix;\r\n const worldStart = worldMatrix.transformPointAffine(startOrOffset, new Vector3());\r\n const worldEnd = worldMatrix.transformPointAffine(endOrOffset, new Vector3());\r\n\r\n return {\r\n type: 'capsule',\r\n start: worldStart,\r\n end: worldEnd,\r\n radius,\r\n localRadius: radius,\r\n localRadiusScaleRef: getPerpendicularScale(\r\n worldMatrix,\r\n Vector3.sub(endOrOffset, startOrOffset, new Vector3())\r\n ),\r\n node,\r\n enabled: true,\r\n localStartOffset: startOrOffset.clone(),\r\n localEndOffset: endOrOffset.clone()\r\n };\r\n } else {\r\n // No node, use as world positions\r\n return {\r\n type: 'capsule',\r\n start: startOrOffset.clone(),\r\n end: endOrOffset.clone(),\r\n radius,\r\n node: null,\r\n enabled: true\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Creates a plane collider\r\n * @param pointOrOffset - Point on plane in world space, or local offset if node is provided\r\n * @param normal - Normal vector (will be normalized)\r\n * @param node - Optional scene node to attach to (if provided, pointOrOffset is treated as local offset)\r\n *\r\n * @public\r\n */\r\nexport function createPlaneCollider(\r\n pointOrOffset: Vector3,\r\n normal: Vector3,\r\n node?: SceneNode\r\n): PlaneCollider {\r\n const normalizedNormal = new Vector3();\r\n Vector3.normalize(normal, normalizedNormal);\r\n\r\n if (node) {\r\n // If node is provided, treat as local offset\r\n const worldMatrix = node.worldMatrix;\r\n const worldPoint = worldMatrix.transformPointAffine(pointOrOffset, new Vector3());\r\n\r\n return {\r\n type: 'plane',\r\n point: worldPoint,\r\n normal: normalizedNormal.clone(),\r\n node,\r\n enabled: true,\r\n localPointOffset: pointOrOffset.clone(),\r\n localNormal: normalizedNormal.clone()\r\n };\r\n } else {\r\n // No node, use as world position\r\n return {\r\n type: 'plane',\r\n point: pointOrOffset.clone(),\r\n normal: normalizedNormal,\r\n node: null,\r\n enabled: true\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Creates an oriented box collider.\r\n * @param centerOrOffset - Center position in world space, or local offset if node is provided\r\n * @param halfExtents - Local/world half extents of the box\r\n * @param node - Optional scene node to attach to\r\n *\r\n * @public\r\n */\r\nexport function createBoxCollider(\r\n centerOrOffset: Vector3,\r\n halfExtents: Vector3,\r\n node?: SceneNode\r\n): BoxCollider {\r\n const localExtents = new Vector3(\r\n Math.max(0.0001, Math.abs(halfExtents.x)),\r\n Math.max(0.0001, Math.abs(halfExtents.y)),\r\n Math.max(0.0001, Math.abs(halfExtents.z))\r\n );\r\n if (node) {\r\n const worldMatrix = node.worldMatrix;\r\n const center = worldMatrix.transformPointAffine(centerOrOffset, new Vector3());\r\n const axes = createWorldAxes(worldMatrix);\r\n const scales = getAxisScales(worldMatrix);\r\n return {\r\n type: 'box',\r\n center,\r\n halfExtents: new Vector3(\r\n localExtents.x * scales.x,\r\n localExtents.y * scales.y,\r\n localExtents.z * scales.z\r\n ),\r\n axes,\r\n localOffset: centerOrOffset.clone(),\r\n localHalfExtents: localExtents,\r\n node,\r\n enabled: true\r\n };\r\n }\r\n return {\r\n type: 'box',\r\n center: centerOrOffset.clone(),\r\n halfExtents: localExtents,\r\n axes: [Vector3.axisPX(), Vector3.axisPY(), Vector3.axisPZ()],\r\n node: null,\r\n enabled: true\r\n };\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and a sphere collider\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolveSphereCollision(\r\n particlePos: Vector3,\r\n collider: SphereCollider,\r\n particleRadius: number = 0\r\n): boolean {\r\n const toParticle = Vector3.sub(particlePos, collider.center, new Vector3());\r\n const distSq = toParticle.magnitudeSq;\r\n const contactRadius = collider.radius + Math.max(0, particleRadius);\r\n const radiusSq = contactRadius * contactRadius;\r\n\r\n if (distSq < radiusSq) {\r\n // Particle is inside sphere, push it out\r\n const dist = distSq > COLLISION_DISTANCE_EPSILON_SQ ? Math.sqrt(distSq) : 0;\r\n const penetration = contactRadius - dist;\r\n\r\n // Push particle to sphere surface\r\n if (dist > 0) {\r\n toParticle.scaleBy(1 / dist);\r\n } else {\r\n toParticle.setXYZ(0, 1, 0);\r\n }\r\n toParticle.scaleBy(penetration);\r\n Vector3.add(particlePos, toParticle, particlePos);\r\n\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and a capsule collider\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolveCapsuleCollision(\r\n particlePos: Vector3,\r\n collider: CapsuleCollider,\r\n particleRadius: number = 0\r\n): boolean {\r\n const contactRadius = collider.radius + Math.max(0, particleRadius);\r\n // Find closest point on capsule axis\r\n const axis = Vector3.sub(collider.end, collider.start, new Vector3());\r\n const axisLength = axis.magnitude;\r\n\r\n if (axisLength < 0.0001) {\r\n // Degenerate capsule, treat as sphere\r\n const toParticle = Vector3.sub(particlePos, collider.start, new Vector3());\r\n const distSq = toParticle.magnitudeSq;\r\n const radiusSq = contactRadius * contactRadius;\r\n\r\n if (distSq < radiusSq) {\r\n const dist = distSq > COLLISION_DISTANCE_EPSILON_SQ ? Math.sqrt(distSq) : 0;\r\n const penetration = contactRadius - dist;\r\n if (dist > 0) {\r\n toParticle.scaleBy(1 / dist);\r\n } else {\r\n toParticle.setXYZ(0, 1, 0);\r\n }\r\n toParticle.scaleBy(penetration);\r\n Vector3.add(particlePos, toParticle, particlePos);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n Vector3.normalize(axis, axis);\r\n\r\n const toParticle = Vector3.sub(particlePos, collider.start, new Vector3());\r\n const projection = Vector3.dot(toParticle, axis);\r\n\r\n // Clamp projection to capsule length\r\n const t = Math.max(0, Math.min(axisLength, projection));\r\n\r\n // Closest point on capsule axis\r\n const closestPoint = Vector3.add(collider.start, Vector3.scale(axis, t, new Vector3()), new Vector3());\r\n\r\n // Check distance from closest point\r\n const toParticleFromAxis = Vector3.sub(particlePos, closestPoint, new Vector3());\r\n const distSq = toParticleFromAxis.magnitudeSq;\r\n const radiusSq = contactRadius * contactRadius;\r\n\r\n if (distSq < radiusSq) {\r\n const dist = distSq > COLLISION_DISTANCE_EPSILON_SQ ? Math.sqrt(distSq) : 0;\r\n const penetration = contactRadius - dist;\r\n if (dist > 0) {\r\n toParticleFromAxis.scaleBy(1 / dist);\r\n } else {\r\n getCapsuleAxisFallbackNormal(axis, toParticleFromAxis);\r\n }\r\n toParticleFromAxis.scaleBy(penetration);\r\n Vector3.add(particlePos, toParticleFromAxis, particlePos);\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and a plane collider\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolvePlaneCollision(\r\n particlePos: Vector3,\r\n collider: PlaneCollider,\r\n particleRadius: number = 0\r\n): boolean {\r\n const toParticle = Vector3.sub(particlePos, collider.point, new Vector3());\r\n const distance = Vector3.dot(toParticle, collider.normal);\r\n const contactDistance = Math.max(0, particleRadius);\r\n\r\n if (distance < contactDistance) {\r\n // Particle is below plane, push it up\r\n const correction = Vector3.scale(collider.normal, contactDistance - distance, new Vector3());\r\n Vector3.add(particlePos, correction, particlePos);\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and an oriented box collider.\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolveBoxCollision(\r\n particlePos: Vector3,\r\n collider: BoxCollider,\r\n particleRadius: number = 0\r\n): boolean {\r\n const delta = Vector3.sub(particlePos, collider.center, new Vector3());\r\n const local = new Vector3(\r\n Vector3.dot(delta, collider.axes[0]),\r\n Vector3.dot(delta, collider.axes[1]),\r\n Vector3.dot(delta, collider.axes[2])\r\n );\r\n const radius = Math.max(0, particleRadius);\r\n const inside =\r\n Math.abs(local.x) <= collider.halfExtents.x &&\r\n Math.abs(local.y) <= collider.halfExtents.y &&\r\n Math.abs(local.z) <= collider.halfExtents.z;\r\n if (!inside) {\r\n if (radius <= 0) {\r\n return false;\r\n }\r\n const closest = new Vector3(\r\n Math.max(-collider.halfExtents.x, Math.min(collider.halfExtents.x, local.x)),\r\n Math.max(-collider.halfExtents.y, Math.min(collider.halfExtents.y, local.y)),\r\n Math.max(-collider.halfExtents.z, Math.min(collider.halfExtents.z, local.z))\r\n );\r\n const fromClosest = Vector3.sub(local, closest, new Vector3());\r\n const distanceSq = fromClosest.magnitudeSq;\r\n if (distanceSq >= radius * radius || distanceSq <= COLLISION_DISTANCE_EPSILON_SQ) {\r\n return false;\r\n }\r\n const distance = Math.sqrt(distanceSq);\r\n fromClosest.scaleBy((radius - distance) / distance);\r\n Vector3.add(\r\n particlePos,\r\n Vector3.add(\r\n Vector3.scale(collider.axes[0], fromClosest.x, new Vector3()),\r\n Vector3.add(\r\n Vector3.scale(collider.axes[1], fromClosest.y, new Vector3()),\r\n Vector3.scale(collider.axes[2], fromClosest.z, new Vector3()),\r\n new Vector3()\r\n ),\r\n new Vector3()\r\n ),\r\n particlePos\r\n );\r\n return true;\r\n }\r\n const penetration = new Vector3(\r\n collider.halfExtents.x - Math.abs(local.x) + radius,\r\n collider.halfExtents.y - Math.abs(local.y) + radius,\r\n collider.halfExtents.z - Math.abs(local.z) + radius\r\n );\r\n let axis = 0;\r\n let minPenetration = penetration.x;\r\n if (penetration.y < minPenetration) {\r\n axis = 1;\r\n minPenetration = penetration.y;\r\n }\r\n if (penetration.z < minPenetration) {\r\n axis = 2;\r\n minPenetration = penetration.z;\r\n }\r\n const localAxis = axis === 0 ? local.x : axis === 1 ? local.y : local.z;\r\n const sign = localAxis < 0 ? -1 : 1;\r\n const correction = Vector3.scale(collider.axes[axis], minPenetration * sign, new Vector3());\r\n Vector3.add(particlePos, correction, particlePos);\r\n return true;\r\n}\r\n\r\n/**\r\n * Updates collider position from its associated node\r\n *\r\n * @public\r\n */\r\nexport function updateColliderFromNode(collider: SpringCollider, runtimeNode?: Nullable<SceneNode>): void {\r\n const node = runtimeNode ?? collider.node;\r\n if (!node || !collider.enabled) {\r\n return;\r\n }\r\n\r\n const worldMatrix = node.worldMatrix;\r\n\r\n switch (collider.type) {\r\n case 'sphere': {\r\n const sphere = collider as SphereCollider;\r\n if (sphere.localRadius !== undefined) {\r\n const currentScale = getUniformScale(worldMatrix);\r\n const refScale = Math.max(1e-6, sphere.localRadiusScaleRef ?? 1);\r\n sphere.radius = sphere.localRadius * (currentScale / refScale);\r\n }\r\n if (sphere.localOffset) {\r\n // Transform local offset to world space\r\n worldMatrix.transformPointAffine(sphere.localOffset, sphere.center);\r\n } else {\r\n // No local offset, just use node position\r\n sphere.center.x = worldMatrix.m03;\r\n sphere.center.y = worldMatrix.m13;\r\n sphere.center.z = worldMatrix.m23;\r\n }\r\n break;\r\n }\r\n\r\n case 'capsule': {\r\n const capsule = collider as CapsuleCollider;\r\n if (capsule.localRadius !== undefined) {\r\n const axisLocal =\r\n capsule.localStartOffset && capsule.localEndOffset\r\n ? Vector3.sub(capsule.localEndOffset, capsule.localStartOffset, new Vector3())\r\n : Vector3.axisPY();\r\n const currentScale = getPerpendicularScale(worldMatrix, axisLocal);\r\n const refScale = Math.max(1e-6, capsule.localRadiusScaleRef ?? 1);\r\n capsule.radius = capsule.localRadius * (currentScale / refScale);\r\n }\r\n if (capsule.localStartOffset && capsule.localEndOffset) {\r\n // Transform local offsets to world space\r\n worldMatrix.transformPointAffine(capsule.localStartOffset, capsule.start);\r\n worldMatrix.transformPointAffine(capsule.localEndOffset, capsule.end);\r\n } else {\r\n // No local offsets, just use node position for start\r\n capsule.start.x = worldMatrix.m03;\r\n capsule.start.y = worldMatrix.m13;\r\n capsule.start.z = worldMatrix.m23;\r\n }\r\n break;\r\n }\r\n\r\n case 'plane': {\r\n const plane = collider as PlaneCollider;\r\n if (plane.localPointOffset) {\r\n // Transform local offset to world space\r\n worldMatrix.transformPointAffine(plane.localPointOffset, plane.point);\r\n } else {\r\n // No local offset, just use node position\r\n plane.point.x = worldMatrix.m03;\r\n plane.point.y = worldMatrix.m13;\r\n plane.point.z = worldMatrix.m23;\r\n }\r\n\r\n if (plane.localNormal) {\r\n // Transform local normal to world space (rotation only)\r\n worldMatrix.transformVectorAffine(plane.localNormal, plane.normal).inplaceNormalize();\r\n }\r\n break;\r\n }\r\n\r\n case 'box': {\r\n const box = collider as BoxCollider;\r\n if (box.localOffset) {\r\n worldMatrix.transformPointAffine(box.localOffset, box.center);\r\n } else {\r\n box.center.x = worldMatrix.m03;\r\n box.center.y = worldMatrix.m13;\r\n box.center.z = worldMatrix.m23;\r\n }\r\n const axes = createWorldAxes(worldMatrix);\r\n box.axes[0].set(axes[0]);\r\n box.axes[1].set(axes[1]);\r\n box.axes[2].set(axes[2]);\r\n if (box.localHalfExtents) {\r\n const scales = getAxisScales(worldMatrix);\r\n box.halfExtents.setXYZ(\r\n box.localHalfExtents.x * scales.x,\r\n box.localHalfExtents.y * scales.y,\r\n box.localHalfExtents.z * scales.z\r\n );\r\n }\r\n break;\r\n }\r\n }\r\n}\r\n\r\nfunction createWorldAxes(worldMatrix: any): [Vector3, Vector3, Vector3] {\r\n const x = worldMatrix.transformVectorAffine(Vector3.axisPX(), new Vector3()).inplaceNormalize();\r\n const y = worldMatrix.transformVectorAffine(Vector3.axisPY(), new Vector3()).inplaceNormalize();\r\n const z = worldMatrix.transformVectorAffine(Vector3.axisPZ(), new Vector3()).inplaceNormalize();\r\n return [x, y, z];\r\n}\r\n\r\nfunction getAxisScales(worldMatrix: any) {\r\n return {\r\n x: Math.max(1e-6, worldMatrix.transformVectorAffine(Vector3.axisPX(), new Vector3()).magnitude),\r\n y: Math.max(1e-6, worldMatrix.transformVectorAffine(Vector3.axisPY(), new Vector3()).magnitude),\r\n z: Math.max(1e-6, worldMatrix.transformVectorAffine(Vector3.axisPZ(), new Vector3()).magnitude)\r\n };\r\n}\r\n\r\nfunction getUniformScale(worldMatrix: any): number {\r\n const sx = worldMatrix.transformVectorAffine(Vector3.axisPX(), new Vector3()).magnitude;\r\n const sy = worldMatrix.transformVectorAffine(Vector3.axisPY(), new Vector3()).magnitude;\r\n const sz = worldMatrix.transformVectorAffine(Vector3.axisPZ(), new Vector3()).magnitude;\r\n return Math.max(1e-6, (sx + sy + sz) / 3);\r\n}\r\n\r\nfunction getPerpendicularScale(worldMatrix: any, axisLocal: Vector3): number {\r\n const axis = axisLocal.magnitudeSq > 1e-8 ? axisLocal.clone().inplaceNormalize() : Vector3.axisPY();\r\n const helper = Math.abs(axis.y) < 0.99 ? Vector3.axisPY() : Vector3.axisPX();\r\n const u = Vector3.cross(axis, helper, new Vector3()).inplaceNormalize();\r\n const v = Vector3.cross(axis, u, new Vector3()).inplaceNormalize();\r\n const su = worldMatrix.transformVectorAffine(u, new Vector3()).magnitude;\r\n const sv = worldMatrix.transformVectorAffine(v, new Vector3()).magnitude;\r\n return Math.max(1e-6, (su + sv) * 0.5);\r\n}\r\n"],"names":["COLLISION_DISTANCE_EPSILON_SQ","getCapsuleAxisFallbackNormal","axis","result","reference","Math","abs","z","Vector3","axisPZ","axisPX","sub","scale","dot","inplaceNormalize","createSphereCollider","centerOrOffset","radius","node","worldMatrix","worldCenter","transformPointAffine","type","center","localRadius","localRadiusScaleRef","getUniformScale","enabled","localOffset","clone","createCapsuleCollider","startOrOffset","endOrOffset","worldStart","worldEnd","start","end","getPerpendicularScale","localStartOffset","localEndOffset","createPlaneCollider","pointOrOffset","normal","normalizedNormal","normalize","worldPoint","point","localPointOffset","localNormal","createBoxCollider","halfExtents","localExtents","max","x","y","axes","createWorldAxes","scales","getAxisScales","localHalfExtents","axisPY","resolveSphereCollision","particlePos","collider","particleRadius","toParticle","distSq","magnitudeSq","contactRadius","radiusSq","dist","sqrt","penetration","scaleBy","setXYZ","add","resolveCapsuleCollision","axisLength","magnitude","projection","t","min","closestPoint","toParticleFromAxis","resolvePlaneCollision","distance","contactDistance","correction","resolveBoxCollision","delta","local","inside","closest","fromClosest","distanceSq","minPenetration","localAxis","sign","updateColliderFromNode","runtimeNode","sphere","undefined","currentScale","refScale","m03","m13","m23","capsule","axisLocal","plane","transformVectorAffine","box","set","sx","sy","sz","helper","u","cross","v","su","sv"],"mappings":"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"}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
originalRotation: options?.originalRotation?.clone() ?? null,
|
|
12
12
|
mass: options?.mass ?? 1.0,
|
|
13
13
|
damping: options?.damping ?? 0.95,
|
|
14
|
+
collisionRadius: Math.max(0, Number(options?.collisionRadius) || 0),
|
|
14
15
|
fixed: options?.fixed ?? false,
|
|
15
16
|
node: options?.node ?? null,
|
|
16
17
|
anchorNode: options?.anchorNode ?? null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spring_particle.js","sources":["../../../src/animation/spring/spring_particle.ts"],"sourcesContent":["import type { Vector3, Quaternion, Nullable } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../../scene/scene_node';\r\n\r\n/**\r\n * Represents a particle in the spring system\r\n *\r\n * @public\r\n */\r\nexport interface SpringParticle {\r\n /** Current position in world space */\r\n position: Vector3;\r\n /** Previous position for Verlet integration */\r\n prevPosition: Vector3;\r\n /** Original position for reset */\r\n originalPosition: Vector3;\r\n /** Animated (target) position for pose preservation */\r\n animPosition: Vector3;\r\n /** Original world rotation (for calculating rotation delta) */\r\n originalRotation: Quaternion | null;\r\n /** Mass of the particle (affects inertia) */\r\n mass: number;\r\n /**
|
|
1
|
+
{"version":3,"file":"spring_particle.js","sources":["../../../src/animation/spring/spring_particle.ts"],"sourcesContent":["import type { Vector3, Quaternion, Nullable } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../../scene/scene_node';\r\n\r\n/**\r\n * Represents a particle in the spring system\r\n *\r\n * @public\r\n */\r\nexport interface SpringParticle {\r\n /** Current position in world space */\r\n position: Vector3;\r\n /** Previous position for Verlet integration */\r\n prevPosition: Vector3;\r\n /** Original position for reset */\r\n originalPosition: Vector3;\r\n /** Animated (target) position for pose preservation */\r\n animPosition: Vector3;\r\n /** Original world rotation (for calculating rotation delta) */\r\n originalRotation: Quaternion | null;\r\n /** Mass of the particle (affects inertia) */\r\n mass: number;\r\n /** Velocity retention [0-1] (0 = fully damped, 1 = no damping) */\r\n damping: number;\r\n /** World-space collision radius around the particle center */\r\n collisionRadius: number;\r\n /** Whether this particle is fixed (anchor point) */\r\n fixed: boolean;\r\n /** Associated scene node (optional) */\r\n node: Nullable<SceneNode>;\r\n /** Optional alternate anchor node used as the fixed-position source */\r\n anchorNode?: Nullable<SceneNode>;\r\n /** Optional local-space offset evaluated from anchorNode */\r\n anchorOffset?: Nullable<Vector3>;\r\n /** Previous frame position (used to calculate velocity for inertial forces) */\r\n lastFramePosition: Vector3;\r\n /** Position history for rotation center estimation (for fixed particles) */\r\n positionHistory?: Vector3[];\r\n}\r\n\r\n/**\r\n * Creates a new spring particle\r\n *\r\n * @public\r\n */\r\nexport function createSpringParticle(\r\n position: Vector3,\r\n options?: {\r\n mass?: number;\r\n damping?: number;\r\n collisionRadius?: number;\r\n fixed?: boolean;\r\n node?: SceneNode;\r\n anchorNode?: SceneNode;\r\n anchorOffset?: Vector3;\r\n originalRotation?: Quaternion;\r\n }\r\n): SpringParticle {\r\n return {\r\n position: position.clone(),\r\n prevPosition: position.clone(),\r\n originalPosition: position.clone(),\r\n animPosition: position.clone(),\r\n originalRotation: options?.originalRotation?.clone() ?? null,\r\n mass: options?.mass ?? 1.0,\r\n damping: options?.damping ?? 0.95,\r\n collisionRadius: Math.max(0, Number(options?.collisionRadius) || 0),\r\n fixed: options?.fixed ?? false,\r\n node: options?.node ?? null,\r\n anchorNode: options?.anchorNode ?? null,\r\n anchorOffset: options?.anchorOffset?.clone() ?? null,\r\n lastFramePosition: position.clone()\r\n };\r\n}\r\n"],"names":["createSpringParticle","position","options","clone","prevPosition","originalPosition","animPosition","originalRotation","mass","damping","collisionRadius","Math","max","Number","fixed","node","anchorNode","anchorOffset","lastFramePosition"],"mappings":"AAuCA;;;;AAIC,IACM,SAASA,oBACdC,CAAAA,QAAiB,EACjBC,OASC,EAAA;IAED,OAAO;AACLD,QAAAA,QAAAA,EAAUA,SAASE,KAAK,EAAA;AACxBC,QAAAA,YAAAA,EAAcH,SAASE,KAAK,EAAA;AAC5BE,QAAAA,gBAAAA,EAAkBJ,SAASE,KAAK,EAAA;AAChCG,QAAAA,YAAAA,EAAcL,SAASE,KAAK,EAAA;QAC5BI,gBAAkBL,EAAAA,OAAAA,EAASK,kBAAkBJ,KAAW,EAAA,IAAA,IAAA;AACxDK,QAAAA,IAAAA,EAAMN,SAASM,IAAQ,IAAA,GAAA;AACvBC,QAAAA,OAAAA,EAASP,SAASO,OAAW,IAAA,IAAA;AAC7BC,QAAAA,eAAAA,EAAiBC,KAAKC,GAAG,CAAC,CAAGC,EAAAA,MAAAA,CAAOX,SAASQ,eAAoB,CAAA,IAAA,CAAA,CAAA;AACjEI,QAAAA,KAAAA,EAAOZ,SAASY,KAAS,IAAA,KAAA;AACzBC,QAAAA,IAAAA,EAAMb,SAASa,IAAQ,IAAA,IAAA;AACvBC,QAAAA,UAAAA,EAAYd,SAASc,UAAc,IAAA,IAAA;QACnCC,YAAcf,EAAAA,OAAAA,EAASe,cAAcd,KAAW,EAAA,IAAA,IAAA;AAChDe,QAAAA,iBAAAA,EAAmBjB,SAASE,KAAK;AACnC,KAAA;AACF;;;;"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { Vector3, Quaternion } from '@zephyr3d/base';
|
|
2
|
+
|
|
3
|
+
const EPSILON = 1e-6;
|
|
4
|
+
const INITIAL_COLLISION_PENETRATION_SLOP = 1e-4;
|
|
5
|
+
const DEFAULT_INITIAL_COLLISION_PENETRATION_RELEASE_TIME = 0.25;
|
|
6
|
+
function clampSpringRatio(value) {
|
|
7
|
+
return Math.max(0, Math.min(1, Number(value) || 0));
|
|
8
|
+
}
|
|
9
|
+
function interpolateSpringValue(root, tip, exponent, index, count) {
|
|
10
|
+
const t = Math.pow(index / Math.max(1, count - 1), Math.max(0.1, exponent));
|
|
11
|
+
return root + (tip - root) * t;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Converts a user-facing per-step strength into a strength that can be applied
|
|
15
|
+
* repeatedly without changing the effective response.
|
|
16
|
+
*/ function getIterationStrength(strength, iterations) {
|
|
17
|
+
const value = clampSpringRatio(strength);
|
|
18
|
+
return iterations > 1 ? 1 - Math.pow(1 - value, 1 / iterations) : value;
|
|
19
|
+
}
|
|
20
|
+
/** Smoothly releases startup collider overlap so particles reach the real surface after `duration`. */ function getReleasedCollisionPenetration(initialPenetration, elapsed, duration) {
|
|
21
|
+
if (initialPenetration <= 0 || duration <= 0) {
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
const t = Math.max(0, Math.min(1, elapsed / duration));
|
|
25
|
+
const progress = t * t * (3 - 2 * t);
|
|
26
|
+
return initialPenetration * (1 - progress);
|
|
27
|
+
}
|
|
28
|
+
/** Returns the Kawaii-style pose target relative to the simulated parent. */ function getParentRelativePoseTarget(particle, parent, result = new Vector3()) {
|
|
29
|
+
if (!parent) {
|
|
30
|
+
result.set(particle.animPosition);
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
Vector3.sub(particle.animPosition, parent.animPosition, result);
|
|
34
|
+
return Vector3.add(parent.position, result, result);
|
|
35
|
+
}
|
|
36
|
+
/** Builds a pose-follow direction and falloff measured from the nearest fixed particle. */ function getSpringPoseTopology(particles) {
|
|
37
|
+
const fixedIndices = [];
|
|
38
|
+
for(let i = 0; i < particles.length; i++){
|
|
39
|
+
if (particles[i].fixed) {
|
|
40
|
+
fixedIndices.push(i);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (fixedIndices.length === 0) {
|
|
44
|
+
const lastIndex = Math.max(1, particles.length - 1);
|
|
45
|
+
return particles.map((_, index)=>({
|
|
46
|
+
parent: index > 0 ? particles[index - 1] : null,
|
|
47
|
+
nearestAnchor: null,
|
|
48
|
+
normalizedDistance: index / lastIndex
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
const nearestFixedIndices = new Array(particles.length);
|
|
52
|
+
const distances = new Array(particles.length);
|
|
53
|
+
let maxDistance = 1;
|
|
54
|
+
for(let i = 0; i < particles.length; i++){
|
|
55
|
+
let nearestFixedIndex = fixedIndices[0];
|
|
56
|
+
let nearestDistance = Math.abs(i - nearestFixedIndex);
|
|
57
|
+
for(let j = 1; j < fixedIndices.length; j++){
|
|
58
|
+
const distance = Math.abs(i - fixedIndices[j]);
|
|
59
|
+
if (distance < nearestDistance) {
|
|
60
|
+
nearestFixedIndex = fixedIndices[j];
|
|
61
|
+
nearestDistance = distance;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
nearestFixedIndices[i] = nearestFixedIndex;
|
|
65
|
+
distances[i] = nearestDistance;
|
|
66
|
+
maxDistance = Math.max(maxDistance, nearestDistance);
|
|
67
|
+
}
|
|
68
|
+
return particles.map((_, index)=>{
|
|
69
|
+
const nearestFixedIndex = nearestFixedIndices[index];
|
|
70
|
+
return {
|
|
71
|
+
parent: index > 0 ? particles[index - 1] : null,
|
|
72
|
+
nearestAnchor: particles[nearestFixedIndex],
|
|
73
|
+
normalizedDistance: distances[index] / maxDistance
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/** Returns the Kawaii target, blending hierarchy shape with the nearest fixed anchor. */ function getKawaiiPoseTarget(particle, topology, result = new Vector3()) {
|
|
78
|
+
getParentRelativePoseTarget(particle, topology.parent, result);
|
|
79
|
+
if (!topology.nearestAnchor || topology.nearestAnchor === topology.parent) {
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
const anchorTarget = getParentRelativePoseTarget(particle, topology.nearestAnchor);
|
|
83
|
+
return Vector3.lerp(result, anchorTarget, 1 - topology.normalizedDistance, result);
|
|
84
|
+
}
|
|
85
|
+
/** Position-based distance projection with inverse-mass weighting. */ function solveDistanceConstraint(particleA, particleB, restLength, stiffness) {
|
|
86
|
+
const inverseMassA = particleA.fixed ? 0 : 1 / Math.max(particleA.mass, EPSILON);
|
|
87
|
+
const inverseMassB = particleB.fixed ? 0 : 1 / Math.max(particleB.mass, EPSILON);
|
|
88
|
+
const inverseMassSum = inverseMassA + inverseMassB;
|
|
89
|
+
if (inverseMassSum <= EPSILON) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const delta = Vector3.sub(particleB.position, particleA.position, new Vector3());
|
|
93
|
+
const length = delta.magnitude;
|
|
94
|
+
if (length <= EPSILON) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const correctionScale = (length - restLength) / length * clampSpringRatio(stiffness);
|
|
98
|
+
if (inverseMassA > 0) {
|
|
99
|
+
Vector3.add(particleA.position, Vector3.scale(delta, correctionScale * (inverseMassA / inverseMassSum), new Vector3()), particleA.position);
|
|
100
|
+
}
|
|
101
|
+
if (inverseMassB > 0) {
|
|
102
|
+
Vector3.sub(particleB.position, Vector3.scale(delta, correctionScale * (inverseMassB / inverseMassSum), new Vector3()), particleB.position);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Resolves a contact as an inelastic projection while preserving tangential Verlet velocity. */ function resolveInelasticCollision(particle, collider, resolveCollision, allowedPenetration = 0) {
|
|
106
|
+
const positionBeforeCollision = particle.position.clone();
|
|
107
|
+
const preservedDisplacement = Vector3.sub(positionBeforeCollision, particle.prevPosition, new Vector3());
|
|
108
|
+
if (!resolveCollision(particle.position, collider, particle.collisionRadius)) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const correction = Vector3.sub(particle.position, positionBeforeCollision, new Vector3());
|
|
112
|
+
const correctionLength = correction.magnitude;
|
|
113
|
+
const excessPenetration = correctionLength - Math.max(0, allowedPenetration);
|
|
114
|
+
if (excessPenetration <= EPSILON) {
|
|
115
|
+
particle.position.set(positionBeforeCollision);
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
const outwardNormal = correction.scaleBy(1 / correctionLength);
|
|
119
|
+
Vector3.add(positionBeforeCollision, Vector3.scale(outwardNormal, excessPenetration, new Vector3()), particle.position);
|
|
120
|
+
if (correctionLength > EPSILON) {
|
|
121
|
+
const inwardDistance = Vector3.dot(preservedDisplacement, outwardNormal);
|
|
122
|
+
if (inwardDistance < 0) {
|
|
123
|
+
Vector3.sub(preservedDisplacement, Vector3.scale(outwardNormal, inwardDistance, new Vector3()), preservedDisplacement);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
Vector3.sub(particle.position, preservedDisplacement, particle.prevPosition);
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
/** Returns how far a point is inside a collider according to its resolver. */ function measureCollisionPenetration(position, collider, resolveCollision, particleRadius = 0) {
|
|
130
|
+
const resolvedPosition = position.clone();
|
|
131
|
+
return resolveCollision(resolvedPosition, collider, particleRadius) ? Vector3.distance(position, resolvedPosition) : 0;
|
|
132
|
+
}
|
|
133
|
+
function getFallbackRotationAxis(direction) {
|
|
134
|
+
const reference = Math.abs(direction.x) < 0.8 ? Vector3.axisPX() : Vector3.axisPY();
|
|
135
|
+
return Vector3.cross(direction, reference, new Vector3()).inplaceNormalize();
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Limits a child direction around its current animated direction while
|
|
139
|
+
* preserving the current simulated segment length.
|
|
140
|
+
*/ function solveAngleLimit(parent, child, maxAngleDegrees, preserveVelocity) {
|
|
141
|
+
if (maxAngleDegrees <= 0 || child.fixed) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const poseDirection = Vector3.sub(child.animPosition, parent.animPosition, new Vector3());
|
|
145
|
+
const simulatedDirection = Vector3.sub(child.position, parent.position, new Vector3());
|
|
146
|
+
const simulatedLength = simulatedDirection.magnitude;
|
|
147
|
+
if (poseDirection.magnitudeSq <= EPSILON || simulatedLength <= EPSILON) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
poseDirection.inplaceNormalize();
|
|
151
|
+
simulatedDirection.scaleBy(1 / simulatedLength);
|
|
152
|
+
const dot = Math.max(-1, Math.min(1, Vector3.dot(poseDirection, simulatedDirection)));
|
|
153
|
+
const angle = Math.acos(dot);
|
|
154
|
+
const limit = maxAngleDegrees * Math.PI / 180;
|
|
155
|
+
if (angle <= limit) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
let axis = Vector3.cross(poseDirection, simulatedDirection, new Vector3());
|
|
159
|
+
if (axis.magnitudeSq <= EPSILON) {
|
|
160
|
+
axis = getFallbackRotationAxis(poseDirection);
|
|
161
|
+
} else {
|
|
162
|
+
axis.inplaceNormalize();
|
|
163
|
+
}
|
|
164
|
+
const allowedDirection = Quaternion.fromAxisAngle(axis, limit).transform(poseDirection, new Vector3());
|
|
165
|
+
const previousPosition = child.position.clone();
|
|
166
|
+
Vector3.add(parent.position, Vector3.scale(allowedDirection, simulatedLength, allowedDirection), child.position);
|
|
167
|
+
if (preserveVelocity) {
|
|
168
|
+
Vector3.add(child.prevPosition, Vector3.sub(child.position, previousPosition, previousPosition), child.prevPosition);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export { DEFAULT_INITIAL_COLLISION_PENETRATION_RELEASE_TIME, INITIAL_COLLISION_PENETRATION_SLOP, clampSpringRatio, getIterationStrength, getKawaiiPoseTarget, getParentRelativePoseTarget, getReleasedCollisionPenetration, getSpringPoseTopology, interpolateSpringValue, measureCollisionPenetration, resolveInelasticCollision, solveAngleLimit, solveDistanceConstraint };
|
|
173
|
+
//# sourceMappingURL=spring_solver.js.map
|