@zephyr3d/scene 0.9.26 → 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 +146 -30
- 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 +300 -56
- 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 +177 -3
- 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 +178 -200
- 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 +30475 -19865
- package/dist/index.js +67 -12
- 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/hairstrand.js +235 -235
- package/dist/material/hairstrand.js.map +1 -1
- package/dist/material/lambert.js +4 -1
- package/dist/material/lambert.js.map +1 -1
- package/dist/material/material.js +362 -300
- 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 +223 -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 +733 -190
- 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 +2009 -201
- 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 +668 -63
- package/dist/posteffect/motionblur.js.map +1 -1
- package/dist/posteffect/posteffect.js +12 -1
- package/dist/posteffect/posteffect.js.map +1 -1
- package/dist/posteffect/postsss.js +572 -0
- package/dist/posteffect/postsss.js.map +1 -0
- package/dist/posteffect/sao.js +48 -50
- 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 +34 -15
- 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 +40 -39
- package/dist/render/abuffer_oit.js.map +1 -1
- package/dist/render/clipmap.js +328 -62
- 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 +26 -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 +53 -53
- 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 +8 -13
- package/dist/render/fbm_wavegenerator.js.map +1 -1
- package/dist/render/fft_wavegenerator.js +268 -136
- package/dist/render/fft_wavegenerator.js.map +1 -1
- package/dist/render/gerstner_wavegenerator.js +113 -28
- 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/hzb.js +80 -22
- package/dist/render/hzb.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 +23 -9
- 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/oit.js +11 -11
- package/dist/render/oit.js.map +1 -1
- 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 +198 -11
- package/dist/render/render_queue.js.map +1 -1
- package/dist/render/renderer.js +14 -7
- package/dist/render/renderer.js.map +1 -1
- package/dist/render/rendergraph/blackboard.js +15 -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 +585 -59
- package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
- package/dist/render/rendergraph/frame_resource_requirements.js +1 -0
- package/dist/render/rendergraph/frame_resource_requirements.js.map +1 -1
- package/dist/render/rendergraph/history_resources.js +8 -1
- package/dist/render/rendergraph/history_resources.js.map +1 -1
- 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 +524 -0
- package/dist/render/underwater.js.map +1 -0
- 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 +1195 -0
- package/dist/render/water_caustics.js.map +1 -0
- 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 +36 -36
- 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 +997 -96
- 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/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 +40 -87
- package/dist/shaders/water.js.map +1 -1
- package/dist/shaders/water_medium.js +42 -0
- package/dist/shaders/water_medium.js.map +1 -0
- 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 +87 -49
- 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 +36 -6
- package/dist/utility/serialization/manager.js.map +1 -1
- package/dist/utility/serialization/scene/animation.js +77 -7
- 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 +140 -279
- 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 +2473 -114
- package/dist/utility/serialization/scene/water.js.map +1 -1
- package/dist/utility/serialization/types.js.map +1 -1
- package/dist/utility/shprojector.js +97 -109
- 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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spring_solver.js","sources":["../../../src/animation/spring/spring_solver.ts"],"sourcesContent":["import { Quaternion, Vector3 } from '@zephyr3d/base';\r\nimport type { SpringParticle } from './spring_particle';\r\n\r\n/** Motion model used by the spring integration pipeline. */\r\nexport type SpringMotionModel = 'legacy' | 'kawaii';\r\n\r\nconst EPSILON = 1e-6;\r\nexport const INITIAL_COLLISION_PENETRATION_SLOP = 1e-4;\r\nexport const DEFAULT_INITIAL_COLLISION_PENETRATION_RELEASE_TIME = 0.25;\r\n\r\nexport function clampSpringRatio(value: number): number {\r\n return Math.max(0, Math.min(1, Number(value) || 0));\r\n}\r\n\r\nexport function interpolateSpringValue(\r\n root: number,\r\n tip: number,\r\n exponent: number,\r\n index: number,\r\n count: number\r\n) {\r\n const t = Math.pow(index / Math.max(1, count - 1), Math.max(0.1, exponent));\r\n return root + (tip - root) * t;\r\n}\r\n\r\n/**\r\n * Converts a user-facing per-step strength into a strength that can be applied\r\n * repeatedly without changing the effective response.\r\n */\r\nexport function getIterationStrength(strength: number, iterations: number): number {\r\n const value = clampSpringRatio(strength);\r\n return iterations > 1 ? 1 - Math.pow(1 - value, 1 / iterations) : value;\r\n}\r\n\r\n/** Smoothly releases startup collider overlap so particles reach the real surface after `duration`. */\r\nexport function getReleasedCollisionPenetration(\r\n initialPenetration: number,\r\n elapsed: number,\r\n duration: number\r\n): number {\r\n if (initialPenetration <= 0 || duration <= 0) {\r\n return 0;\r\n }\r\n const t = Math.max(0, Math.min(1, elapsed / duration));\r\n const progress = t * t * (3 - 2 * t);\r\n return initialPenetration * (1 - progress);\r\n}\r\n\r\n/** Returns the Kawaii-style pose target relative to the simulated parent. */\r\nexport function getParentRelativePoseTarget(\r\n particle: SpringParticle,\r\n parent: SpringParticle | null,\r\n result = new Vector3()\r\n): Vector3 {\r\n if (!parent) {\r\n result.set(particle.animPosition);\r\n return result;\r\n }\r\n Vector3.sub(particle.animPosition, parent.animPosition, result);\r\n return Vector3.add(parent.position, result, result);\r\n}\r\n\r\nexport interface SpringPoseTopologyEntry {\r\n parent: SpringParticle | null;\r\n nearestAnchor: SpringParticle | null;\r\n normalizedDistance: number;\r\n}\r\n\r\n/** Builds a pose-follow direction and falloff measured from the nearest fixed particle. */\r\nexport function getSpringPoseTopology(particles: readonly SpringParticle[]): SpringPoseTopologyEntry[] {\r\n const fixedIndices: number[] = [];\r\n for (let i = 0; i < particles.length; i++) {\r\n if (particles[i].fixed) {\r\n fixedIndices.push(i);\r\n }\r\n }\r\n\r\n if (fixedIndices.length === 0) {\r\n const lastIndex = Math.max(1, particles.length - 1);\r\n return particles.map((_, index) => ({\r\n parent: index > 0 ? particles[index - 1] : null,\r\n nearestAnchor: null,\r\n normalizedDistance: index / lastIndex\r\n }));\r\n }\r\n\r\n const nearestFixedIndices = new Array<number>(particles.length);\r\n const distances = new Array<number>(particles.length);\r\n let maxDistance = 1;\r\n for (let i = 0; i < particles.length; i++) {\r\n let nearestFixedIndex = fixedIndices[0];\r\n let nearestDistance = Math.abs(i - nearestFixedIndex);\r\n for (let j = 1; j < fixedIndices.length; j++) {\r\n const distance = Math.abs(i - fixedIndices[j]);\r\n if (distance < nearestDistance) {\r\n nearestFixedIndex = fixedIndices[j];\r\n nearestDistance = distance;\r\n }\r\n }\r\n nearestFixedIndices[i] = nearestFixedIndex;\r\n distances[i] = nearestDistance;\r\n maxDistance = Math.max(maxDistance, nearestDistance);\r\n }\r\n\r\n return particles.map((_, index) => {\r\n const nearestFixedIndex = nearestFixedIndices[index];\r\n return {\r\n parent: index > 0 ? particles[index - 1] : null,\r\n nearestAnchor: particles[nearestFixedIndex],\r\n normalizedDistance: distances[index] / maxDistance\r\n };\r\n });\r\n}\r\n\r\n/** Returns the Kawaii target, blending hierarchy shape with the nearest fixed anchor. */\r\nexport function getKawaiiPoseTarget(\r\n particle: SpringParticle,\r\n topology: SpringPoseTopologyEntry,\r\n result = new Vector3()\r\n): Vector3 {\r\n getParentRelativePoseTarget(particle, topology.parent, result);\r\n if (!topology.nearestAnchor || topology.nearestAnchor === topology.parent) {\r\n return result;\r\n }\r\n const anchorTarget = getParentRelativePoseTarget(particle, topology.nearestAnchor);\r\n return Vector3.lerp(result, anchorTarget, 1 - topology.normalizedDistance, result);\r\n}\r\n\r\n/** Position-based distance projection with inverse-mass weighting. */\r\nexport function solveDistanceConstraint(\r\n particleA: SpringParticle,\r\n particleB: SpringParticle,\r\n restLength: number,\r\n stiffness: number\r\n): void {\r\n const inverseMassA = particleA.fixed ? 0 : 1 / Math.max(particleA.mass, EPSILON);\r\n const inverseMassB = particleB.fixed ? 0 : 1 / Math.max(particleB.mass, EPSILON);\r\n const inverseMassSum = inverseMassA + inverseMassB;\r\n if (inverseMassSum <= EPSILON) {\r\n return;\r\n }\r\n\r\n const delta = Vector3.sub(particleB.position, particleA.position, new Vector3());\r\n const length = delta.magnitude;\r\n if (length <= EPSILON) {\r\n return;\r\n }\r\n\r\n const correctionScale = ((length - restLength) / length) * clampSpringRatio(stiffness);\r\n if (inverseMassA > 0) {\r\n Vector3.add(\r\n particleA.position,\r\n Vector3.scale(delta, correctionScale * (inverseMassA / inverseMassSum), new Vector3()),\r\n particleA.position\r\n );\r\n }\r\n if (inverseMassB > 0) {\r\n Vector3.sub(\r\n particleB.position,\r\n Vector3.scale(delta, correctionScale * (inverseMassB / inverseMassSum), new Vector3()),\r\n particleB.position\r\n );\r\n }\r\n}\r\n\r\n/** Resolves a contact as an inelastic projection while preserving tangential Verlet velocity. */\r\nexport function resolveInelasticCollision<TCollider>(\r\n particle: SpringParticle,\r\n collider: TCollider,\r\n resolveCollision: (position: Vector3, collider: TCollider, particleRadius?: number) => boolean,\r\n allowedPenetration: number = 0\r\n): boolean {\r\n const positionBeforeCollision = particle.position.clone();\r\n const preservedDisplacement = Vector3.sub(positionBeforeCollision, particle.prevPosition, new Vector3());\r\n if (!resolveCollision(particle.position, collider, particle.collisionRadius)) {\r\n return false;\r\n }\r\n\r\n const correction = Vector3.sub(particle.position, positionBeforeCollision, new Vector3());\r\n const correctionLength = correction.magnitude;\r\n const excessPenetration = correctionLength - Math.max(0, allowedPenetration);\r\n if (excessPenetration <= EPSILON) {\r\n particle.position.set(positionBeforeCollision);\r\n return false;\r\n }\r\n\r\n const outwardNormal = correction.scaleBy(1 / correctionLength);\r\n Vector3.add(\r\n positionBeforeCollision,\r\n Vector3.scale(outwardNormal, excessPenetration, new Vector3()),\r\n particle.position\r\n );\r\n if (correctionLength > EPSILON) {\r\n const inwardDistance = Vector3.dot(preservedDisplacement, outwardNormal);\r\n if (inwardDistance < 0) {\r\n Vector3.sub(\r\n preservedDisplacement,\r\n Vector3.scale(outwardNormal, inwardDistance, new Vector3()),\r\n preservedDisplacement\r\n );\r\n }\r\n }\r\n Vector3.sub(particle.position, preservedDisplacement, particle.prevPosition);\r\n return true;\r\n}\r\n\r\n/** Returns how far a point is inside a collider according to its resolver. */\r\nexport function measureCollisionPenetration<TCollider>(\r\n position: Vector3,\r\n collider: TCollider,\r\n resolveCollision: (position: Vector3, collider: TCollider, particleRadius?: number) => boolean,\r\n particleRadius: number = 0\r\n): number {\r\n const resolvedPosition = position.clone();\r\n return resolveCollision(resolvedPosition, collider, particleRadius)\r\n ? Vector3.distance(position, resolvedPosition)\r\n : 0;\r\n}\r\n\r\nfunction getFallbackRotationAxis(direction: Vector3): Vector3 {\r\n const reference = Math.abs(direction.x) < 0.8 ? Vector3.axisPX() : Vector3.axisPY();\r\n return Vector3.cross(direction, reference, new Vector3()).inplaceNormalize();\r\n}\r\n\r\n/**\r\n * Limits a child direction around its current animated direction while\r\n * preserving the current simulated segment length.\r\n */\r\nexport function solveAngleLimit(\r\n parent: SpringParticle,\r\n child: SpringParticle,\r\n maxAngleDegrees: number,\r\n preserveVelocity: boolean\r\n): void {\r\n if (maxAngleDegrees <= 0 || child.fixed) {\r\n return;\r\n }\r\n\r\n const poseDirection = Vector3.sub(child.animPosition, parent.animPosition, new Vector3());\r\n const simulatedDirection = Vector3.sub(child.position, parent.position, new Vector3());\r\n const simulatedLength = simulatedDirection.magnitude;\r\n if (poseDirection.magnitudeSq <= EPSILON || simulatedLength <= EPSILON) {\r\n return;\r\n }\r\n poseDirection.inplaceNormalize();\r\n simulatedDirection.scaleBy(1 / simulatedLength);\r\n\r\n const dot = Math.max(-1, Math.min(1, Vector3.dot(poseDirection, simulatedDirection)));\r\n const angle = Math.acos(dot);\r\n const limit = (maxAngleDegrees * Math.PI) / 180;\r\n if (angle <= limit) {\r\n return;\r\n }\r\n\r\n let axis = Vector3.cross(poseDirection, simulatedDirection, new Vector3());\r\n if (axis.magnitudeSq <= EPSILON) {\r\n axis = getFallbackRotationAxis(poseDirection);\r\n } else {\r\n axis.inplaceNormalize();\r\n }\r\n const allowedDirection = Quaternion.fromAxisAngle(axis, limit).transform(poseDirection, new Vector3());\r\n const previousPosition = child.position.clone();\r\n Vector3.add(\r\n parent.position,\r\n Vector3.scale(allowedDirection, simulatedLength, allowedDirection),\r\n child.position\r\n );\r\n if (preserveVelocity) {\r\n Vector3.add(\r\n child.prevPosition,\r\n Vector3.sub(child.position, previousPosition, previousPosition),\r\n child.prevPosition\r\n );\r\n }\r\n}\r\n"],"names":["EPSILON","INITIAL_COLLISION_PENETRATION_SLOP","DEFAULT_INITIAL_COLLISION_PENETRATION_RELEASE_TIME","clampSpringRatio","value","Math","max","min","Number","interpolateSpringValue","root","tip","exponent","index","count","t","pow","getIterationStrength","strength","iterations","getReleasedCollisionPenetration","initialPenetration","elapsed","duration","progress","getParentRelativePoseTarget","particle","parent","result","Vector3","set","animPosition","sub","add","position","getSpringPoseTopology","particles","fixedIndices","i","length","fixed","push","lastIndex","map","_","nearestAnchor","normalizedDistance","nearestFixedIndices","Array","distances","maxDistance","nearestFixedIndex","nearestDistance","abs","j","distance","getKawaiiPoseTarget","topology","anchorTarget","lerp","solveDistanceConstraint","particleA","particleB","restLength","stiffness","inverseMassA","mass","inverseMassB","inverseMassSum","delta","magnitude","correctionScale","scale","resolveInelasticCollision","collider","resolveCollision","allowedPenetration","positionBeforeCollision","clone","preservedDisplacement","prevPosition","collisionRadius","correction","correctionLength","excessPenetration","outwardNormal","scaleBy","inwardDistance","dot","measureCollisionPenetration","particleRadius","resolvedPosition","getFallbackRotationAxis","direction","reference","x","axisPX","axisPY","cross","inplaceNormalize","solveAngleLimit","child","maxAngleDegrees","preserveVelocity","poseDirection","simulatedDirection","simulatedLength","magnitudeSq","angle","acos","limit","PI","axis","allowedDirection","Quaternion","fromAxisAngle","transform","previousPosition"],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Vector3, Quaternion } from '@zephyr3d/base';
|
|
2
2
|
import { IKUtils } from '../ik/ik_utils.js';
|
|
3
|
-
import { updateColliderFromNode, resolveSphereCollision, resolveCapsuleCollision, resolvePlaneCollision } from './spring_collider.js';
|
|
3
|
+
import { updateColliderFromNode, resolveSphereCollision, resolveCapsuleCollision, resolvePlaneCollision, resolveBoxCollision } from './spring_collider.js';
|
|
4
4
|
import { SpringNodePoseTracker } from './spring_node_pose_tracker.js';
|
|
5
|
+
import { DEFAULT_INITIAL_COLLISION_PENETRATION_RELEASE_TIME, getSpringPoseTopology, getKawaiiPoseTarget, interpolateSpringValue, solveAngleLimit, solveDistanceConstraint, resolveInelasticCollision, measureCollisionPenetration, INITIAL_COLLISION_PENETRATION_SLOP, getReleasedCollisionPenetration, getIterationStrength } from './spring_solver.js';
|
|
5
6
|
|
|
6
7
|
const FIXED_SIMULATION_TIME_STEP = 1 / 60;
|
|
7
8
|
const MAX_ACCUMULATED_SIMULATION_TIME = 1 / 20;
|
|
@@ -35,7 +36,16 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
35
36
|
_smoothedSphereCenters;
|
|
36
37
|
_smoothedCapsuleEndpoints;
|
|
37
38
|
_smoothedPlaneData;
|
|
39
|
+
_smoothedBoxData;
|
|
38
40
|
_nodePoseTracker;
|
|
41
|
+
_motionModel;
|
|
42
|
+
_angleLimitRoot;
|
|
43
|
+
_angleLimitTip;
|
|
44
|
+
_constraintVelocityHistoryRetention;
|
|
45
|
+
_preserveInitialCollisionPenetration;
|
|
46
|
+
_initialCollisionPenetrationReleaseTime;
|
|
47
|
+
_initialCollisionPenetrationElapsed;
|
|
48
|
+
_initialCollisionPenetration;
|
|
39
49
|
constructor(chain, options){
|
|
40
50
|
this._chain = chain;
|
|
41
51
|
this._iterations = options?.iterations ?? 5;
|
|
@@ -58,7 +68,16 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
58
68
|
this._smoothedSphereCenters = new WeakMap();
|
|
59
69
|
this._smoothedCapsuleEndpoints = new WeakMap();
|
|
60
70
|
this._smoothedPlaneData = new WeakMap();
|
|
71
|
+
this._smoothedBoxData = new WeakMap();
|
|
61
72
|
this._nodePoseTracker = new SpringNodePoseTracker();
|
|
73
|
+
this._motionModel = options?.motionModel ?? 'kawaii';
|
|
74
|
+
this._angleLimitRoot = Math.max(0, options?.angleLimitRoot ?? 0);
|
|
75
|
+
this._angleLimitTip = Math.max(0, options?.angleLimitTip ?? this._angleLimitRoot);
|
|
76
|
+
this._constraintVelocityHistoryRetention = Math.max(0, Math.min(1, options?.constraintVelocityHistoryRetention ?? 0.35));
|
|
77
|
+
this._preserveInitialCollisionPenetration = options?.preserveInitialCollisionPenetration ?? this._motionModel === 'kawaii';
|
|
78
|
+
this._initialCollisionPenetrationReleaseTime = Math.max(0, options?.initialCollisionPenetrationReleaseTime ?? DEFAULT_INITIAL_COLLISION_PENETRATION_RELEASE_TIME);
|
|
79
|
+
this._initialCollisionPenetrationElapsed = 0;
|
|
80
|
+
this._initialCollisionPenetration = new WeakMap();
|
|
62
81
|
}
|
|
63
82
|
/**
|
|
64
83
|
* Updates the physics simulation
|
|
@@ -76,10 +95,10 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
76
95
|
}
|
|
77
96
|
this._timeAccumulator = Math.max(0, this._timeAccumulator - stepCount * FIXED_SIMULATION_TIME_STEP);
|
|
78
97
|
for(let i = 0; i < stepCount; i++){
|
|
79
|
-
this.simulateStep(FIXED_SIMULATION_TIME_STEP, i === 0 ? frameDt : 0);
|
|
98
|
+
this.simulateStep(FIXED_SIMULATION_TIME_STEP, i === 0 ? frameDt : 0, i, stepCount);
|
|
80
99
|
}
|
|
81
100
|
}
|
|
82
|
-
simulateStep(dt, inputDeltaTime) {
|
|
101
|
+
simulateStep(dt, inputDeltaTime, stepIndex, stepCount) {
|
|
83
102
|
// Step 1: Save all particle positions before updating
|
|
84
103
|
if (this._enableInertialForces) {
|
|
85
104
|
for (const p of this._chain.particles){
|
|
@@ -87,7 +106,8 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
87
106
|
}
|
|
88
107
|
}
|
|
89
108
|
// Step 2: Update fixed particles from their scene nodes
|
|
90
|
-
|
|
109
|
+
const substepBlend = 1 / Math.max(1, stepCount - stepIndex);
|
|
110
|
+
this.updateFixedParticles(inputDeltaTime, substepBlend);
|
|
91
111
|
// Step 3: Calculate global rotation parameters
|
|
92
112
|
let rotationCenter = null;
|
|
93
113
|
let angularVelocity = null;
|
|
@@ -125,8 +145,13 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
125
145
|
constraint.lambda = 0;
|
|
126
146
|
}
|
|
127
147
|
}
|
|
148
|
+
if (this._motionModel === 'kawaii') {
|
|
149
|
+
this.solvePosePreservation(1, true);
|
|
150
|
+
}
|
|
128
151
|
for(let iter = 0; iter < this._iterations; iter++){
|
|
129
|
-
|
|
152
|
+
const reverse = this._motionModel === 'kawaii' && !!(iter & 1);
|
|
153
|
+
for(let constraintIndex = 0; constraintIndex < this._chain.constraints.length; constraintIndex++){
|
|
154
|
+
const constraint = this._chain.constraints[reverse ? this._chain.constraints.length - 1 - constraintIndex : constraintIndex];
|
|
130
155
|
if (this._solver === 'xpbd') {
|
|
131
156
|
this.solveConstraintXPBD(constraint, dt);
|
|
132
157
|
} else {
|
|
@@ -135,15 +160,56 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
135
160
|
}
|
|
136
161
|
// Pull particles back toward the animated pose to preserve hair silhouette.
|
|
137
162
|
// Normalize follow strength across solver iterations so tuning stays intuitive.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
163
|
+
if (this._motionModel === 'legacy') {
|
|
164
|
+
this.solvePosePreservation(this._iterations, false);
|
|
165
|
+
}
|
|
166
|
+
if (this._motionModel === 'legacy') {
|
|
167
|
+
this.solveCollisions(inputDeltaTime);
|
|
168
|
+
}
|
|
141
169
|
}
|
|
170
|
+
if (this._motionModel === 'kawaii') {
|
|
171
|
+
this.solveCollisions(inputDeltaTime, substepBlend);
|
|
172
|
+
this.solveAngleLimits();
|
|
173
|
+
if (this._solver === 'xpbd') {
|
|
174
|
+
this.solveCollisions(0, 0);
|
|
175
|
+
for (const constraint of this._chain.constraints){
|
|
176
|
+
constraint.lambda = 0;
|
|
177
|
+
}
|
|
178
|
+
const closureIterations = Math.min(16, Math.max(4, this._iterations));
|
|
179
|
+
for(let iteration = 0; iteration < closureIterations; iteration++){
|
|
180
|
+
const reverse = !!(iteration & 1);
|
|
181
|
+
for(let constraintIndex = 0; constraintIndex < this._chain.constraints.length; constraintIndex++){
|
|
182
|
+
const constraint = this._chain.constraints[reverse ? this._chain.constraints.length - 1 - constraintIndex : constraintIndex];
|
|
183
|
+
this.solveConstraintXPBD(constraint, dt);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (this._colliders.some((collider)=>collider.enabled)) {
|
|
187
|
+
for (const constraint of this._chain.constraints){
|
|
188
|
+
constraint.lambda = 0;
|
|
189
|
+
}
|
|
190
|
+
const contactClosureIterations = Math.min(4, closureIterations);
|
|
191
|
+
for(let iteration = 0; iteration < contactClosureIterations; iteration++){
|
|
192
|
+
const reverse = !!(iteration & 1);
|
|
193
|
+
for(let constraintIndex = 0; constraintIndex < this._chain.constraints.length; constraintIndex++){
|
|
194
|
+
const constraint = this._chain.constraints[reverse ? this._chain.constraints.length - 1 - constraintIndex : constraintIndex];
|
|
195
|
+
this.solveConstraintXPBD(constraint, dt);
|
|
196
|
+
}
|
|
197
|
+
this.solveCollisions(0, 0);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
for (const constraint of this._chain.constraints){
|
|
202
|
+
this.solveConstraint(constraint);
|
|
203
|
+
}
|
|
204
|
+
this.solveCollisions(0, 0);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
this.advanceInitialCollisionPenetrationRelease(dt);
|
|
142
208
|
}
|
|
143
209
|
/**
|
|
144
210
|
* Updates fixed particles to match their scene node positions
|
|
145
|
-
*/ updateFixedParticles(deltaTime) {
|
|
146
|
-
const blend = this.getTemporalBlendFactor(deltaTime, DEFAULT_PARTICLE_TARGET_SMOOTHING_TIME);
|
|
211
|
+
*/ updateFixedParticles(deltaTime, substepBlend) {
|
|
212
|
+
const blend = this._motionModel === 'kawaii' ? substepBlend : this.getTemporalBlendFactor(deltaTime, DEFAULT_PARTICLE_TARGET_SMOOTHING_TIME);
|
|
147
213
|
for (const particle of this._chain.particles){
|
|
148
214
|
const sourceNode = particle.anchorNode ?? particle.node;
|
|
149
215
|
if (!sourceNode) {
|
|
@@ -172,35 +238,46 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
172
238
|
/**
|
|
173
239
|
* Solves pose preservation (long-range attachment to animated pose).
|
|
174
240
|
* This keeps strands close to authored shape while preserving dynamic movement.
|
|
175
|
-
*/ solvePosePreservation(totalIterations) {
|
|
241
|
+
*/ solvePosePreservation(totalIterations, parentRelative) {
|
|
176
242
|
if (this._poseFollowRoot <= 0 && this._poseFollowTip <= 0) {
|
|
177
243
|
return;
|
|
178
244
|
}
|
|
179
|
-
const
|
|
245
|
+
const topology = getSpringPoseTopology(this._chain.particles);
|
|
180
246
|
for(let i = 0; i < this._chain.particles.length; i++){
|
|
181
247
|
const particle = this._chain.particles[i];
|
|
182
248
|
if (particle.fixed) {
|
|
183
249
|
continue;
|
|
184
250
|
}
|
|
185
|
-
const t = Math.pow(i
|
|
251
|
+
const t = Math.pow(topology[i].normalizedDistance, this._poseFollowExponent);
|
|
186
252
|
const particlePoseFollow = this.lerp(this._poseFollowRoot, this._poseFollowTip, t);
|
|
187
253
|
// Convert user-facing per-frame follow into per-iteration follow:
|
|
188
254
|
// effective = 1 - (1 - follow)^iterations
|
|
189
|
-
const iterationFollow =
|
|
190
|
-
const
|
|
255
|
+
const iterationFollow = getIterationStrength(particlePoseFollow, totalIterations);
|
|
256
|
+
const poseTarget = parentRelative ? getKawaiiPoseTarget(particle, topology[i]) : particle.animPosition;
|
|
257
|
+
const toAnim = Vector3.sub(poseTarget, particle.position, new Vector3());
|
|
191
258
|
const correction = Vector3.scale(toAnim, iterationFollow, new Vector3());
|
|
192
259
|
Vector3.add(particle.position, correction, particle.position);
|
|
193
260
|
const particleMaxPoseOffset = this.lerp(this._maxPoseOffsetRoot, this._maxPoseOffsetTip, t);
|
|
194
261
|
if (particleMaxPoseOffset > 0) {
|
|
195
|
-
const offset = Vector3.sub(particle.position,
|
|
262
|
+
const offset = Vector3.sub(particle.position, poseTarget, new Vector3());
|
|
196
263
|
const offsetLen = offset.magnitude;
|
|
197
264
|
if (offsetLen > particleMaxPoseOffset && offsetLen > 1e-6) {
|
|
198
265
|
offset.scaleBy(particleMaxPoseOffset / offsetLen);
|
|
199
|
-
Vector3.add(
|
|
266
|
+
Vector3.add(poseTarget, offset, particle.position);
|
|
200
267
|
}
|
|
201
268
|
}
|
|
202
269
|
}
|
|
203
270
|
}
|
|
271
|
+
solveAngleLimits() {
|
|
272
|
+
if (this._angleLimitRoot <= 0 && this._angleLimitTip <= 0) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
const particles = this._chain.particles;
|
|
276
|
+
for(let i = 1; i < particles.length; i++){
|
|
277
|
+
const limit = interpolateSpringValue(this._angleLimitRoot, this._angleLimitTip, this._poseFollowExponent, i, particles.length);
|
|
278
|
+
solveAngleLimit(particles[i - 1], particles[i], limit, this._solver === 'xpbd');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
204
281
|
lerp(a, b, t) {
|
|
205
282
|
return a + (b - a) * t;
|
|
206
283
|
}
|
|
@@ -388,11 +465,19 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
388
465
|
const n = Vector3.scale(delta, 1.0 / currentLength, new Vector3());
|
|
389
466
|
if (!pA.fixed) {
|
|
390
467
|
// deltaX_a = -w_a * deltaLambda * n
|
|
391
|
-
|
|
468
|
+
const correction = Vector3.scale(n, -wA * deltaLambda, new Vector3());
|
|
469
|
+
Vector3.add(pA.position, correction, pA.position);
|
|
470
|
+
if (this._motionModel === 'kawaii') {
|
|
471
|
+
Vector3.add(pA.prevPosition, Vector3.scale(correction, this._constraintVelocityHistoryRetention, new Vector3()), pA.prevPosition);
|
|
472
|
+
}
|
|
392
473
|
}
|
|
393
474
|
if (!pB.fixed) {
|
|
394
475
|
// deltaX_b = +w_b * deltaLambda * n
|
|
395
|
-
|
|
476
|
+
const correction = Vector3.scale(n, wB * deltaLambda, new Vector3());
|
|
477
|
+
Vector3.add(pB.position, correction, pB.position);
|
|
478
|
+
if (this._motionModel === 'kawaii') {
|
|
479
|
+
Vector3.add(pB.prevPosition, Vector3.scale(correction, this._constraintVelocityHistoryRetention, new Vector3()), pB.prevPosition);
|
|
480
|
+
}
|
|
396
481
|
}
|
|
397
482
|
}
|
|
398
483
|
/**
|
|
@@ -400,6 +485,10 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
400
485
|
*/ solveConstraint(constraint) {
|
|
401
486
|
const pA = this._chain.particles[constraint.particleA];
|
|
402
487
|
const pB = this._chain.particles[constraint.particleB];
|
|
488
|
+
if (this._motionModel === 'kawaii') {
|
|
489
|
+
solveDistanceConstraint(pA, pB, constraint.restLength, constraint.stiffness);
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
403
492
|
// Calculate current distance
|
|
404
493
|
const delta = Vector3.sub(pB.position, pA.position, new Vector3());
|
|
405
494
|
const currentLength = delta.magnitude;
|
|
@@ -419,12 +508,13 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
419
508
|
}
|
|
420
509
|
/**
|
|
421
510
|
* Solves collisions for all particles
|
|
422
|
-
*/ solveCollisions(deltaTime) {
|
|
511
|
+
*/ solveCollisions(deltaTime, blendOverride) {
|
|
423
512
|
// Update dynamic colliders from their nodes
|
|
424
|
-
const blend = this.getTemporalBlendFactor(deltaTime, DEFAULT_COLLIDER_SMOOTHING_TIME);
|
|
513
|
+
const blend = blendOverride ?? this.getTemporalBlendFactor(deltaTime, DEFAULT_COLLIDER_SMOOTHING_TIME);
|
|
425
514
|
const spheres = [];
|
|
426
515
|
const capsules = [];
|
|
427
516
|
const planes = [];
|
|
517
|
+
const boxes = [];
|
|
428
518
|
for (const collider of this._colliders){
|
|
429
519
|
if (collider.node) {
|
|
430
520
|
updateColliderFromNode(collider);
|
|
@@ -473,6 +563,18 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
473
563
|
});
|
|
474
564
|
break;
|
|
475
565
|
}
|
|
566
|
+
case 'box':
|
|
567
|
+
{
|
|
568
|
+
const source = collider;
|
|
569
|
+
boxes.push({
|
|
570
|
+
particleCollider: source,
|
|
571
|
+
collider: {
|
|
572
|
+
...source,
|
|
573
|
+
...this.getSmoothedBoxData(source, blend)
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
476
578
|
}
|
|
477
579
|
}
|
|
478
580
|
// Check each particle against all colliders
|
|
@@ -481,13 +583,32 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
481
583
|
continue; // Skip fixed particles
|
|
482
584
|
}
|
|
483
585
|
for (const collider of spheres){
|
|
484
|
-
|
|
586
|
+
if (this._motionModel === 'kawaii') {
|
|
587
|
+
resolveInelasticCollision(particle, collider.collider, resolveSphereCollision, this.getInitialCollisionPenetration(particle, collider.particleCollider, collider.collider, resolveSphereCollision));
|
|
588
|
+
} else {
|
|
589
|
+
resolveSphereCollision(particle.position, collider.collider, particle.collisionRadius);
|
|
590
|
+
}
|
|
485
591
|
}
|
|
486
592
|
for (const collider of capsules){
|
|
487
|
-
|
|
593
|
+
if (this._motionModel === 'kawaii') {
|
|
594
|
+
resolveInelasticCollision(particle, collider.collider, resolveCapsuleCollision, this.getInitialCollisionPenetration(particle, collider.particleCollider, collider.collider, resolveCapsuleCollision));
|
|
595
|
+
} else {
|
|
596
|
+
resolveCapsuleCollision(particle.position, collider.collider, particle.collisionRadius);
|
|
597
|
+
}
|
|
488
598
|
}
|
|
489
599
|
for (const collider of planes){
|
|
490
|
-
|
|
600
|
+
if (this._motionModel === 'kawaii') {
|
|
601
|
+
resolveInelasticCollision(particle, collider.collider, resolvePlaneCollision, this.getInitialCollisionPenetration(particle, collider.particleCollider, collider.collider, resolvePlaneCollision));
|
|
602
|
+
} else {
|
|
603
|
+
resolvePlaneCollision(particle.position, collider.collider, particle.collisionRadius);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
for (const collider of boxes){
|
|
607
|
+
if (this._motionModel === 'kawaii') {
|
|
608
|
+
resolveInelasticCollision(particle, collider.collider, resolveBoxCollision, this.getInitialCollisionPenetration(particle, collider.particleCollider, collider.collider, resolveBoxCollision));
|
|
609
|
+
} else {
|
|
610
|
+
resolveBoxCollision(particle.position, collider.collider, particle.collisionRadius);
|
|
611
|
+
}
|
|
491
612
|
}
|
|
492
613
|
}
|
|
493
614
|
}
|
|
@@ -561,6 +682,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
561
682
|
this._smoothedSphereCenters = new WeakMap();
|
|
562
683
|
this._smoothedCapsuleEndpoints = new WeakMap();
|
|
563
684
|
this._smoothedPlaneData = new WeakMap();
|
|
685
|
+
this._smoothedBoxData = new WeakMap();
|
|
686
|
+
this._initialCollisionPenetrationElapsed = 0;
|
|
687
|
+
this._initialCollisionPenetration = new WeakMap();
|
|
564
688
|
}
|
|
565
689
|
/**
|
|
566
690
|
* Gets the spring chain
|
|
@@ -630,6 +754,57 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
630
754
|
}
|
|
631
755
|
}
|
|
632
756
|
}
|
|
757
|
+
get motionModel() {
|
|
758
|
+
return this._motionModel;
|
|
759
|
+
}
|
|
760
|
+
set motionModel(value) {
|
|
761
|
+
if (value !== 'legacy' && value !== 'kawaii') {
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
if (this._motionModel !== value) {
|
|
765
|
+
this._motionModel = value;
|
|
766
|
+
this.reset();
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
get angleLimitRoot() {
|
|
770
|
+
return this._angleLimitRoot;
|
|
771
|
+
}
|
|
772
|
+
set angleLimitRoot(value) {
|
|
773
|
+
this._angleLimitRoot = Math.max(0, Number(value) || 0);
|
|
774
|
+
}
|
|
775
|
+
get angleLimitTip() {
|
|
776
|
+
return this._angleLimitTip;
|
|
777
|
+
}
|
|
778
|
+
set angleLimitTip(value) {
|
|
779
|
+
this._angleLimitTip = Math.max(0, Number(value) || 0);
|
|
780
|
+
}
|
|
781
|
+
get constraintVelocityHistoryRetention() {
|
|
782
|
+
return this._constraintVelocityHistoryRetention;
|
|
783
|
+
}
|
|
784
|
+
set constraintVelocityHistoryRetention(value) {
|
|
785
|
+
this._constraintVelocityHistoryRetention = Math.max(0, Math.min(1, Number(value) || 0));
|
|
786
|
+
}
|
|
787
|
+
get preserveInitialCollisionPenetration() {
|
|
788
|
+
return this._preserveInitialCollisionPenetration;
|
|
789
|
+
}
|
|
790
|
+
set preserveInitialCollisionPenetration(value) {
|
|
791
|
+
if (this._preserveInitialCollisionPenetration !== value) {
|
|
792
|
+
this._preserveInitialCollisionPenetration = value;
|
|
793
|
+
this._initialCollisionPenetrationElapsed = 0;
|
|
794
|
+
this._initialCollisionPenetration = new WeakMap();
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
get initialCollisionPenetrationReleaseTime() {
|
|
798
|
+
return this._initialCollisionPenetrationReleaseTime;
|
|
799
|
+
}
|
|
800
|
+
set initialCollisionPenetrationReleaseTime(value) {
|
|
801
|
+
const duration = Math.max(0, Number(value) || 0);
|
|
802
|
+
if (this._initialCollisionPenetrationReleaseTime !== duration) {
|
|
803
|
+
this._initialCollisionPenetrationReleaseTime = duration;
|
|
804
|
+
this._initialCollisionPenetrationElapsed = 0;
|
|
805
|
+
this._initialCollisionPenetration = new WeakMap();
|
|
806
|
+
}
|
|
807
|
+
}
|
|
633
808
|
/**
|
|
634
809
|
* Gets pose preservation strength [0-1]
|
|
635
810
|
*/ get poseFollow() {
|
|
@@ -699,6 +874,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
699
874
|
this._smoothedSphereCenters = new WeakMap();
|
|
700
875
|
this._smoothedCapsuleEndpoints = new WeakMap();
|
|
701
876
|
this._smoothedPlaneData = new WeakMap();
|
|
877
|
+
this._smoothedBoxData = new WeakMap();
|
|
878
|
+
this._initialCollisionPenetrationElapsed = 0;
|
|
879
|
+
this._initialCollisionPenetration = new WeakMap();
|
|
702
880
|
}
|
|
703
881
|
/**
|
|
704
882
|
* Removes a collider from the system
|
|
@@ -709,6 +887,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
709
887
|
this._smoothedSphereCenters = new WeakMap();
|
|
710
888
|
this._smoothedCapsuleEndpoints = new WeakMap();
|
|
711
889
|
this._smoothedPlaneData = new WeakMap();
|
|
890
|
+
this._smoothedBoxData = new WeakMap();
|
|
891
|
+
this._initialCollisionPenetrationElapsed = 0;
|
|
892
|
+
this._initialCollisionPenetration = new WeakMap();
|
|
712
893
|
return true;
|
|
713
894
|
}
|
|
714
895
|
return false;
|
|
@@ -720,12 +901,37 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
720
901
|
this._smoothedSphereCenters = new WeakMap();
|
|
721
902
|
this._smoothedCapsuleEndpoints = new WeakMap();
|
|
722
903
|
this._smoothedPlaneData = new WeakMap();
|
|
904
|
+
this._smoothedBoxData = new WeakMap();
|
|
905
|
+
this._initialCollisionPenetrationElapsed = 0;
|
|
906
|
+
this._initialCollisionPenetration = new WeakMap();
|
|
723
907
|
}
|
|
724
908
|
/**
|
|
725
909
|
* Gets all colliders
|
|
726
910
|
*/ get colliders() {
|
|
727
911
|
return this._colliders;
|
|
728
912
|
}
|
|
913
|
+
getInitialCollisionPenetration(particle, sourceCollider, collider, resolveCollision) {
|
|
914
|
+
if (!this._preserveInitialCollisionPenetration) {
|
|
915
|
+
return 0;
|
|
916
|
+
}
|
|
917
|
+
let particlePenetrations = this._initialCollisionPenetration.get(particle);
|
|
918
|
+
if (!particlePenetrations) {
|
|
919
|
+
particlePenetrations = new WeakMap();
|
|
920
|
+
this._initialCollisionPenetration.set(particle, particlePenetrations);
|
|
921
|
+
}
|
|
922
|
+
let penetration = particlePenetrations.get(sourceCollider);
|
|
923
|
+
if (penetration === undefined) {
|
|
924
|
+
penetration = measureCollisionPenetration(particle.animPosition, collider, resolveCollision, particle.collisionRadius) + INITIAL_COLLISION_PENETRATION_SLOP;
|
|
925
|
+
particlePenetrations.set(sourceCollider, penetration);
|
|
926
|
+
}
|
|
927
|
+
return getReleasedCollisionPenetration(penetration, this._initialCollisionPenetrationElapsed, this._initialCollisionPenetrationReleaseTime);
|
|
928
|
+
}
|
|
929
|
+
advanceInitialCollisionPenetrationRelease(deltaTime) {
|
|
930
|
+
if (!this._preserveInitialCollisionPenetration) {
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
this._initialCollisionPenetrationElapsed = Math.min(this._initialCollisionPenetrationReleaseTime, this._initialCollisionPenetrationElapsed + Math.max(0, deltaTime));
|
|
934
|
+
}
|
|
729
935
|
getTemporalBlendFactor(deltaTime, smoothingTime) {
|
|
730
936
|
const dt = Math.min(Math.max(Number(deltaTime) || 0, 0), MAX_ACCUMULATED_SIMULATION_TIME);
|
|
731
937
|
if (smoothingTime <= 0) {
|
|
@@ -798,6 +1004,25 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
|
|
|
798
1004
|
}
|
|
799
1005
|
return cached;
|
|
800
1006
|
}
|
|
1007
|
+
getSmoothedBoxData(collider, blend) {
|
|
1008
|
+
const current = {
|
|
1009
|
+
center: collider.center.clone(),
|
|
1010
|
+
halfExtents: collider.halfExtents.clone(),
|
|
1011
|
+
axes: collider.axes.map((axis)=>axis.clone())
|
|
1012
|
+
};
|
|
1013
|
+
const cached = this._smoothedBoxData.get(collider);
|
|
1014
|
+
if (!cached || blend >= 1) {
|
|
1015
|
+
this._smoothedBoxData.set(collider, current);
|
|
1016
|
+
return current;
|
|
1017
|
+
}
|
|
1018
|
+
Vector3.lerp(cached.center, current.center, blend, cached.center);
|
|
1019
|
+
Vector3.lerp(cached.halfExtents, current.halfExtents, blend, cached.halfExtents);
|
|
1020
|
+
for(let i = 0; i < 3; i++){
|
|
1021
|
+
Vector3.lerp(cached.axes[i], current.axes[i], blend, cached.axes[i]);
|
|
1022
|
+
cached.axes[i].inplaceNormalize();
|
|
1023
|
+
}
|
|
1024
|
+
return cached;
|
|
1025
|
+
}
|
|
801
1026
|
}
|
|
802
1027
|
|
|
803
1028
|
export { SpringSystem };
|